1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // aw88261.c -- AW88261 ALSA SoC Audio driver |
4 | // |
5 | // Copyright (c) 2023 awinic Technology CO., LTD |
6 | // |
7 | // Author: Jimmy Zhang <zhangjianming@awinic.com> |
8 | // Author: Weidong Wang <wangweidong.a@awinic.com> |
9 | // |
10 | |
11 | #include <linux/i2c.h> |
12 | #include <linux/firmware.h> |
13 | #include <linux/regmap.h> |
14 | #include <sound/soc.h> |
15 | #include "aw88261.h" |
16 | #include "aw88395/aw88395_data_type.h" |
17 | #include "aw88395/aw88395_device.h" |
18 | |
19 | static const struct regmap_config aw88261_remap_config = { |
20 | .val_bits = 16, |
21 | .reg_bits = 8, |
22 | .max_register = AW88261_REG_MAX, |
23 | .reg_format_endian = REGMAP_ENDIAN_LITTLE, |
24 | .val_format_endian = REGMAP_ENDIAN_BIG, |
25 | }; |
26 | |
27 | static void aw88261_dev_set_volume(struct aw_device *aw_dev, unsigned int value) |
28 | { |
29 | struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; |
30 | unsigned int real_value, volume; |
31 | unsigned int reg_value; |
32 | |
33 | volume = min((value + vol_desc->init_volume), (unsigned int)AW88261_MUTE_VOL); |
34 | real_value = DB_TO_REG_VAL(volume); |
35 | |
36 | regmap_read(map: aw_dev->regmap, AW88261_SYSCTRL2_REG, val: ®_value); |
37 | |
38 | real_value = (real_value | (reg_value & AW88261_VOL_START_MASK)); |
39 | |
40 | dev_dbg(aw_dev->dev, "value 0x%x , real_value:0x%x" , value, real_value); |
41 | |
42 | regmap_write(map: aw_dev->regmap, AW88261_SYSCTRL2_REG, val: real_value); |
43 | } |
44 | |
45 | static void aw88261_dev_fade_in(struct aw_device *aw_dev) |
46 | { |
47 | struct aw_volume_desc *desc = &aw_dev->volume_desc; |
48 | int fade_in_vol = desc->ctl_volume; |
49 | int fade_step = aw_dev->fade_step; |
50 | int i; |
51 | |
52 | if (fade_step == 0 || aw_dev->fade_in_time == 0) { |
53 | aw88261_dev_set_volume(aw_dev, value: fade_in_vol); |
54 | return; |
55 | } |
56 | |
57 | for (i = AW88261_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { |
58 | aw88261_dev_set_volume(aw_dev, value: i); |
59 | usleep_range(min: aw_dev->fade_in_time, |
60 | max: aw_dev->fade_in_time + 10); |
61 | } |
62 | |
63 | if (i != fade_in_vol) |
64 | aw88261_dev_set_volume(aw_dev, value: fade_in_vol); |
65 | } |
66 | |
67 | static void aw88261_dev_fade_out(struct aw_device *aw_dev) |
68 | { |
69 | struct aw_volume_desc *desc = &aw_dev->volume_desc; |
70 | int fade_step = aw_dev->fade_step; |
71 | int i; |
72 | |
73 | if (fade_step == 0 || aw_dev->fade_out_time == 0) { |
74 | aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); |
75 | return; |
76 | } |
77 | |
78 | for (i = desc->ctl_volume; i <= AW88261_MUTE_VOL; i += fade_step) { |
79 | aw88261_dev_set_volume(aw_dev, value: i); |
80 | usleep_range(min: aw_dev->fade_out_time, max: aw_dev->fade_out_time + 10); |
81 | } |
82 | |
83 | if (i != AW88261_MUTE_VOL) { |
84 | aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); |
85 | usleep_range(min: aw_dev->fade_out_time, max: aw_dev->fade_out_time + 10); |
86 | } |
87 | } |
88 | |
89 | static void aw88261_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) |
90 | { |
91 | if (flag) |
92 | regmap_update_bits(map: aw_dev->regmap, AW88261_I2SCFG1_REG, |
93 | mask: ~AW88261_I2STXEN_MASK, AW88261_I2STXEN_ENABLE_VALUE); |
94 | else |
95 | regmap_update_bits(map: aw_dev->regmap, AW88261_I2SCFG1_REG, |
96 | mask: ~AW88261_I2STXEN_MASK, AW88261_I2STXEN_DISABLE_VALUE); |
97 | } |
98 | |
99 | static void aw88261_dev_pwd(struct aw_device *aw_dev, bool pwd) |
100 | { |
101 | if (pwd) |
102 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
103 | mask: ~AW88261_PWDN_MASK, AW88261_PWDN_POWER_DOWN_VALUE); |
104 | else |
105 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
106 | mask: ~AW88261_PWDN_MASK, AW88261_PWDN_WORKING_VALUE); |
107 | } |
108 | |
109 | static void aw88261_dev_amppd(struct aw_device *aw_dev, bool amppd) |
110 | { |
111 | if (amppd) |
112 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
113 | mask: ~AW88261_AMPPD_MASK, AW88261_AMPPD_POWER_DOWN_VALUE); |
114 | else |
115 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
116 | mask: ~AW88261_AMPPD_MASK, AW88261_AMPPD_WORKING_VALUE); |
117 | } |
118 | |
119 | static void aw88261_dev_mute(struct aw_device *aw_dev, bool is_mute) |
120 | { |
121 | if (is_mute) { |
122 | aw88261_dev_fade_out(aw_dev); |
123 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
124 | mask: ~AW88261_HMUTE_MASK, AW88261_HMUTE_ENABLE_VALUE); |
125 | } else { |
126 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
127 | mask: ~AW88261_HMUTE_MASK, AW88261_HMUTE_DISABLE_VALUE); |
128 | aw88261_dev_fade_in(aw_dev); |
129 | } |
130 | } |
131 | |
132 | static void aw88261_dev_clear_int_status(struct aw_device *aw_dev) |
133 | { |
134 | unsigned int int_status; |
135 | |
136 | /* read int status and clear */ |
137 | regmap_read(map: aw_dev->regmap, AW88261_SYSINT_REG, val: &int_status); |
138 | /* make sure int status is clear */ |
139 | regmap_read(map: aw_dev->regmap, AW88261_SYSINT_REG, val: &int_status); |
140 | |
141 | dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x" , int_status); |
142 | } |
143 | |
144 | static int aw88261_dev_get_iis_status(struct aw_device *aw_dev) |
145 | { |
146 | unsigned int reg_val; |
147 | int ret; |
148 | |
149 | ret = regmap_read(map: aw_dev->regmap, AW88261_SYSST_REG, val: ®_val); |
150 | if (ret) |
151 | return ret; |
152 | if ((reg_val & AW88261_BIT_PLL_CHECK) != AW88261_BIT_PLL_CHECK) { |
153 | dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x" , reg_val); |
154 | return -EINVAL; |
155 | } |
156 | |
157 | return ret; |
158 | } |
159 | |
160 | static int aw88261_dev_check_mode1_pll(struct aw_device *aw_dev) |
161 | { |
162 | int ret, i; |
163 | |
164 | for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { |
165 | ret = aw88261_dev_get_iis_status(aw_dev); |
166 | if (ret) { |
167 | dev_err(aw_dev->dev, "mode1 iis signal check error" ); |
168 | usleep_range(min: AW88261_2000_US, max: AW88261_2000_US + 10); |
169 | } else { |
170 | return ret; |
171 | } |
172 | } |
173 | |
174 | return -EPERM; |
175 | } |
176 | |
177 | static int aw88261_dev_check_mode2_pll(struct aw_device *aw_dev) |
178 | { |
179 | unsigned int reg_val; |
180 | int ret, i; |
181 | |
182 | ret = regmap_read(map: aw_dev->regmap, AW88261_PLLCTRL1_REG, val: ®_val); |
183 | if (ret) |
184 | return ret; |
185 | |
186 | reg_val &= (~AW88261_CCO_MUX_MASK); |
187 | if (reg_val == AW88261_CCO_MUX_DIVIDED_VALUE) { |
188 | dev_dbg(aw_dev->dev, "CCO_MUX is already divider" ); |
189 | return -EPERM; |
190 | } |
191 | |
192 | /* change mode2 */ |
193 | ret = regmap_update_bits(map: aw_dev->regmap, AW88261_PLLCTRL1_REG, |
194 | mask: ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_DIVIDED_VALUE); |
195 | if (ret) |
196 | return ret; |
197 | |
198 | for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { |
199 | ret = aw88261_dev_get_iis_status(aw_dev); |
200 | if (ret) { |
201 | dev_err(aw_dev->dev, "mode2 iis signal check error" ); |
202 | usleep_range(min: AW88261_2000_US, max: AW88261_2000_US + 10); |
203 | } else { |
204 | break; |
205 | } |
206 | } |
207 | |
208 | /* change mode1 */ |
209 | ret = regmap_update_bits(map: aw_dev->regmap, AW88261_PLLCTRL1_REG, |
210 | mask: ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_BYPASS_VALUE); |
211 | if (ret == 0) { |
212 | usleep_range(min: AW88261_2000_US, max: AW88261_2000_US + 10); |
213 | for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { |
214 | ret = aw88261_dev_check_mode1_pll(aw_dev); |
215 | if (ret) { |
216 | dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error" ); |
217 | usleep_range(min: AW88261_2000_US, max: AW88261_2000_US + 10); |
218 | } else { |
219 | break; |
220 | } |
221 | } |
222 | } |
223 | |
224 | return ret; |
225 | } |
226 | |
227 | static int aw88261_dev_check_syspll(struct aw_device *aw_dev) |
228 | { |
229 | int ret; |
230 | |
231 | ret = aw88261_dev_check_mode1_pll(aw_dev); |
232 | if (ret) { |
233 | dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check" ); |
234 | ret = aw88261_dev_check_mode2_pll(aw_dev); |
235 | if (ret) { |
236 | dev_err(aw_dev->dev, "mode2 check iis failed" ); |
237 | return ret; |
238 | } |
239 | } |
240 | |
241 | return ret; |
242 | } |
243 | |
244 | static int aw88261_dev_check_sysst(struct aw_device *aw_dev) |
245 | { |
246 | unsigned int check_val; |
247 | unsigned int reg_val; |
248 | int ret, i; |
249 | |
250 | for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { |
251 | ret = regmap_read(map: aw_dev->regmap, AW88261_SYSST_REG, val: ®_val); |
252 | if (ret) |
253 | return ret; |
254 | |
255 | check_val = reg_val & (~AW88261_BIT_SYSST_CHECK_MASK) |
256 | & AW88261_BIT_SYSST_CHECK; |
257 | if (check_val != AW88261_BIT_SYSST_CHECK) { |
258 | dev_err(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x" , |
259 | reg_val, AW88261_BIT_SYSST_CHECK); |
260 | usleep_range(min: AW88261_2000_US, max: AW88261_2000_US + 10); |
261 | } else { |
262 | return 0; |
263 | } |
264 | } |
265 | |
266 | return -EPERM; |
267 | } |
268 | |
269 | static void aw88261_dev_uls_hmute(struct aw_device *aw_dev, bool uls_hmute) |
270 | { |
271 | if (uls_hmute) |
272 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
273 | mask: ~AW88261_ULS_HMUTE_MASK, |
274 | AW88261_ULS_HMUTE_ENABLE_VALUE); |
275 | else |
276 | regmap_update_bits(map: aw_dev->regmap, AW88261_SYSCTRL_REG, |
277 | mask: ~AW88261_ULS_HMUTE_MASK, |
278 | AW88261_ULS_HMUTE_DISABLE_VALUE); |
279 | } |
280 | |
281 | static void aw88261_reg_force_set(struct aw88261 *aw88261) |
282 | { |
283 | if (aw88261->frcset_en == AW88261_FRCSET_ENABLE) { |
284 | /* set FORCE_PWM */ |
285 | regmap_update_bits(map: aw88261->regmap, AW88261_BSTCTRL3_REG, |
286 | AW88261_FORCE_PWM_MASK, AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE); |
287 | /* set BOOST_OS_WIDTH */ |
288 | regmap_update_bits(map: aw88261->regmap, AW88261_BSTCTRL5_REG, |
289 | AW88261_BST_OS_WIDTH_MASK, AW88261_BST_OS_WIDTH_50NS_VALUE); |
290 | /* set BURST_LOOPR */ |
291 | regmap_update_bits(map: aw88261->regmap, AW88261_BSTCTRL6_REG, |
292 | AW88261_BST_LOOPR_MASK, AW88261_BST_LOOPR_340K_VALUE); |
293 | /* set RSQN_DLY */ |
294 | regmap_update_bits(map: aw88261->regmap, AW88261_BSTCTRL7_REG, |
295 | AW88261_RSQN_DLY_MASK, AW88261_RSQN_DLY_35NS_VALUE); |
296 | /* set BURST_SSMODE */ |
297 | regmap_update_bits(map: aw88261->regmap, AW88261_BSTCTRL8_REG, |
298 | AW88261_BURST_SSMODE_MASK, AW88261_BURST_SSMODE_FAST_VALUE); |
299 | /* set BST_BURST */ |
300 | regmap_update_bits(map: aw88261->regmap, AW88261_BSTCTRL9_REG, |
301 | AW88261_BST_BURST_MASK, AW88261_BST_BURST_30MA_VALUE); |
302 | } else { |
303 | dev_dbg(aw88261->aw_pa->dev, "needn't set reg value" ); |
304 | } |
305 | } |
306 | |
307 | static int aw88261_dev_get_icalk(struct aw_device *aw_dev, int16_t *icalk) |
308 | { |
309 | u16 reg_icalk, reg_icalkl; |
310 | unsigned int reg_val; |
311 | int ret; |
312 | |
313 | ret = regmap_read(map: aw_dev->regmap, AW88261_EFRH4_REG, val: ®_val); |
314 | if (ret) |
315 | return ret; |
316 | |
317 | reg_icalk = reg_val & (~AW88261_EF_ISN_GESLP_H_MASK); |
318 | |
319 | ret = regmap_read(map: aw_dev->regmap, AW88261_EFRL4_REG, val: ®_val); |
320 | if (ret) |
321 | return ret; |
322 | |
323 | reg_icalkl = reg_val & (~AW88261_EF_ISN_GESLP_L_MASK); |
324 | |
325 | reg_icalk = (reg_icalk >> AW88261_ICALK_SHIFT) & (reg_icalkl >> AW88261_ICALKL_SHIFT); |
326 | |
327 | if (reg_icalk & (~AW88261_EF_ISN_GESLP_SIGN_MASK)) |
328 | reg_icalk = reg_icalk | ~AW88261_EF_ISN_GESLP_NEG; |
329 | |
330 | *icalk = (int16_t)reg_icalk; |
331 | |
332 | return ret; |
333 | } |
334 | |
335 | static int aw88261_dev_get_vcalk(struct aw_device *aw_dev, int16_t *vcalk) |
336 | { |
337 | u16 reg_vcalk, reg_vcalkl; |
338 | unsigned int reg_val; |
339 | int ret; |
340 | |
341 | ret = regmap_read(map: aw_dev->regmap, AW88261_EFRH3_REG, val: ®_val); |
342 | if (ret) |
343 | return ret; |
344 | |
345 | reg_vcalk = (u16)reg_val & (~AW88261_EF_VSN_GESLP_H_MASK); |
346 | |
347 | ret = regmap_read(map: aw_dev->regmap, AW88261_EFRL3_REG, val: ®_val); |
348 | if (ret) |
349 | return ret; |
350 | |
351 | reg_vcalkl = (u16)reg_val & (~AW88261_EF_VSN_GESLP_L_MASK); |
352 | |
353 | reg_vcalk = (reg_vcalk >> AW88261_VCALK_SHIFT) & (reg_vcalkl >> AW88261_VCALKL_SHIFT); |
354 | |
355 | if (reg_vcalk & AW88261_EF_VSN_GESLP_SIGN_MASK) |
356 | reg_vcalk = reg_vcalk | (~AW88261_EF_VSN_GESLP_NEG); |
357 | *vcalk = (int16_t)reg_vcalk; |
358 | |
359 | return ret; |
360 | } |
361 | |
362 | static int aw88261_dev_set_vcalb(struct aw_device *aw_dev) |
363 | { |
364 | int16_t icalk_val, vcalk_val; |
365 | int icalk, vcalk, vcalb; |
366 | u32 reg_val; |
367 | int ret; |
368 | |
369 | ret = aw88261_dev_get_icalk(aw_dev, icalk: &icalk_val); |
370 | if (ret) |
371 | return ret; |
372 | |
373 | ret = aw88261_dev_get_vcalk(aw_dev, vcalk: &vcalk_val); |
374 | if (ret) |
375 | return ret; |
376 | |
377 | icalk = AW88261_CABL_BASE_VALUE + AW88261_ICABLK_FACTOR * icalk_val; |
378 | vcalk = AW88261_CABL_BASE_VALUE + AW88261_VCABLK_FACTOR * vcalk_val; |
379 | if (!vcalk) |
380 | return -EINVAL; |
381 | |
382 | vcalb = AW88261_VCAL_FACTOR * icalk / vcalk; |
383 | reg_val = (unsigned int)vcalb; |
384 | |
385 | dev_dbg(aw_dev->dev, "icalk=%d, vcalk=%d, vcalb=%d, reg_val=0x%04x" , |
386 | icalk, vcalk, vcalb, reg_val); |
387 | ret = regmap_write(map: aw_dev->regmap, AW88261_VSNTM1_REG, val: reg_val); |
388 | |
389 | return ret; |
390 | } |
391 | |
392 | static int aw88261_dev_reg_update(struct aw88261 *aw88261, |
393 | unsigned char *data, unsigned int len) |
394 | { |
395 | struct aw_device *aw_dev = aw88261->aw_pa; |
396 | struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; |
397 | unsigned int read_val, efcheck_val, read_vol; |
398 | int data_len, i, ret; |
399 | int16_t *reg_data; |
400 | u16 reg_val; |
401 | u8 reg_addr; |
402 | |
403 | if (!len || !data) { |
404 | dev_err(aw_dev->dev, "reg data is null or len is 0" ); |
405 | return -EINVAL; |
406 | } |
407 | |
408 | reg_data = (int16_t *)data; |
409 | data_len = len >> 1; |
410 | |
411 | if (data_len & 0x1) { |
412 | dev_err(aw_dev->dev, "data len:%d unsupported" , data_len); |
413 | return -EINVAL; |
414 | } |
415 | |
416 | for (i = 0; i < data_len; i += 2) { |
417 | reg_addr = reg_data[i]; |
418 | reg_val = reg_data[i + 1]; |
419 | |
420 | if (reg_addr == AW88261_SYSCTRL_REG) { |
421 | aw88261->amppd_st = reg_val & (~AW88261_AMPPD_MASK); |
422 | ret = regmap_read(map: aw_dev->regmap, reg: reg_addr, val: &read_val); |
423 | if (ret) |
424 | break; |
425 | |
426 | read_val &= (~AW88261_AMPPD_MASK) | (~AW88261_PWDN_MASK) | |
427 | (~AW88261_HMUTE_MASK); |
428 | reg_val &= (AW88261_AMPPD_MASK | AW88261_PWDN_MASK | AW88261_HMUTE_MASK); |
429 | reg_val |= read_val; |
430 | |
431 | /* enable uls hmute */ |
432 | reg_val &= AW88261_ULS_HMUTE_MASK; |
433 | reg_val |= AW88261_ULS_HMUTE_ENABLE_VALUE; |
434 | } |
435 | |
436 | if (reg_addr == AW88261_DBGCTRL_REG) { |
437 | efcheck_val = reg_val & (~AW88261_EF_DBMD_MASK); |
438 | if (efcheck_val == AW88261_OR_VALUE) |
439 | aw88261->efuse_check = AW88261_EF_OR_CHECK; |
440 | else |
441 | aw88261->efuse_check = AW88261_EF_AND_CHECK; |
442 | } |
443 | |
444 | /* i2stxen */ |
445 | if (reg_addr == AW88261_I2SCTRL3_REG) { |
446 | /* close tx */ |
447 | reg_val &= AW88261_I2STXEN_MASK; |
448 | reg_val |= AW88261_I2STXEN_DISABLE_VALUE; |
449 | } |
450 | |
451 | if (reg_addr == AW88261_SYSCTRL2_REG) { |
452 | read_vol = (reg_val & (~AW88261_VOL_MASK)) >> |
453 | AW88261_VOL_START_BIT; |
454 | aw_dev->volume_desc.init_volume = |
455 | REG_VAL_TO_DB(read_vol); |
456 | } |
457 | |
458 | if (reg_addr == AW88261_VSNTM1_REG) |
459 | continue; |
460 | |
461 | ret = regmap_write(map: aw_dev->regmap, reg: reg_addr, val: reg_val); |
462 | if (ret) |
463 | break; |
464 | } |
465 | |
466 | ret = aw88261_dev_set_vcalb(aw_dev); |
467 | if (ret) |
468 | return ret; |
469 | |
470 | if (aw_dev->prof_cur != aw_dev->prof_index) |
471 | vol_desc->ctl_volume = 0; |
472 | |
473 | /* keep min volume */ |
474 | aw88261_dev_set_volume(aw_dev, value: vol_desc->mute_volume); |
475 | |
476 | return ret; |
477 | } |
478 | |
479 | static int aw88261_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name) |
480 | { |
481 | struct aw_prof_info *prof_info = &aw_dev->prof_info; |
482 | struct aw_prof_desc *prof_desc; |
483 | |
484 | if ((index >= aw_dev->prof_info.count) || (index < 0)) { |
485 | dev_err(aw_dev->dev, "index[%d] overflow count[%d]" , |
486 | index, aw_dev->prof_info.count); |
487 | return -EINVAL; |
488 | } |
489 | |
490 | prof_desc = &aw_dev->prof_info.prof_desc[index]; |
491 | |
492 | *prof_name = prof_info->prof_name_list[prof_desc->id]; |
493 | |
494 | return 0; |
495 | } |
496 | |
497 | static int aw88261_dev_get_prof_data(struct aw_device *aw_dev, int index, |
498 | struct aw_prof_desc **prof_desc) |
499 | { |
500 | if ((index >= aw_dev->prof_info.count) || (index < 0)) { |
501 | dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n" , |
502 | __func__, index, aw_dev->prof_info.count); |
503 | return -EINVAL; |
504 | } |
505 | |
506 | *prof_desc = &aw_dev->prof_info.prof_desc[index]; |
507 | |
508 | return 0; |
509 | } |
510 | |
511 | static int aw88261_dev_fw_update(struct aw88261 *aw88261) |
512 | { |
513 | struct aw_device *aw_dev = aw88261->aw_pa; |
514 | struct aw_prof_desc *prof_index_desc; |
515 | struct aw_sec_data_desc *sec_desc; |
516 | char *prof_name; |
517 | int ret; |
518 | |
519 | ret = aw88261_dev_get_prof_name(aw_dev, index: aw_dev->prof_index, prof_name: &prof_name); |
520 | if (ret) { |
521 | dev_err(aw_dev->dev, "get prof name failed" ); |
522 | return -EINVAL; |
523 | } |
524 | |
525 | dev_dbg(aw_dev->dev, "start update %s" , prof_name); |
526 | |
527 | ret = aw88261_dev_get_prof_data(aw_dev, index: aw_dev->prof_index, prof_desc: &prof_index_desc); |
528 | if (ret) |
529 | return ret; |
530 | |
531 | /* update reg */ |
532 | sec_desc = prof_index_desc->sec_desc; |
533 | ret = aw88261_dev_reg_update(aw88261, data: sec_desc[AW88395_DATA_TYPE_REG].data, |
534 | len: sec_desc[AW88395_DATA_TYPE_REG].len); |
535 | if (ret) { |
536 | dev_err(aw_dev->dev, "update reg failed" ); |
537 | return ret; |
538 | } |
539 | |
540 | aw_dev->prof_cur = aw_dev->prof_index; |
541 | |
542 | return ret; |
543 | } |
544 | |
545 | static int aw88261_dev_start(struct aw88261 *aw88261) |
546 | { |
547 | struct aw_device *aw_dev = aw88261->aw_pa; |
548 | int ret; |
549 | |
550 | if (aw_dev->status == AW88261_DEV_PW_ON) { |
551 | dev_info(aw_dev->dev, "already power on" ); |
552 | return 0; |
553 | } |
554 | |
555 | /* power on */ |
556 | aw88261_dev_pwd(aw_dev, pwd: false); |
557 | usleep_range(min: AW88261_2000_US, max: AW88261_2000_US + 10); |
558 | |
559 | ret = aw88261_dev_check_syspll(aw_dev); |
560 | if (ret) { |
561 | dev_err(aw_dev->dev, "pll check failed cannot start" ); |
562 | goto pll_check_fail; |
563 | } |
564 | |
565 | /* amppd on */ |
566 | aw88261_dev_amppd(aw_dev, amppd: false); |
567 | usleep_range(min: AW88261_1000_US, max: AW88261_1000_US + 50); |
568 | |
569 | /* check i2s status */ |
570 | ret = aw88261_dev_check_sysst(aw_dev); |
571 | if (ret) { |
572 | dev_err(aw_dev->dev, "sysst check failed" ); |
573 | goto sysst_check_fail; |
574 | } |
575 | |
576 | /* enable tx feedback */ |
577 | aw88261_dev_i2s_tx_enable(aw_dev, flag: true); |
578 | |
579 | if (aw88261->amppd_st) |
580 | aw88261_dev_amppd(aw_dev, amppd: true); |
581 | |
582 | aw88261_reg_force_set(aw88261); |
583 | |
584 | /* close uls mute */ |
585 | aw88261_dev_uls_hmute(aw_dev, uls_hmute: false); |
586 | |
587 | /* close mute */ |
588 | if (!aw88261->mute_st) |
589 | aw88261_dev_mute(aw_dev, is_mute: false); |
590 | |
591 | /* clear inturrupt */ |
592 | aw88261_dev_clear_int_status(aw_dev); |
593 | aw_dev->status = AW88261_DEV_PW_ON; |
594 | |
595 | return 0; |
596 | |
597 | sysst_check_fail: |
598 | aw88261_dev_i2s_tx_enable(aw_dev, flag: false); |
599 | aw88261_dev_clear_int_status(aw_dev); |
600 | aw88261_dev_amppd(aw_dev, amppd: true); |
601 | pll_check_fail: |
602 | aw88261_dev_pwd(aw_dev, pwd: true); |
603 | aw_dev->status = AW88261_DEV_PW_OFF; |
604 | |
605 | return ret; |
606 | } |
607 | |
608 | static int aw88261_dev_stop(struct aw_device *aw_dev) |
609 | { |
610 | if (aw_dev->status == AW88261_DEV_PW_OFF) { |
611 | dev_info(aw_dev->dev, "already power off" ); |
612 | return 0; |
613 | } |
614 | |
615 | aw_dev->status = AW88261_DEV_PW_OFF; |
616 | |
617 | /* clear inturrupt */ |
618 | aw88261_dev_clear_int_status(aw_dev); |
619 | |
620 | aw88261_dev_uls_hmute(aw_dev, uls_hmute: true); |
621 | /* set mute */ |
622 | aw88261_dev_mute(aw_dev, is_mute: true); |
623 | |
624 | /* close tx feedback */ |
625 | aw88261_dev_i2s_tx_enable(aw_dev, flag: false); |
626 | usleep_range(min: AW88261_1000_US, max: AW88261_1000_US + 100); |
627 | |
628 | /* enable amppd */ |
629 | aw88261_dev_amppd(aw_dev, amppd: true); |
630 | |
631 | /* set power down */ |
632 | aw88261_dev_pwd(aw_dev, pwd: true); |
633 | |
634 | return 0; |
635 | } |
636 | |
637 | static int aw88261_reg_update(struct aw88261 *aw88261, bool force) |
638 | { |
639 | struct aw_device *aw_dev = aw88261->aw_pa; |
640 | int ret; |
641 | |
642 | if (force) { |
643 | ret = regmap_write(map: aw_dev->regmap, |
644 | AW88261_ID_REG, AW88261_SOFT_RESET_VALUE); |
645 | if (ret) |
646 | return ret; |
647 | |
648 | ret = aw88261_dev_fw_update(aw88261); |
649 | if (ret) |
650 | return ret; |
651 | } else { |
652 | if (aw_dev->prof_cur != aw_dev->prof_index) { |
653 | ret = aw88261_dev_fw_update(aw88261); |
654 | if (ret) |
655 | return ret; |
656 | } else { |
657 | ret = 0; |
658 | } |
659 | } |
660 | |
661 | aw_dev->prof_cur = aw_dev->prof_index; |
662 | |
663 | return ret; |
664 | } |
665 | |
666 | static void aw88261_start_pa(struct aw88261 *aw88261) |
667 | { |
668 | int ret, i; |
669 | |
670 | for (i = 0; i < AW88261_START_RETRIES; i++) { |
671 | ret = aw88261_reg_update(aw88261, force: aw88261->phase_sync); |
672 | if (ret) { |
673 | dev_err(aw88261->aw_pa->dev, "fw update failed, cnt:%d\n" , i); |
674 | continue; |
675 | } |
676 | ret = aw88261_dev_start(aw88261); |
677 | if (ret) { |
678 | dev_err(aw88261->aw_pa->dev, "aw88261 device start failed. retry = %d" , i); |
679 | continue; |
680 | } else { |
681 | dev_info(aw88261->aw_pa->dev, "start success\n" ); |
682 | break; |
683 | } |
684 | } |
685 | } |
686 | |
687 | static void aw88261_startup_work(struct work_struct *work) |
688 | { |
689 | struct aw88261 *aw88261 = |
690 | container_of(work, struct aw88261, start_work.work); |
691 | |
692 | mutex_lock(&aw88261->lock); |
693 | aw88261_start_pa(aw88261); |
694 | mutex_unlock(lock: &aw88261->lock); |
695 | } |
696 | |
697 | static void aw88261_start(struct aw88261 *aw88261, bool sync_start) |
698 | { |
699 | if (aw88261->aw_pa->fw_status != AW88261_DEV_FW_OK) |
700 | return; |
701 | |
702 | if (aw88261->aw_pa->status == AW88261_DEV_PW_ON) |
703 | return; |
704 | |
705 | if (sync_start == AW88261_SYNC_START) |
706 | aw88261_start_pa(aw88261); |
707 | else |
708 | queue_delayed_work(wq: system_wq, |
709 | dwork: &aw88261->start_work, |
710 | AW88261_START_WORK_DELAY_MS); |
711 | } |
712 | |
713 | static struct snd_soc_dai_driver aw88261_dai[] = { |
714 | { |
715 | .name = "aw88261-aif" , |
716 | .id = 1, |
717 | .playback = { |
718 | .stream_name = "Speaker_Playback" , |
719 | .channels_min = 1, |
720 | .channels_max = 2, |
721 | .rates = AW88261_RATES, |
722 | .formats = AW88261_FORMATS, |
723 | }, |
724 | .capture = { |
725 | .stream_name = "Speaker_Capture" , |
726 | .channels_min = 1, |
727 | .channels_max = 2, |
728 | .rates = AW88261_RATES, |
729 | .formats = AW88261_FORMATS, |
730 | }, |
731 | }, |
732 | }; |
733 | |
734 | static int aw88261_get_fade_in_time(struct snd_kcontrol *kcontrol, |
735 | struct snd_ctl_elem_value *ucontrol) |
736 | { |
737 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
738 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: component); |
739 | struct aw_device *aw_dev = aw88261->aw_pa; |
740 | |
741 | ucontrol->value.integer.value[0] = aw_dev->fade_in_time; |
742 | |
743 | return 0; |
744 | } |
745 | |
746 | static int aw88261_set_fade_in_time(struct snd_kcontrol *kcontrol, |
747 | struct snd_ctl_elem_value *ucontrol) |
748 | { |
749 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
750 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: component); |
751 | struct soc_mixer_control *mc = |
752 | (struct soc_mixer_control *)kcontrol->private_value; |
753 | struct aw_device *aw_dev = aw88261->aw_pa; |
754 | int time; |
755 | |
756 | time = ucontrol->value.integer.value[0]; |
757 | |
758 | if (time < mc->min || time > mc->max) |
759 | return -EINVAL; |
760 | |
761 | if (time != aw_dev->fade_in_time) { |
762 | aw_dev->fade_in_time = time; |
763 | return 1; |
764 | } |
765 | |
766 | return 0; |
767 | } |
768 | |
769 | static int aw88261_get_fade_out_time(struct snd_kcontrol *kcontrol, |
770 | struct snd_ctl_elem_value *ucontrol) |
771 | { |
772 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
773 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: component); |
774 | struct aw_device *aw_dev = aw88261->aw_pa; |
775 | |
776 | ucontrol->value.integer.value[0] = aw_dev->fade_out_time; |
777 | |
778 | return 0; |
779 | } |
780 | |
781 | static int aw88261_set_fade_out_time(struct snd_kcontrol *kcontrol, |
782 | struct snd_ctl_elem_value *ucontrol) |
783 | { |
784 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
785 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: component); |
786 | struct soc_mixer_control *mc = |
787 | (struct soc_mixer_control *)kcontrol->private_value; |
788 | struct aw_device *aw_dev = aw88261->aw_pa; |
789 | int time; |
790 | |
791 | time = ucontrol->value.integer.value[0]; |
792 | if (time < mc->min || time > mc->max) |
793 | return -EINVAL; |
794 | |
795 | if (time != aw_dev->fade_out_time) { |
796 | aw_dev->fade_out_time = time; |
797 | return 1; |
798 | } |
799 | |
800 | return 0; |
801 | } |
802 | |
803 | static int aw88261_dev_set_profile_index(struct aw_device *aw_dev, int index) |
804 | { |
805 | /* check the index whether is valid */ |
806 | if ((index >= aw_dev->prof_info.count) || (index < 0)) |
807 | return -EINVAL; |
808 | /* check the index whether change */ |
809 | if (aw_dev->prof_index == index) |
810 | return -EPERM; |
811 | |
812 | aw_dev->prof_index = index; |
813 | |
814 | return 0; |
815 | } |
816 | |
817 | static int aw88261_profile_info(struct snd_kcontrol *kcontrol, |
818 | struct snd_ctl_elem_info *uinfo) |
819 | { |
820 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
821 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
822 | char *prof_name, *name; |
823 | int count, ret; |
824 | |
825 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
826 | uinfo->count = 1; |
827 | |
828 | count = aw88261->aw_pa->prof_info.count; |
829 | if (count <= 0) { |
830 | uinfo->value.enumerated.items = 0; |
831 | return 0; |
832 | } |
833 | |
834 | uinfo->value.enumerated.items = count; |
835 | |
836 | if (uinfo->value.enumerated.item >= count) |
837 | uinfo->value.enumerated.item = count - 1; |
838 | |
839 | name = uinfo->value.enumerated.name; |
840 | count = uinfo->value.enumerated.item; |
841 | |
842 | ret = aw88261_dev_get_prof_name(aw_dev: aw88261->aw_pa, index: count, prof_name: &prof_name); |
843 | if (ret) { |
844 | strscpy(uinfo->value.enumerated.name, "null" , |
845 | strlen("null" ) + 1); |
846 | return 0; |
847 | } |
848 | |
849 | strscpy(name, prof_name, sizeof(uinfo->value.enumerated.name)); |
850 | |
851 | return 0; |
852 | } |
853 | |
854 | static int aw88261_profile_get(struct snd_kcontrol *kcontrol, |
855 | struct snd_ctl_elem_value *ucontrol) |
856 | { |
857 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
858 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
859 | |
860 | ucontrol->value.integer.value[0] = aw88261->aw_pa->prof_index; |
861 | |
862 | return 0; |
863 | } |
864 | |
865 | static int aw88261_profile_set(struct snd_kcontrol *kcontrol, |
866 | struct snd_ctl_elem_value *ucontrol) |
867 | { |
868 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
869 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
870 | int ret; |
871 | |
872 | /* pa stop or stopping just set profile */ |
873 | mutex_lock(&aw88261->lock); |
874 | ret = aw88261_dev_set_profile_index(aw_dev: aw88261->aw_pa, index: ucontrol->value.integer.value[0]); |
875 | if (ret) { |
876 | dev_dbg(codec->dev, "profile index does not change" ); |
877 | mutex_unlock(lock: &aw88261->lock); |
878 | return 0; |
879 | } |
880 | |
881 | if (aw88261->aw_pa->status) { |
882 | aw88261_dev_stop(aw_dev: aw88261->aw_pa); |
883 | aw88261_start(aw88261, sync_start: AW88261_SYNC_START); |
884 | } |
885 | |
886 | mutex_unlock(lock: &aw88261->lock); |
887 | |
888 | return 1; |
889 | } |
890 | |
891 | static int aw88261_volume_get(struct snd_kcontrol *kcontrol, |
892 | struct snd_ctl_elem_value *ucontrol) |
893 | { |
894 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
895 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
896 | struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; |
897 | |
898 | ucontrol->value.integer.value[0] = vol_desc->ctl_volume; |
899 | |
900 | return 0; |
901 | } |
902 | |
903 | static int aw88261_volume_set(struct snd_kcontrol *kcontrol, |
904 | struct snd_ctl_elem_value *ucontrol) |
905 | { |
906 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
907 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
908 | struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; |
909 | struct soc_mixer_control *mc = |
910 | (struct soc_mixer_control *)kcontrol->private_value; |
911 | int value; |
912 | |
913 | value = ucontrol->value.integer.value[0]; |
914 | |
915 | if (value < mc->min || value > mc->max) |
916 | return -EINVAL; |
917 | |
918 | if (vol_desc->ctl_volume != value) { |
919 | vol_desc->ctl_volume = value; |
920 | aw88261_dev_set_volume(aw_dev: aw88261->aw_pa, value: vol_desc->ctl_volume); |
921 | |
922 | return 1; |
923 | } |
924 | |
925 | return 0; |
926 | } |
927 | |
928 | static int aw88261_get_fade_step(struct snd_kcontrol *kcontrol, |
929 | struct snd_ctl_elem_value *ucontrol) |
930 | { |
931 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
932 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
933 | |
934 | ucontrol->value.integer.value[0] = aw88261->aw_pa->fade_step; |
935 | |
936 | return 0; |
937 | } |
938 | |
939 | static int aw88261_set_fade_step(struct snd_kcontrol *kcontrol, |
940 | struct snd_ctl_elem_value *ucontrol) |
941 | { |
942 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
943 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: codec); |
944 | struct soc_mixer_control *mc = |
945 | (struct soc_mixer_control *)kcontrol->private_value; |
946 | int value; |
947 | |
948 | value = ucontrol->value.integer.value[0]; |
949 | if (value < mc->min || value > mc->max) |
950 | return -EINVAL; |
951 | |
952 | if (aw88261->aw_pa->fade_step != value) { |
953 | aw88261->aw_pa->fade_step = value; |
954 | return 1; |
955 | } |
956 | |
957 | return 0; |
958 | } |
959 | |
960 | static const struct snd_kcontrol_new aw88261_controls[] = { |
961 | SOC_SINGLE_EXT("PCM Playback Volume" , AW88261_SYSCTRL2_REG, |
962 | 6, AW88261_MUTE_VOL, 0, aw88261_volume_get, |
963 | aw88261_volume_set), |
964 | SOC_SINGLE_EXT("Fade Step" , 0, 0, AW88261_MUTE_VOL, 0, |
965 | aw88261_get_fade_step, aw88261_set_fade_step), |
966 | SOC_SINGLE_EXT("Volume Ramp Up Step" , 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, |
967 | aw88261_get_fade_in_time, aw88261_set_fade_in_time), |
968 | SOC_SINGLE_EXT("Volume Ramp Down Step" , 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, |
969 | aw88261_get_fade_out_time, aw88261_set_fade_out_time), |
970 | AW88261_PROFILE_EXT("Profile Set" , aw88261_profile_info, |
971 | aw88261_profile_get, aw88261_profile_set), |
972 | }; |
973 | |
974 | static int aw88261_playback_event(struct snd_soc_dapm_widget *w, |
975 | struct snd_kcontrol *k, int event) |
976 | { |
977 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
978 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: component); |
979 | |
980 | mutex_lock(&aw88261->lock); |
981 | switch (event) { |
982 | case SND_SOC_DAPM_PRE_PMU: |
983 | aw88261_start(aw88261, sync_start: AW88261_ASYNC_START); |
984 | break; |
985 | case SND_SOC_DAPM_POST_PMD: |
986 | aw88261_dev_stop(aw_dev: aw88261->aw_pa); |
987 | break; |
988 | default: |
989 | break; |
990 | } |
991 | mutex_unlock(lock: &aw88261->lock); |
992 | |
993 | return 0; |
994 | } |
995 | |
996 | static const struct snd_soc_dapm_widget aw88261_dapm_widgets[] = { |
997 | /* playback */ |
998 | SND_SOC_DAPM_AIF_IN_E("AIF_RX" , "Speaker_Playback" , 0, 0, 0, 0, |
999 | aw88261_playback_event, |
1000 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1001 | SND_SOC_DAPM_OUTPUT("DAC Output" ), |
1002 | |
1003 | /* capture */ |
1004 | SND_SOC_DAPM_AIF_OUT("AIF_TX" , "Speaker_Capture" , 0, SND_SOC_NOPM, 0, 0), |
1005 | SND_SOC_DAPM_INPUT("ADC Input" ), |
1006 | }; |
1007 | |
1008 | static const struct snd_soc_dapm_route aw88261_audio_map[] = { |
1009 | {"DAC Output" , NULL, "AIF_RX" }, |
1010 | {"AIF_TX" , NULL, "ADC Input" }, |
1011 | }; |
1012 | |
1013 | static int aw88261_frcset_check(struct aw88261 *aw88261) |
1014 | { |
1015 | unsigned int reg_val; |
1016 | u16 temh, teml, tem; |
1017 | int ret; |
1018 | |
1019 | ret = regmap_read(map: aw88261->regmap, AW88261_EFRH3_REG, val: ®_val); |
1020 | if (ret) |
1021 | return ret; |
1022 | temh = ((u16)reg_val & (~AW88261_TEMH_MASK)); |
1023 | |
1024 | ret = regmap_read(map: aw88261->regmap, AW88261_EFRL3_REG, val: ®_val); |
1025 | if (ret) |
1026 | return ret; |
1027 | teml = ((u16)reg_val & (~AW88261_TEML_MASK)); |
1028 | |
1029 | if (aw88261->efuse_check == AW88261_EF_OR_CHECK) |
1030 | tem = (temh | teml); |
1031 | else |
1032 | tem = (temh & teml); |
1033 | |
1034 | if (tem == AW88261_DEFAULT_CFG) |
1035 | aw88261->frcset_en = AW88261_FRCSET_ENABLE; |
1036 | else |
1037 | aw88261->frcset_en = AW88261_FRCSET_DISABLE; |
1038 | |
1039 | dev_dbg(aw88261->aw_pa->dev, "tem is 0x%04x, frcset_en is %d" , |
1040 | tem, aw88261->frcset_en); |
1041 | |
1042 | return ret; |
1043 | } |
1044 | |
1045 | static int aw88261_dev_init(struct aw88261 *aw88261, struct aw_container *aw_cfg) |
1046 | { |
1047 | struct aw_device *aw_dev = aw88261->aw_pa; |
1048 | int ret; |
1049 | |
1050 | ret = aw88395_dev_cfg_load(aw_dev, aw_cfg); |
1051 | if (ret) { |
1052 | dev_err(aw_dev->dev, "aw_dev acf parse failed" ); |
1053 | return -EINVAL; |
1054 | } |
1055 | |
1056 | ret = regmap_write(map: aw_dev->regmap, AW88261_ID_REG, AW88261_SOFT_RESET_VALUE); |
1057 | if (ret) |
1058 | return ret; |
1059 | |
1060 | aw_dev->fade_in_time = AW88261_500_US; |
1061 | aw_dev->fade_out_time = AW88261_500_US; |
1062 | aw_dev->prof_cur = AW88261_INIT_PROFILE; |
1063 | aw_dev->prof_index = AW88261_INIT_PROFILE; |
1064 | |
1065 | ret = aw88261_dev_fw_update(aw88261); |
1066 | if (ret) { |
1067 | dev_err(aw_dev->dev, "fw update failed ret = %d\n" , ret); |
1068 | return ret; |
1069 | } |
1070 | |
1071 | ret = aw88261_frcset_check(aw88261); |
1072 | if (ret) { |
1073 | dev_err(aw_dev->dev, "aw88261_frcset_check ret = %d\n" , ret); |
1074 | return ret; |
1075 | } |
1076 | |
1077 | aw88261_dev_clear_int_status(aw_dev); |
1078 | |
1079 | aw88261_dev_uls_hmute(aw_dev, uls_hmute: true); |
1080 | |
1081 | aw88261_dev_mute(aw_dev, is_mute: true); |
1082 | |
1083 | aw88261_dev_i2s_tx_enable(aw_dev, flag: false); |
1084 | |
1085 | usleep_range(min: AW88261_1000_US, max: AW88261_1000_US + 100); |
1086 | |
1087 | aw88261_dev_amppd(aw_dev, amppd: true); |
1088 | |
1089 | aw88261_dev_pwd(aw_dev, pwd: true); |
1090 | |
1091 | return 0; |
1092 | } |
1093 | |
1094 | static int aw88261_request_firmware_file(struct aw88261 *aw88261) |
1095 | { |
1096 | const struct firmware *cont = NULL; |
1097 | int ret; |
1098 | |
1099 | aw88261->aw_pa->fw_status = AW88261_DEV_FW_FAILED; |
1100 | |
1101 | ret = request_firmware(fw: &cont, AW88261_ACF_FILE, device: aw88261->aw_pa->dev); |
1102 | if (ret) |
1103 | return dev_err_probe(dev: aw88261->aw_pa->dev, err: ret, |
1104 | fmt: "load [%s] failed!" , AW88261_ACF_FILE); |
1105 | |
1106 | dev_info(aw88261->aw_pa->dev, "loaded %s - size: %zu\n" , |
1107 | AW88261_ACF_FILE, cont ? cont->size : 0); |
1108 | |
1109 | aw88261->aw_cfg = devm_kzalloc(dev: aw88261->aw_pa->dev, size: cont->size + sizeof(int), GFP_KERNEL); |
1110 | if (!aw88261->aw_cfg) { |
1111 | release_firmware(fw: cont); |
1112 | return -ENOMEM; |
1113 | } |
1114 | aw88261->aw_cfg->len = (int)cont->size; |
1115 | memcpy(aw88261->aw_cfg->data, cont->data, cont->size); |
1116 | release_firmware(fw: cont); |
1117 | |
1118 | ret = aw88395_dev_load_acf_check(aw_dev: aw88261->aw_pa, aw_cfg: aw88261->aw_cfg); |
1119 | if (ret) { |
1120 | dev_err(aw88261->aw_pa->dev, "load [%s] failed !" , AW88261_ACF_FILE); |
1121 | return ret; |
1122 | } |
1123 | |
1124 | mutex_lock(&aw88261->lock); |
1125 | /* aw device init */ |
1126 | ret = aw88261_dev_init(aw88261, aw_cfg: aw88261->aw_cfg); |
1127 | if (ret) |
1128 | dev_err(aw88261->aw_pa->dev, "dev init failed" ); |
1129 | mutex_unlock(lock: &aw88261->lock); |
1130 | |
1131 | return ret; |
1132 | } |
1133 | |
1134 | static int aw88261_codec_probe(struct snd_soc_component *component) |
1135 | { |
1136 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
1137 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: component); |
1138 | int ret; |
1139 | |
1140 | INIT_DELAYED_WORK(&aw88261->start_work, aw88261_startup_work); |
1141 | |
1142 | ret = aw88261_request_firmware_file(aw88261); |
1143 | if (ret) |
1144 | return dev_err_probe(dev: aw88261->aw_pa->dev, err: ret, |
1145 | fmt: "aw88261_request_firmware_file failed\n" ); |
1146 | |
1147 | /* add widgets */ |
1148 | ret = snd_soc_dapm_new_controls(dapm, widget: aw88261_dapm_widgets, |
1149 | ARRAY_SIZE(aw88261_dapm_widgets)); |
1150 | if (ret) |
1151 | return ret; |
1152 | |
1153 | /* add route */ |
1154 | ret = snd_soc_dapm_add_routes(dapm, route: aw88261_audio_map, |
1155 | ARRAY_SIZE(aw88261_audio_map)); |
1156 | if (ret) |
1157 | return ret; |
1158 | |
1159 | ret = snd_soc_add_component_controls(component, controls: aw88261_controls, |
1160 | ARRAY_SIZE(aw88261_controls)); |
1161 | |
1162 | return ret; |
1163 | } |
1164 | |
1165 | static void aw88261_codec_remove(struct snd_soc_component *aw_codec) |
1166 | { |
1167 | struct aw88261 *aw88261 = snd_soc_component_get_drvdata(c: aw_codec); |
1168 | |
1169 | cancel_delayed_work_sync(dwork: &aw88261->start_work); |
1170 | } |
1171 | |
1172 | static const struct snd_soc_component_driver soc_codec_dev_aw88261 = { |
1173 | .probe = aw88261_codec_probe, |
1174 | .remove = aw88261_codec_remove, |
1175 | }; |
1176 | |
1177 | static void aw88261_parse_channel_dt(struct aw88261 *aw88261) |
1178 | { |
1179 | struct aw_device *aw_dev = aw88261->aw_pa; |
1180 | struct device_node *np = aw_dev->dev->of_node; |
1181 | u32 channel_value = AW88261_DEV_DEFAULT_CH; |
1182 | |
1183 | of_property_read_u32(np, propname: "awinic,audio-channel" , out_value: &channel_value); |
1184 | aw88261->phase_sync = of_property_read_bool(np, propname: "awinic,sync-flag" ); |
1185 | |
1186 | aw_dev->channel = channel_value; |
1187 | } |
1188 | |
1189 | static int aw88261_init(struct aw88261 **aw88261, struct i2c_client *i2c, struct regmap *regmap) |
1190 | { |
1191 | struct aw_device *aw_dev; |
1192 | unsigned int chip_id; |
1193 | int ret; |
1194 | |
1195 | /* read chip id */ |
1196 | ret = regmap_read(map: regmap, AW88261_ID_REG, val: &chip_id); |
1197 | if (ret) { |
1198 | dev_err(&i2c->dev, "%s read chipid error. ret = %d" , __func__, ret); |
1199 | return ret; |
1200 | } |
1201 | if (chip_id != AW88261_CHIP_ID) { |
1202 | dev_err(&i2c->dev, "unsupported device" ); |
1203 | return -ENXIO; |
1204 | } |
1205 | |
1206 | dev_info(&i2c->dev, "chip id = %x\n" , chip_id); |
1207 | |
1208 | aw_dev = devm_kzalloc(dev: &i2c->dev, size: sizeof(*aw_dev), GFP_KERNEL); |
1209 | if (!aw_dev) |
1210 | return -ENOMEM; |
1211 | |
1212 | (*aw88261)->aw_pa = aw_dev; |
1213 | aw_dev->i2c = i2c; |
1214 | aw_dev->regmap = regmap; |
1215 | aw_dev->dev = &i2c->dev; |
1216 | aw_dev->chip_id = AW88261_CHIP_ID; |
1217 | aw_dev->acf = NULL; |
1218 | aw_dev->prof_info.prof_desc = NULL; |
1219 | aw_dev->prof_info.count = 0; |
1220 | aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; |
1221 | aw_dev->channel = 0; |
1222 | aw_dev->fw_status = AW88261_DEV_FW_FAILED; |
1223 | aw_dev->fade_step = AW88261_VOLUME_STEP_DB; |
1224 | aw_dev->volume_desc.ctl_volume = AW88261_VOL_DEFAULT_VALUE; |
1225 | aw_dev->volume_desc.mute_volume = AW88261_MUTE_VOL; |
1226 | aw88261_parse_channel_dt(aw88261: *aw88261); |
1227 | |
1228 | return ret; |
1229 | } |
1230 | |
1231 | static int aw88261_i2c_probe(struct i2c_client *i2c) |
1232 | { |
1233 | struct aw88261 *aw88261; |
1234 | int ret; |
1235 | |
1236 | ret = i2c_check_functionality(adap: i2c->adapter, I2C_FUNC_I2C); |
1237 | if (!ret) |
1238 | return dev_err_probe(dev: &i2c->dev, err: -ENXIO, fmt: "check_functionality failed" ); |
1239 | |
1240 | aw88261 = devm_kzalloc(dev: &i2c->dev, size: sizeof(*aw88261), GFP_KERNEL); |
1241 | if (!aw88261) |
1242 | return -ENOMEM; |
1243 | |
1244 | mutex_init(&aw88261->lock); |
1245 | |
1246 | i2c_set_clientdata(client: i2c, data: aw88261); |
1247 | |
1248 | aw88261->regmap = devm_regmap_init_i2c(i2c, &aw88261_remap_config); |
1249 | if (IS_ERR(ptr: aw88261->regmap)) { |
1250 | ret = PTR_ERR(ptr: aw88261->regmap); |
1251 | return dev_err_probe(dev: &i2c->dev, err: ret, fmt: "failed to init regmap: %d\n" , ret); |
1252 | } |
1253 | |
1254 | /* aw pa init */ |
1255 | ret = aw88261_init(aw88261: &aw88261, i2c, regmap: aw88261->regmap); |
1256 | if (ret) |
1257 | return ret; |
1258 | |
1259 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
1260 | component_driver: &soc_codec_dev_aw88261, |
1261 | dai_drv: aw88261_dai, ARRAY_SIZE(aw88261_dai)); |
1262 | if (ret) |
1263 | dev_err(&i2c->dev, "failed to register aw88261: %d" , ret); |
1264 | |
1265 | return ret; |
1266 | } |
1267 | |
1268 | static const struct i2c_device_id aw88261_i2c_id[] = { |
1269 | { AW88261_I2C_NAME, 0 }, |
1270 | { } |
1271 | }; |
1272 | MODULE_DEVICE_TABLE(i2c, aw88261_i2c_id); |
1273 | |
1274 | static struct i2c_driver aw88261_i2c_driver = { |
1275 | .driver = { |
1276 | .name = AW88261_I2C_NAME, |
1277 | }, |
1278 | .probe = aw88261_i2c_probe, |
1279 | .id_table = aw88261_i2c_id, |
1280 | }; |
1281 | module_i2c_driver(aw88261_i2c_driver); |
1282 | |
1283 | MODULE_DESCRIPTION("ASoC AW88261 Smart PA Driver" ); |
1284 | MODULE_LICENSE("GPL v2" ); |
1285 | |