Commit | Line | Data |
---|---|---|
5be27f1e SD |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // | |
3 | // TAS2781 HDA I2C driver | |
4 | // | |
5 | // Copyright 2023 Texas Instruments, Inc. | |
6 | // | |
7 | // Author: Shenghao Ding <shenghao-ding@ti.com> | |
8 | ||
9 | #include <linux/acpi.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/mod_devicetable.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/pm_runtime.h> | |
18 | #include <linux/regmap.h> | |
19 | #include <sound/hda_codec.h> | |
20 | #include <sound/soc.h> | |
21 | #include <sound/tas2781.h> | |
22 | #include <sound/tlv.h> | |
23 | #include <sound/tas2781-tlv.h> | |
24 | ||
25 | #include "hda_local.h" | |
26 | #include "hda_auto_parser.h" | |
27 | #include "hda_component.h" | |
28 | #include "hda_jack.h" | |
29 | #include "hda_generic.h" | |
30 | ||
31 | #define TASDEVICE_SPEAKER_CALIBRATION_SIZE 20 | |
32 | ||
33 | /* No standard control callbacks for SNDRV_CTL_ELEM_IFACE_CARD | |
34 | * Define two controls, one is Volume control callbacks, the other is | |
35 | * flag setting control callbacks. | |
36 | */ | |
37 | ||
38 | /* Volume control callbacks for tas2781 */ | |
39 | #define ACARD_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ | |
40 | xhandler_get, xhandler_put, tlv_array) \ | |
41 | { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = (xname),\ | |
42 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | |
43 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | |
44 | .tlv.p = (tlv_array), \ | |
45 | .info = snd_soc_info_volsw_range, \ | |
46 | .get = xhandler_get, .put = xhandler_put, \ | |
47 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | |
48 | {.reg = xreg, .rreg = xreg, .shift = xshift, \ | |
49 | .rshift = xshift, .min = xmin, .max = xmax, \ | |
50 | .invert = xinvert} } | |
51 | ||
52 | /* Flag control callbacks for tas2781 */ | |
53 | #define ACARD_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ | |
54 | { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, \ | |
55 | .info = snd_ctl_boolean_mono_info, \ | |
56 | .get = xhandler_get, .put = xhandler_put, \ | |
57 | .private_value = xdata } | |
58 | ||
59 | enum calib_data { | |
60 | R0_VAL = 0, | |
61 | INV_R0, | |
62 | R0LOW, | |
63 | POWER, | |
64 | TLIM, | |
65 | CALIB_MAX | |
66 | }; | |
67 | ||
c3ca4458 GK |
68 | #define TAS2563_MAX_CHANNELS 4 |
69 | ||
70 | #define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c) | |
71 | #define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34) | |
72 | #define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40) | |
73 | #define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48) | |
74 | #define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14) | |
75 | #define TAS2563_CAL_N 5 | |
76 | #define TAS2563_CAL_DATA_SIZE 4 | |
77 | #define TAS2563_CAL_CH_SIZE 20 | |
78 | #define TAS2563_CAL_ARRAY_SIZE 80 | |
79 | ||
80 | static unsigned int cal_regs[TAS2563_CAL_N] = { | |
81 | TAS2563_CAL_POWER, TAS2563_CAL_R0, TAS2563_CAL_INVR0, | |
82 | TAS2563_CAL_R0_LOW, TAS2563_CAL_TLIM, | |
83 | }; | |
84 | ||
85 | ||
4e7914eb GK |
86 | struct tas2781_hda { |
87 | struct device *dev; | |
88 | struct tasdevice_priv *priv; | |
89 | struct snd_kcontrol *dsp_prog_ctl; | |
90 | struct snd_kcontrol *dsp_conf_ctl; | |
91 | struct snd_kcontrol *prof_ctl; | |
ae065d0c | 92 | struct snd_kcontrol *snd_ctls[2]; |
4e7914eb GK |
93 | }; |
94 | ||
5be27f1e SD |
95 | static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) |
96 | { | |
97 | struct tasdevice_priv *tas_priv = data; | |
98 | struct acpi_resource_i2c_serialbus *sb; | |
99 | ||
100 | if (i2c_acpi_get_i2c_resource(ares, &sb)) { | |
101 | if (tas_priv->ndev < TASDEVICE_MAX_CHANNELS && | |
c021ca72 | 102 | sb->slave_address != tas_priv->global_addr) { |
5be27f1e SD |
103 | tas_priv->tasdevice[tas_priv->ndev].dev_addr = |
104 | (unsigned int)sb->slave_address; | |
105 | tas_priv->ndev++; | |
106 | } | |
107 | } | |
108 | return 1; | |
109 | } | |
110 | ||
111 | static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) | |
112 | { | |
113 | struct acpi_device *adev; | |
5be27f1e | 114 | LIST_HEAD(resources); |
5be27f1e SD |
115 | int ret; |
116 | ||
117 | adev = acpi_dev_get_first_match_dev(hid, NULL, -1); | |
118 | if (!adev) { | |
119 | dev_err(p->dev, | |
120 | "Failed to find an ACPI device for %s\n", hid); | |
121 | return -ENODEV; | |
122 | } | |
123 | ||
124 | ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p); | |
125 | if (ret < 0) | |
126 | goto err; | |
127 | ||
128 | acpi_dev_free_resource_list(&resources); | |
129 | strscpy(p->dev_name, hid, sizeof(p->dev_name)); | |
5be27f1e SD |
130 | acpi_dev_put(adev); |
131 | ||
5be27f1e SD |
132 | return 0; |
133 | ||
134 | err: | |
135 | dev_err(p->dev, "read acpi error, ret: %d\n", ret); | |
1c80cc05 | 136 | acpi_dev_put(adev); |
5be27f1e SD |
137 | |
138 | return ret; | |
139 | } | |
140 | ||
141 | static void tas2781_hda_playback_hook(struct device *dev, int action) | |
142 | { | |
4e7914eb | 143 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e | 144 | |
4e7914eb | 145 | dev_dbg(tas_hda->dev, "%s: action = %d\n", __func__, action); |
5be27f1e SD |
146 | switch (action) { |
147 | case HDA_GEN_PCM_ACT_OPEN: | |
148 | pm_runtime_get_sync(dev); | |
4e7914eb GK |
149 | mutex_lock(&tas_hda->priv->codec_lock); |
150 | tasdevice_tuning_switch(tas_hda->priv, 0); | |
9fc91a6f | 151 | tas_hda->priv->playback_started = true; |
4e7914eb | 152 | mutex_unlock(&tas_hda->priv->codec_lock); |
5be27f1e SD |
153 | break; |
154 | case HDA_GEN_PCM_ACT_CLOSE: | |
4e7914eb GK |
155 | mutex_lock(&tas_hda->priv->codec_lock); |
156 | tasdevice_tuning_switch(tas_hda->priv, 1); | |
9fc91a6f | 157 | tas_hda->priv->playback_started = false; |
4e7914eb | 158 | mutex_unlock(&tas_hda->priv->codec_lock); |
5be27f1e SD |
159 | |
160 | pm_runtime_mark_last_busy(dev); | |
161 | pm_runtime_put_autosuspend(dev); | |
162 | break; | |
163 | default: | |
5be27f1e SD |
164 | break; |
165 | } | |
166 | } | |
167 | ||
168 | static int tasdevice_info_profile(struct snd_kcontrol *kcontrol, | |
169 | struct snd_ctl_elem_info *uinfo) | |
170 | { | |
171 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
172 | ||
173 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
174 | uinfo->count = 1; | |
175 | uinfo->value.integer.min = 0; | |
176 | uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1; | |
177 | ||
178 | return 0; | |
179 | } | |
180 | ||
181 | static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol, | |
182 | struct snd_ctl_elem_value *ucontrol) | |
183 | { | |
184 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
185 | ||
15bc3066 GK |
186 | mutex_lock(&tas_priv->codec_lock); |
187 | ||
5be27f1e SD |
188 | ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id; |
189 | ||
26c04a8a GK |
190 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", |
191 | __func__, kcontrol->id.name, tas_priv->rcabin.profile_cfg_id); | |
192 | ||
15bc3066 GK |
193 | mutex_unlock(&tas_priv->codec_lock); |
194 | ||
5be27f1e SD |
195 | return 0; |
196 | } | |
197 | ||
5be27f1e SD |
198 | static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol, |
199 | struct snd_ctl_elem_value *ucontrol) | |
200 | { | |
201 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
202 | int nr_profile = ucontrol->value.integer.value[0]; | |
203 | int max = tas_priv->rcabin.ncfgs - 1; | |
204 | int val, ret = 0; | |
205 | ||
da42bcb3 | 206 | val = clamp(nr_profile, 0, max); |
5be27f1e | 207 | |
15bc3066 GK |
208 | mutex_lock(&tas_priv->codec_lock); |
209 | ||
26c04a8a GK |
210 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", |
211 | __func__, kcontrol->id.name, | |
212 | tas_priv->rcabin.profile_cfg_id, val); | |
213 | ||
5be27f1e SD |
214 | if (tas_priv->rcabin.profile_cfg_id != val) { |
215 | tas_priv->rcabin.profile_cfg_id = val; | |
216 | ret = 1; | |
217 | } | |
218 | ||
15bc3066 GK |
219 | mutex_unlock(&tas_priv->codec_lock); |
220 | ||
5be27f1e SD |
221 | return ret; |
222 | } | |
223 | ||
224 | static int tasdevice_info_programs(struct snd_kcontrol *kcontrol, | |
225 | struct snd_ctl_elem_info *uinfo) | |
226 | { | |
227 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
228 | struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
229 | ||
230 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
231 | uinfo->count = 1; | |
232 | uinfo->value.integer.min = 0; | |
233 | uinfo->value.integer.max = tas_fw->nr_programs - 1; | |
234 | ||
235 | return 0; | |
236 | } | |
237 | ||
238 | static int tasdevice_info_config(struct snd_kcontrol *kcontrol, | |
239 | struct snd_ctl_elem_info *uinfo) | |
240 | { | |
241 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
242 | struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
243 | ||
244 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | |
245 | uinfo->count = 1; | |
246 | uinfo->value.integer.min = 0; | |
247 | uinfo->value.integer.max = tas_fw->nr_configurations - 1; | |
248 | ||
249 | return 0; | |
250 | } | |
251 | ||
252 | static int tasdevice_program_get(struct snd_kcontrol *kcontrol, | |
253 | struct snd_ctl_elem_value *ucontrol) | |
254 | { | |
255 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
256 | ||
15bc3066 GK |
257 | mutex_lock(&tas_priv->codec_lock); |
258 | ||
5be27f1e SD |
259 | ucontrol->value.integer.value[0] = tas_priv->cur_prog; |
260 | ||
26c04a8a GK |
261 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", |
262 | __func__, kcontrol->id.name, tas_priv->cur_prog); | |
263 | ||
15bc3066 GK |
264 | mutex_unlock(&tas_priv->codec_lock); |
265 | ||
5be27f1e SD |
266 | return 0; |
267 | } | |
268 | ||
269 | static int tasdevice_program_put(struct snd_kcontrol *kcontrol, | |
270 | struct snd_ctl_elem_value *ucontrol) | |
271 | { | |
272 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
273 | struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
274 | int nr_program = ucontrol->value.integer.value[0]; | |
275 | int max = tas_fw->nr_programs - 1; | |
276 | int val, ret = 0; | |
277 | ||
da42bcb3 | 278 | val = clamp(nr_program, 0, max); |
5be27f1e | 279 | |
15bc3066 GK |
280 | mutex_lock(&tas_priv->codec_lock); |
281 | ||
26c04a8a GK |
282 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", |
283 | __func__, kcontrol->id.name, tas_priv->cur_prog, val); | |
284 | ||
5be27f1e SD |
285 | if (tas_priv->cur_prog != val) { |
286 | tas_priv->cur_prog = val; | |
287 | ret = 1; | |
288 | } | |
289 | ||
15bc3066 GK |
290 | mutex_unlock(&tas_priv->codec_lock); |
291 | ||
5be27f1e SD |
292 | return ret; |
293 | } | |
294 | ||
295 | static int tasdevice_config_get(struct snd_kcontrol *kcontrol, | |
296 | struct snd_ctl_elem_value *ucontrol) | |
297 | { | |
298 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
299 | ||
15bc3066 GK |
300 | mutex_lock(&tas_priv->codec_lock); |
301 | ||
5be27f1e SD |
302 | ucontrol->value.integer.value[0] = tas_priv->cur_conf; |
303 | ||
26c04a8a GK |
304 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", |
305 | __func__, kcontrol->id.name, tas_priv->cur_conf); | |
306 | ||
15bc3066 GK |
307 | mutex_unlock(&tas_priv->codec_lock); |
308 | ||
5be27f1e SD |
309 | return 0; |
310 | } | |
311 | ||
312 | static int tasdevice_config_put(struct snd_kcontrol *kcontrol, | |
313 | struct snd_ctl_elem_value *ucontrol) | |
314 | { | |
315 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
316 | struct tasdevice_fw *tas_fw = tas_priv->fmw; | |
317 | int nr_config = ucontrol->value.integer.value[0]; | |
318 | int max = tas_fw->nr_configurations - 1; | |
319 | int val, ret = 0; | |
320 | ||
da42bcb3 | 321 | val = clamp(nr_config, 0, max); |
5be27f1e | 322 | |
15bc3066 GK |
323 | mutex_lock(&tas_priv->codec_lock); |
324 | ||
26c04a8a GK |
325 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", |
326 | __func__, kcontrol->id.name, tas_priv->cur_conf, val); | |
327 | ||
5be27f1e SD |
328 | if (tas_priv->cur_conf != val) { |
329 | tas_priv->cur_conf = val; | |
330 | ret = 1; | |
331 | } | |
332 | ||
15bc3066 GK |
333 | mutex_unlock(&tas_priv->codec_lock); |
334 | ||
5be27f1e SD |
335 | return ret; |
336 | } | |
337 | ||
5be27f1e SD |
338 | static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol, |
339 | struct snd_ctl_elem_value *ucontrol) | |
340 | { | |
341 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
342 | struct soc_mixer_control *mc = | |
343 | (struct soc_mixer_control *)kcontrol->private_value; | |
15bc3066 | 344 | int ret; |
5be27f1e | 345 | |
15bc3066 GK |
346 | mutex_lock(&tas_priv->codec_lock); |
347 | ||
348 | ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc); | |
349 | ||
26c04a8a GK |
350 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %ld\n", |
351 | __func__, kcontrol->id.name, ucontrol->value.integer.value[0]); | |
352 | ||
15bc3066 GK |
353 | mutex_unlock(&tas_priv->codec_lock); |
354 | ||
355 | return ret; | |
5be27f1e SD |
356 | } |
357 | ||
5be27f1e SD |
358 | static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol, |
359 | struct snd_ctl_elem_value *ucontrol) | |
360 | { | |
361 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
362 | struct soc_mixer_control *mc = | |
363 | (struct soc_mixer_control *)kcontrol->private_value; | |
15bc3066 GK |
364 | int ret; |
365 | ||
366 | mutex_lock(&tas_priv->codec_lock); | |
5be27f1e | 367 | |
26c04a8a GK |
368 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: -> %ld\n", |
369 | __func__, kcontrol->id.name, ucontrol->value.integer.value[0]); | |
370 | ||
5be27f1e | 371 | /* The check of the given value is in tasdevice_amp_putvol. */ |
15bc3066 GK |
372 | ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc); |
373 | ||
374 | mutex_unlock(&tas_priv->codec_lock); | |
375 | ||
376 | return ret; | |
5be27f1e SD |
377 | } |
378 | ||
379 | static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol, | |
380 | struct snd_ctl_elem_value *ucontrol) | |
381 | { | |
382 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
383 | ||
15bc3066 GK |
384 | mutex_lock(&tas_priv->codec_lock); |
385 | ||
5be27f1e | 386 | ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status; |
26c04a8a GK |
387 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", |
388 | __func__, kcontrol->id.name, tas_priv->force_fwload_status); | |
5be27f1e | 389 | |
15bc3066 GK |
390 | mutex_unlock(&tas_priv->codec_lock); |
391 | ||
5be27f1e SD |
392 | return 0; |
393 | } | |
394 | ||
395 | static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, | |
396 | struct snd_ctl_elem_value *ucontrol) | |
397 | { | |
398 | struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); | |
399 | bool change, val = (bool)ucontrol->value.integer.value[0]; | |
400 | ||
15bc3066 GK |
401 | mutex_lock(&tas_priv->codec_lock); |
402 | ||
26c04a8a GK |
403 | dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", |
404 | __func__, kcontrol->id.name, | |
405 | tas_priv->force_fwload_status, val); | |
406 | ||
5be27f1e SD |
407 | if (tas_priv->force_fwload_status == val) |
408 | change = false; | |
409 | else { | |
410 | change = true; | |
411 | tas_priv->force_fwload_status = val; | |
412 | } | |
5be27f1e | 413 | |
15bc3066 GK |
414 | mutex_unlock(&tas_priv->codec_lock); |
415 | ||
5be27f1e SD |
416 | return change; |
417 | } | |
418 | ||
419 | static const struct snd_kcontrol_new tas2781_snd_controls[] = { | |
420 | ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL, | |
421 | 1, 0, 20, 0, tas2781_amp_getvol, | |
422 | tas2781_amp_putvol, amp_vol_tlv), | |
5be27f1e SD |
423 | ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, |
424 | tas2781_force_fwload_get, tas2781_force_fwload_put), | |
425 | }; | |
426 | ||
427 | static const struct snd_kcontrol_new tas2781_prof_ctrl = { | |
428 | .name = "Speaker Profile Id", | |
429 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, | |
430 | .info = tasdevice_info_profile, | |
431 | .get = tasdevice_get_profile_id, | |
432 | .put = tasdevice_set_profile_id, | |
433 | }; | |
434 | ||
435 | static const struct snd_kcontrol_new tas2781_dsp_prog_ctrl = { | |
436 | .name = "Speaker Program Id", | |
437 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, | |
438 | .info = tasdevice_info_programs, | |
439 | .get = tasdevice_program_get, | |
440 | .put = tasdevice_program_put, | |
441 | }; | |
442 | ||
443 | static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = { | |
444 | .name = "Speaker Config Id", | |
445 | .iface = SNDRV_CTL_ELEM_IFACE_CARD, | |
446 | .info = tasdevice_info_config, | |
447 | .get = tasdevice_config_get, | |
448 | .put = tasdevice_config_put, | |
449 | }; | |
450 | ||
c3ca4458 GK |
451 | static void tas2563_apply_calib(struct tasdevice_priv *tas_priv) |
452 | { | |
c3ca4458 | 453 | int offset = 0; |
dcaca1b5 | 454 | __be32 data; |
c3ca4458 GK |
455 | int ret; |
456 | ||
457 | for (int i = 0; i < tas_priv->ndev; i++) { | |
458 | for (int j = 0; j < TAS2563_CAL_N; ++j) { | |
459 | data = cpu_to_be32( | |
460 | *(uint32_t *)&tas_priv->cali_data.data[offset]); | |
461 | ret = tasdevice_dev_bulk_write(tas_priv, i, cal_regs[j], | |
462 | (unsigned char *)&data, TAS2563_CAL_DATA_SIZE); | |
463 | if (ret) | |
464 | dev_err(tas_priv->dev, | |
465 | "Error writing calib regs\n"); | |
466 | offset += TAS2563_CAL_DATA_SIZE; | |
467 | } | |
468 | } | |
469 | } | |
470 | ||
471 | static int tas2563_save_calibration(struct tasdevice_priv *tas_priv) | |
472 | { | |
473 | static efi_guid_t efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, | |
474 | 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); | |
475 | ||
476 | static efi_char16_t *efi_vars[TAS2563_MAX_CHANNELS][TAS2563_CAL_N] = { | |
477 | { L"Power_1", L"R0_1", L"InvR0_1", L"R0_Low_1", L"TLim_1" }, | |
478 | { L"Power_2", L"R0_2", L"InvR0_2", L"R0_Low_2", L"TLim_2" }, | |
479 | { L"Power_3", L"R0_3", L"InvR0_3", L"R0_Low_3", L"TLim_3" }, | |
480 | { L"Power_4", L"R0_4", L"InvR0_4", L"R0_Low_4", L"TLim_4" }, | |
481 | }; | |
482 | ||
483 | unsigned long max_size = TAS2563_CAL_DATA_SIZE; | |
484 | unsigned int offset = 0; | |
485 | efi_status_t status; | |
486 | unsigned int attr; | |
487 | ||
488 | tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, | |
489 | TAS2563_CAL_ARRAY_SIZE, GFP_KERNEL); | |
490 | if (!tas_priv->cali_data.data) | |
491 | return -ENOMEM; | |
492 | ||
493 | for (int i = 0; i < tas_priv->ndev; ++i) { | |
494 | for (int j = 0; j < TAS2563_CAL_N; ++j) { | |
495 | status = efi.get_variable(efi_vars[i][j], | |
496 | &efi_guid, &attr, &max_size, | |
497 | &tas_priv->cali_data.data[offset]); | |
498 | if (status != EFI_SUCCESS || | |
499 | max_size != TAS2563_CAL_DATA_SIZE) { | |
500 | dev_warn(tas_priv->dev, | |
501 | "Calibration data read failed %ld\n", status); | |
502 | return -EINVAL; | |
503 | } | |
504 | offset += TAS2563_CAL_DATA_SIZE; | |
505 | } | |
506 | } | |
507 | ||
508 | tas_priv->cali_data.total_sz = offset; | |
509 | tasdevice_apply_calibration(tas_priv); | |
510 | ||
511 | return 0; | |
512 | } | |
513 | ||
5be27f1e SD |
514 | static void tas2781_apply_calib(struct tasdevice_priv *tas_priv) |
515 | { | |
516 | static const unsigned char page_array[CALIB_MAX] = { | |
0b6f0ff0 | 517 | 0x17, 0x18, 0x18, 0x13, 0x18, |
5be27f1e SD |
518 | }; |
519 | static const unsigned char rgno_array[CALIB_MAX] = { | |
0b6f0ff0 | 520 | 0x74, 0x0c, 0x14, 0x70, 0x7c, |
5be27f1e SD |
521 | }; |
522 | unsigned char *data; | |
523 | int i, j, rc; | |
524 | ||
525 | for (i = 0; i < tas_priv->ndev; i++) { | |
526 | data = tas_priv->cali_data.data + | |
527 | i * TASDEVICE_SPEAKER_CALIBRATION_SIZE; | |
528 | for (j = 0; j < CALIB_MAX; j++) { | |
529 | rc = tasdevice_dev_bulk_write(tas_priv, i, | |
530 | TASDEVICE_REG(0, page_array[j], rgno_array[j]), | |
531 | &(data[4 * j]), 4); | |
532 | if (rc < 0) | |
533 | dev_err(tas_priv->dev, | |
534 | "chn %d calib %d bulk_wr err = %d\n", | |
535 | i, j, rc); | |
536 | } | |
537 | } | |
538 | } | |
539 | ||
a0c9f7f2 | 540 | /* Update the calibration data, including speaker impedance, f0, etc, into algo. |
5be27f1e | 541 | * Calibrate data is done by manufacturer in the factory. These data are used |
a0c9f7f2 | 542 | * by Algo for calculating the speaker temperature, speaker membrane excursion |
5be27f1e SD |
543 | * and f0 in real time during playback. |
544 | */ | |
545 | static int tas2781_save_calibration(struct tasdevice_priv *tas_priv) | |
546 | { | |
547 | efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, | |
548 | 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3); | |
549 | static efi_char16_t efi_name[] = L"CALI_DATA"; | |
550 | struct tm *tm = &tas_priv->tm; | |
551 | unsigned int attr, crc; | |
552 | unsigned int *tmp_val; | |
553 | efi_status_t status; | |
554 | ||
555 | /* Lenovo devices */ | |
556 | if (tas_priv->catlog_id == LENOVO) | |
557 | efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, | |
558 | 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); | |
559 | ||
560 | tas_priv->cali_data.total_sz = 0; | |
561 | /* Get real size of UEFI variable */ | |
562 | status = efi.get_variable(efi_name, &efi_guid, &attr, | |
563 | &tas_priv->cali_data.total_sz, tas_priv->cali_data.data); | |
564 | if (status == EFI_BUFFER_TOO_SMALL) { | |
565 | /* Allocate data buffer of data_size bytes */ | |
566 | tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev, | |
567 | tas_priv->cali_data.total_sz, GFP_KERNEL); | |
568 | if (!tas_priv->cali_data.data) | |
569 | return -ENOMEM; | |
570 | /* Get variable contents into buffer */ | |
571 | status = efi.get_variable(efi_name, &efi_guid, &attr, | |
572 | &tas_priv->cali_data.total_sz, | |
573 | tas_priv->cali_data.data); | |
5be27f1e | 574 | } |
33071422 GK |
575 | if (status != EFI_SUCCESS) |
576 | return -EINVAL; | |
5be27f1e SD |
577 | |
578 | tmp_val = (unsigned int *)tas_priv->cali_data.data; | |
579 | ||
580 | crc = crc32(~0, tas_priv->cali_data.data, 84) ^ ~0; | |
581 | dev_dbg(tas_priv->dev, "cali crc 0x%08x PK tmp_val 0x%08x\n", | |
582 | crc, tmp_val[21]); | |
583 | ||
584 | if (crc == tmp_val[21]) { | |
585 | time64_to_tm(tmp_val[20], 0, tm); | |
586 | dev_dbg(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n", | |
587 | tm->tm_year, tm->tm_mon, tm->tm_mday, | |
588 | tm->tm_hour, tm->tm_min, tm->tm_sec); | |
76f5f55c | 589 | tasdevice_apply_calibration(tas_priv); |
5be27f1e SD |
590 | } else |
591 | tas_priv->cali_data.total_sz = 0; | |
592 | ||
593 | return 0; | |
594 | } | |
595 | ||
4e7914eb GK |
596 | static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda) |
597 | { | |
598 | struct hda_codec *codec = tas_hda->priv->codec; | |
599 | ||
600 | if (tas_hda->dsp_prog_ctl) | |
601 | snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl); | |
602 | ||
603 | if (tas_hda->dsp_conf_ctl) | |
604 | snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl); | |
605 | ||
606 | for (int i = ARRAY_SIZE(tas_hda->snd_ctls) - 1; i >= 0; i--) | |
607 | if (tas_hda->snd_ctls[i]) | |
608 | snd_ctl_remove(codec->card, tas_hda->snd_ctls[i]); | |
609 | ||
610 | if (tas_hda->prof_ctl) | |
611 | snd_ctl_remove(codec->card, tas_hda->prof_ctl); | |
612 | } | |
613 | ||
5be27f1e SD |
614 | static void tasdev_fw_ready(const struct firmware *fmw, void *context) |
615 | { | |
616 | struct tasdevice_priv *tas_priv = context; | |
4e7914eb | 617 | struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev); |
5be27f1e SD |
618 | struct hda_codec *codec = tas_priv->codec; |
619 | int i, ret; | |
620 | ||
621 | pm_runtime_get_sync(tas_priv->dev); | |
622 | mutex_lock(&tas_priv->codec_lock); | |
623 | ||
624 | ret = tasdevice_rca_parser(tas_priv, fmw); | |
625 | if (ret) | |
626 | goto out; | |
627 | ||
4e7914eb GK |
628 | tas_hda->prof_ctl = snd_ctl_new1(&tas2781_prof_ctrl, tas_priv); |
629 | ret = snd_ctl_add(codec->card, tas_hda->prof_ctl); | |
5be27f1e SD |
630 | if (ret) { |
631 | dev_err(tas_priv->dev, | |
632 | "Failed to add KControl %s = %d\n", | |
633 | tas2781_prof_ctrl.name, ret); | |
634 | goto out; | |
635 | } | |
636 | ||
637 | for (i = 0; i < ARRAY_SIZE(tas2781_snd_controls); i++) { | |
4e7914eb GK |
638 | tas_hda->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i], |
639 | tas_priv); | |
640 | ret = snd_ctl_add(codec->card, tas_hda->snd_ctls[i]); | |
5be27f1e SD |
641 | if (ret) { |
642 | dev_err(tas_priv->dev, | |
643 | "Failed to add KControl %s = %d\n", | |
644 | tas2781_snd_controls[i].name, ret); | |
645 | goto out; | |
646 | } | |
647 | } | |
648 | ||
649 | tasdevice_dsp_remove(tas_priv); | |
650 | ||
651 | tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; | |
652 | scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X.bin", | |
653 | codec->core.subsystem_id & 0xffff); | |
654 | ret = tasdevice_dsp_parser(tas_priv); | |
655 | if (ret) { | |
656 | dev_err(tas_priv->dev, "dspfw load %s error\n", | |
657 | tas_priv->coef_binaryname); | |
658 | tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL; | |
659 | goto out; | |
660 | } | |
661 | ||
4e7914eb GK |
662 | tas_hda->dsp_prog_ctl = snd_ctl_new1(&tas2781_dsp_prog_ctrl, |
663 | tas_priv); | |
664 | ret = snd_ctl_add(codec->card, tas_hda->dsp_prog_ctl); | |
5be27f1e SD |
665 | if (ret) { |
666 | dev_err(tas_priv->dev, | |
667 | "Failed to add KControl %s = %d\n", | |
668 | tas2781_dsp_prog_ctrl.name, ret); | |
669 | goto out; | |
670 | } | |
671 | ||
4e7914eb GK |
672 | tas_hda->dsp_conf_ctl = snd_ctl_new1(&tas2781_dsp_conf_ctrl, |
673 | tas_priv); | |
674 | ret = snd_ctl_add(codec->card, tas_hda->dsp_conf_ctl); | |
5be27f1e SD |
675 | if (ret) { |
676 | dev_err(tas_priv->dev, | |
677 | "Failed to add KControl %s = %d\n", | |
678 | tas2781_dsp_conf_ctrl.name, ret); | |
679 | goto out; | |
680 | } | |
681 | ||
682 | tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; | |
683 | tasdevice_prmg_load(tas_priv, 0); | |
ec1de5c2 GK |
684 | if (tas_priv->fmw->nr_programs > 0) |
685 | tas_priv->cur_prog = 0; | |
686 | if (tas_priv->fmw->nr_configurations > 0) | |
687 | tas_priv->cur_conf = 0; | |
5be27f1e SD |
688 | |
689 | /* If calibrated data occurs error, dsp will still works with default | |
690 | * calibrated data inside algo. | |
691 | */ | |
76f5f55c | 692 | tasdevice_save_calibration(tas_priv); |
5be27f1e | 693 | |
68f7f3ff | 694 | tasdevice_tuning_switch(tas_hda->priv, 0); |
9fc91a6f | 695 | tas_hda->priv->playback_started = true; |
68f7f3ff | 696 | |
5be27f1e | 697 | out: |
4e7914eb | 698 | mutex_unlock(&tas_hda->priv->codec_lock); |
5be27f1e SD |
699 | if (fmw) |
700 | release_firmware(fmw); | |
4e7914eb GK |
701 | pm_runtime_mark_last_busy(tas_hda->dev); |
702 | pm_runtime_put_autosuspend(tas_hda->dev); | |
5be27f1e SD |
703 | } |
704 | ||
705 | static int tas2781_hda_bind(struct device *dev, struct device *master, | |
706 | void *master_data) | |
707 | { | |
4e7914eb | 708 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e SD |
709 | struct hda_component *comps = master_data; |
710 | struct hda_codec *codec; | |
711 | unsigned int subid; | |
712 | int ret; | |
713 | ||
4e7914eb GK |
714 | if (!comps || tas_hda->priv->index < 0 || |
715 | tas_hda->priv->index >= HDA_MAX_COMPONENTS) | |
5be27f1e SD |
716 | return -EINVAL; |
717 | ||
4e7914eb | 718 | comps = &comps[tas_hda->priv->index]; |
5be27f1e SD |
719 | if (comps->dev) |
720 | return -EBUSY; | |
721 | ||
722 | codec = comps->codec; | |
723 | subid = codec->core.subsystem_id >> 16; | |
724 | ||
725 | switch (subid) { | |
726 | case 0x17aa: | |
4e7914eb | 727 | tas_hda->priv->catlog_id = LENOVO; |
5be27f1e SD |
728 | break; |
729 | default: | |
4e7914eb | 730 | tas_hda->priv->catlog_id = OTHERS; |
5be27f1e SD |
731 | break; |
732 | } | |
733 | ||
734 | pm_runtime_get_sync(dev); | |
735 | ||
736 | comps->dev = dev; | |
737 | ||
738 | strscpy(comps->name, dev_name(dev), sizeof(comps->name)); | |
739 | ||
34a10669 | 740 | ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready); |
17a1eab7 TI |
741 | if (!ret) |
742 | comps->playback_hook = tas2781_hda_playback_hook; | |
5be27f1e SD |
743 | |
744 | pm_runtime_mark_last_busy(dev); | |
745 | pm_runtime_put_autosuspend(dev); | |
746 | ||
17a1eab7 | 747 | return ret; |
5be27f1e SD |
748 | } |
749 | ||
750 | static void tas2781_hda_unbind(struct device *dev, | |
751 | struct device *master, void *master_data) | |
752 | { | |
4e7914eb | 753 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e | 754 | struct hda_component *comps = master_data; |
4e7914eb | 755 | comps = &comps[tas_hda->priv->index]; |
5be27f1e | 756 | |
75a25d31 GK |
757 | if (comps->dev == dev) { |
758 | comps->dev = NULL; | |
759 | memset(comps->name, 0, sizeof(comps->name)); | |
760 | comps->playback_hook = NULL; | |
761 | } | |
5be27f1e | 762 | |
4e7914eb | 763 | tas2781_hda_remove_controls(tas_hda); |
5be27f1e | 764 | |
4e7914eb GK |
765 | tasdevice_config_info_remove(tas_hda->priv); |
766 | tasdevice_dsp_remove(tas_hda->priv); | |
767 | ||
768 | tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING; | |
5be27f1e SD |
769 | } |
770 | ||
771 | static const struct component_ops tas2781_hda_comp_ops = { | |
772 | .bind = tas2781_hda_bind, | |
773 | .unbind = tas2781_hda_unbind, | |
774 | }; | |
775 | ||
776 | static void tas2781_hda_remove(struct device *dev) | |
777 | { | |
4e7914eb | 778 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e | 779 | |
4e7914eb GK |
780 | pm_runtime_get_sync(tas_hda->dev); |
781 | pm_runtime_disable(tas_hda->dev); | |
5be27f1e | 782 | |
4e7914eb | 783 | component_del(tas_hda->dev, &tas2781_hda_comp_ops); |
5be27f1e | 784 | |
4e7914eb | 785 | pm_runtime_put_noidle(tas_hda->dev); |
5be27f1e | 786 | |
4e7914eb | 787 | tasdevice_remove(tas_hda->priv); |
5be27f1e SD |
788 | } |
789 | ||
790 | static int tas2781_hda_i2c_probe(struct i2c_client *clt) | |
791 | { | |
4e7914eb | 792 | struct tas2781_hda *tas_hda; |
5be27f1e SD |
793 | const char *device_name; |
794 | int ret; | |
795 | ||
5be27f1e | 796 | |
4e7914eb GK |
797 | tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL); |
798 | if (!tas_hda) | |
5be27f1e SD |
799 | return -ENOMEM; |
800 | ||
4e7914eb GK |
801 | dev_set_drvdata(&clt->dev, tas_hda); |
802 | tas_hda->dev = &clt->dev; | |
803 | ||
804 | tas_hda->priv = tasdevice_kzalloc(clt); | |
805 | if (!tas_hda->priv) | |
806 | return -ENOMEM; | |
e7aa1056 | 807 | |
76f5f55c GK |
808 | if (strstr(dev_name(&clt->dev), "TIAS2781")) { |
809 | device_name = "TIAS2781"; | |
810 | tas_hda->priv->save_calibration = tas2781_save_calibration; | |
811 | tas_hda->priv->apply_calibration = tas2781_apply_calib; | |
c021ca72 | 812 | tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; |
c3ca4458 GK |
813 | } else if (strstr(dev_name(&clt->dev), "INT8866")) { |
814 | device_name = "INT8866"; | |
815 | tas_hda->priv->save_calibration = tas2563_save_calibration; | |
816 | tas_hda->priv->apply_calibration = tas2563_apply_calib; | |
817 | tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR; | |
76f5f55c GK |
818 | } else |
819 | return -ENODEV; | |
820 | ||
4e7914eb GK |
821 | tas_hda->priv->irq_info.irq = clt->irq; |
822 | ret = tas2781_read_acpi(tas_hda->priv, device_name); | |
5be27f1e | 823 | if (ret) |
4e7914eb | 824 | return dev_err_probe(tas_hda->dev, ret, |
5be27f1e SD |
825 | "Platform not supported\n"); |
826 | ||
4e7914eb | 827 | ret = tasdevice_init(tas_hda->priv); |
5be27f1e SD |
828 | if (ret) |
829 | goto err; | |
830 | ||
4e7914eb GK |
831 | pm_runtime_set_autosuspend_delay(tas_hda->dev, 3000); |
832 | pm_runtime_use_autosuspend(tas_hda->dev); | |
833 | pm_runtime_mark_last_busy(tas_hda->dev); | |
834 | pm_runtime_set_active(tas_hda->dev); | |
4e7914eb | 835 | pm_runtime_enable(tas_hda->dev); |
5be27f1e | 836 | |
4e7914eb | 837 | tas2781_reset(tas_hda->priv); |
315deab2 | 838 | |
4e7914eb | 839 | ret = component_add(tas_hda->dev, &tas2781_hda_comp_ops); |
5be27f1e | 840 | if (ret) { |
4e7914eb GK |
841 | dev_err(tas_hda->dev, "Register component failed: %d\n", ret); |
842 | pm_runtime_disable(tas_hda->dev); | |
5be27f1e SD |
843 | } |
844 | ||
5be27f1e SD |
845 | err: |
846 | if (ret) | |
847 | tas2781_hda_remove(&clt->dev); | |
848 | return ret; | |
849 | } | |
850 | ||
851 | static void tas2781_hda_i2c_remove(struct i2c_client *clt) | |
852 | { | |
853 | tas2781_hda_remove(&clt->dev); | |
854 | } | |
855 | ||
856 | static int tas2781_runtime_suspend(struct device *dev) | |
857 | { | |
4e7914eb | 858 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e | 859 | |
4e7914eb | 860 | dev_dbg(tas_hda->dev, "Runtime Suspend\n"); |
5be27f1e | 861 | |
4e7914eb | 862 | mutex_lock(&tas_hda->priv->codec_lock); |
5be27f1e | 863 | |
9fc91a6f GK |
864 | /* The driver powers up the amplifiers at module load time. |
865 | * Stop the playback if it's unused. | |
866 | */ | |
4e7914eb GK |
867 | if (tas_hda->priv->playback_started) { |
868 | tasdevice_tuning_switch(tas_hda->priv, 1); | |
869 | tas_hda->priv->playback_started = false; | |
5be27f1e SD |
870 | } |
871 | ||
4e7914eb | 872 | mutex_unlock(&tas_hda->priv->codec_lock); |
5be27f1e SD |
873 | |
874 | return 0; | |
875 | } | |
876 | ||
877 | static int tas2781_runtime_resume(struct device *dev) | |
878 | { | |
4e7914eb | 879 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e | 880 | |
4e7914eb | 881 | dev_dbg(tas_hda->dev, "Runtime Resume\n"); |
5be27f1e | 882 | |
4e7914eb | 883 | mutex_lock(&tas_hda->priv->codec_lock); |
5be27f1e | 884 | |
4e7914eb | 885 | tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); |
5be27f1e SD |
886 | |
887 | /* If calibrated data occurs error, dsp will still works with default | |
888 | * calibrated data inside algo. | |
889 | */ | |
76f5f55c | 890 | tasdevice_apply_calibration(tas_hda->priv); |
5be27f1e | 891 | |
4e7914eb | 892 | mutex_unlock(&tas_hda->priv->codec_lock); |
5be27f1e | 893 | |
6dad45f4 | 894 | return 0; |
5be27f1e SD |
895 | } |
896 | ||
897 | static int tas2781_system_suspend(struct device *dev) | |
898 | { | |
4e7914eb | 899 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5be27f1e | 900 | |
4e7914eb | 901 | dev_dbg(tas_hda->priv->dev, "System Suspend\n"); |
5be27f1e | 902 | |
c58e6ed5 GK |
903 | mutex_lock(&tas_hda->priv->codec_lock); |
904 | ||
5be27f1e | 905 | /* Shutdown chip before system suspend */ |
9fc91a6f GK |
906 | if (tas_hda->priv->playback_started) |
907 | tasdevice_tuning_switch(tas_hda->priv, 1); | |
5be27f1e | 908 | |
c58e6ed5 GK |
909 | mutex_unlock(&tas_hda->priv->codec_lock); |
910 | ||
5be27f1e SD |
911 | /* |
912 | * Reset GPIO may be shared, so cannot reset here. | |
913 | * However beyond this point, amps may be powered down. | |
914 | */ | |
915 | return 0; | |
916 | } | |
917 | ||
918 | static int tas2781_system_resume(struct device *dev) | |
919 | { | |
4e7914eb | 920 | struct tas2781_hda *tas_hda = dev_get_drvdata(dev); |
5f51de7e | 921 | int i; |
5be27f1e | 922 | |
c850c912 | 923 | dev_dbg(tas_hda->priv->dev, "System Resume\n"); |
5be27f1e | 924 | |
4e7914eb | 925 | mutex_lock(&tas_hda->priv->codec_lock); |
5be27f1e | 926 | |
4e7914eb GK |
927 | for (i = 0; i < tas_hda->priv->ndev; i++) { |
928 | tas_hda->priv->tasdevice[i].cur_book = -1; | |
929 | tas_hda->priv->tasdevice[i].cur_prog = -1; | |
930 | tas_hda->priv->tasdevice[i].cur_conf = -1; | |
5be27f1e | 931 | } |
4e7914eb GK |
932 | tas2781_reset(tas_hda->priv); |
933 | tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); | |
5be27f1e SD |
934 | |
935 | /* If calibrated data occurs error, dsp will still work with default | |
936 | * calibrated data inside algo. | |
937 | */ | |
76f5f55c | 938 | tasdevice_apply_calibration(tas_hda->priv); |
9fc91a6f GK |
939 | |
940 | if (tas_hda->priv->playback_started) | |
941 | tasdevice_tuning_switch(tas_hda->priv, 0); | |
942 | ||
4e7914eb | 943 | mutex_unlock(&tas_hda->priv->codec_lock); |
5be27f1e SD |
944 | |
945 | return 0; | |
946 | } | |
947 | ||
948 | static const struct dev_pm_ops tas2781_hda_pm_ops = { | |
949 | RUNTIME_PM_OPS(tas2781_runtime_suspend, tas2781_runtime_resume, NULL) | |
950 | SYSTEM_SLEEP_PM_OPS(tas2781_system_suspend, tas2781_system_resume) | |
951 | }; | |
952 | ||
953 | static const struct i2c_device_id tas2781_hda_i2c_id[] = { | |
954 | { "tas2781-hda", 0 }, | |
955 | {} | |
956 | }; | |
957 | ||
958 | static const struct acpi_device_id tas2781_acpi_hda_match[] = { | |
959 | {"TIAS2781", 0 }, | |
c3ca4458 | 960 | {"INT8866", 0 }, |
5be27f1e SD |
961 | {} |
962 | }; | |
963 | MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); | |
964 | ||
965 | static struct i2c_driver tas2781_hda_i2c_driver = { | |
966 | .driver = { | |
967 | .name = "tas2781-hda", | |
968 | .acpi_match_table = tas2781_acpi_hda_match, | |
969 | .pm = &tas2781_hda_pm_ops, | |
970 | }, | |
971 | .id_table = tas2781_hda_i2c_id, | |
ed81cb9e | 972 | .probe = tas2781_hda_i2c_probe, |
5be27f1e SD |
973 | .remove = tas2781_hda_i2c_remove, |
974 | }; | |
975 | module_i2c_driver(tas2781_hda_i2c_driver); | |
976 | ||
977 | MODULE_DESCRIPTION("TAS2781 HDA Driver"); | |
978 | MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>"); | |
979 | MODULE_LICENSE("GPL"); | |
980 | MODULE_IMPORT_NS(SND_SOC_TAS2781_FMWLIB); |