1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // |
3 | // aw88395_device.c -- AW88395 function for ALSA Audio Driver |
4 | // |
5 | // Copyright (c) 2022-2023 AWINIC Technology CO., LTD |
6 | // |
7 | // Author: Bruce zhao <zhaolei@awinic.com> |
8 | // Author: Ben Yi <yijiangtao@awinic.com> |
9 | // |
10 | |
11 | #include <linux/crc32.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/regmap.h> |
14 | #include "aw88395_device.h" |
15 | #include "aw88395_reg.h" |
16 | |
17 | static int aw_dev_dsp_write_16bit(struct aw_device *aw_dev, |
18 | unsigned short dsp_addr, unsigned int dsp_data) |
19 | { |
20 | int ret; |
21 | |
22 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: dsp_addr); |
23 | if (ret) { |
24 | dev_err(aw_dev->dev, "%s write addr error, ret=%d" , __func__, ret); |
25 | return ret; |
26 | } |
27 | |
28 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMDAT_REG, val: (u16)dsp_data); |
29 | if (ret) { |
30 | dev_err(aw_dev->dev, "%s write data error, ret=%d" , __func__, ret); |
31 | return ret; |
32 | } |
33 | |
34 | return 0; |
35 | } |
36 | |
37 | static int aw_dev_dsp_write_32bit(struct aw_device *aw_dev, |
38 | unsigned short dsp_addr, unsigned int dsp_data) |
39 | { |
40 | u16 temp_data; |
41 | int ret; |
42 | |
43 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: dsp_addr); |
44 | if (ret) { |
45 | dev_err(aw_dev->dev, "%s write addr error, ret=%d" , __func__, ret); |
46 | return ret; |
47 | } |
48 | |
49 | temp_data = dsp_data & AW88395_DSP_16_DATA_MASK; |
50 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMDAT_REG, val: (u16)temp_data); |
51 | if (ret) { |
52 | dev_err(aw_dev->dev, "%s write datal error, ret=%d" , __func__, ret); |
53 | return ret; |
54 | } |
55 | |
56 | temp_data = dsp_data >> 16; |
57 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMDAT_REG, val: (u16)temp_data); |
58 | if (ret) { |
59 | dev_err(aw_dev->dev, "%s write datah error, ret=%d" , __func__, ret); |
60 | return ret; |
61 | } |
62 | |
63 | return 0; |
64 | } |
65 | |
66 | static int aw_dev_dsp_write(struct aw_device *aw_dev, |
67 | unsigned short dsp_addr, unsigned int dsp_data, unsigned char data_type) |
68 | { |
69 | u32 reg_value; |
70 | int ret; |
71 | |
72 | mutex_lock(&aw_dev->dsp_lock); |
73 | switch (data_type) { |
74 | case AW88395_DSP_16_DATA: |
75 | ret = aw_dev_dsp_write_16bit(aw_dev, dsp_addr, dsp_data); |
76 | if (ret) |
77 | dev_err(aw_dev->dev, "write dsp_addr[0x%x] 16-bit dsp_data[0x%x] failed" , |
78 | (u32)dsp_addr, dsp_data); |
79 | break; |
80 | case AW88395_DSP_32_DATA: |
81 | ret = aw_dev_dsp_write_32bit(aw_dev, dsp_addr, dsp_data); |
82 | if (ret) |
83 | dev_err(aw_dev->dev, "write dsp_addr[0x%x] 32-bit dsp_data[0x%x] failed" , |
84 | (u32)dsp_addr, dsp_data); |
85 | break; |
86 | default: |
87 | dev_err(aw_dev->dev, "data type[%d] unsupported" , data_type); |
88 | ret = -EINVAL; |
89 | break; |
90 | } |
91 | |
92 | /* clear dsp chip select state*/ |
93 | if (regmap_read(map: aw_dev->regmap, AW88395_ID_REG, val: ®_value)) |
94 | dev_err(aw_dev->dev, "%s fail to clear chip state. Err=%d\n" , __func__, ret); |
95 | mutex_unlock(lock: &aw_dev->dsp_lock); |
96 | |
97 | return ret; |
98 | } |
99 | |
100 | static int aw_dev_dsp_read_16bit(struct aw_device *aw_dev, |
101 | unsigned short dsp_addr, unsigned int *dsp_data) |
102 | { |
103 | unsigned int temp_data; |
104 | int ret; |
105 | |
106 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: dsp_addr); |
107 | if (ret) { |
108 | dev_err(aw_dev->dev, "%s write error, ret=%d" , __func__, ret); |
109 | return ret; |
110 | } |
111 | |
112 | ret = regmap_read(map: aw_dev->regmap, AW88395_DSPMDAT_REG, val: &temp_data); |
113 | if (ret) { |
114 | dev_err(aw_dev->dev, "%s read error, ret=%d" , __func__, ret); |
115 | return ret; |
116 | } |
117 | *dsp_data = temp_data; |
118 | |
119 | return 0; |
120 | } |
121 | |
122 | static int aw_dev_dsp_read_32bit(struct aw_device *aw_dev, |
123 | unsigned short dsp_addr, unsigned int *dsp_data) |
124 | { |
125 | unsigned int temp_data; |
126 | int ret; |
127 | |
128 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: dsp_addr); |
129 | if (ret) { |
130 | dev_err(aw_dev->dev, "%s write error, ret=%d" , __func__, ret); |
131 | return ret; |
132 | } |
133 | |
134 | ret = regmap_read(map: aw_dev->regmap, AW88395_DSPMDAT_REG, val: &temp_data); |
135 | if (ret) { |
136 | dev_err(aw_dev->dev, "%s read error, ret=%d" , __func__, ret); |
137 | return ret; |
138 | } |
139 | *dsp_data = temp_data; |
140 | |
141 | ret = regmap_read(map: aw_dev->regmap, AW88395_DSPMDAT_REG, val: &temp_data); |
142 | if (ret) { |
143 | dev_err(aw_dev->dev, "%s read error, ret=%d" , __func__, ret); |
144 | return ret; |
145 | } |
146 | *dsp_data |= (temp_data << 16); |
147 | |
148 | return 0; |
149 | } |
150 | |
151 | static int aw_dev_dsp_read(struct aw_device *aw_dev, |
152 | unsigned short dsp_addr, unsigned int *dsp_data, unsigned char data_type) |
153 | { |
154 | u32 reg_value; |
155 | int ret; |
156 | |
157 | mutex_lock(&aw_dev->dsp_lock); |
158 | switch (data_type) { |
159 | case AW88395_DSP_16_DATA: |
160 | ret = aw_dev_dsp_read_16bit(aw_dev, dsp_addr, dsp_data); |
161 | if (ret) |
162 | dev_err(aw_dev->dev, "read dsp_addr[0x%x] 16-bit dsp_data[0x%x] failed" , |
163 | (u32)dsp_addr, *dsp_data); |
164 | break; |
165 | case AW88395_DSP_32_DATA: |
166 | ret = aw_dev_dsp_read_32bit(aw_dev, dsp_addr, dsp_data); |
167 | if (ret) |
168 | dev_err(aw_dev->dev, "read dsp_addr[0x%x] 32r-bit dsp_data[0x%x] failed" , |
169 | (u32)dsp_addr, *dsp_data); |
170 | break; |
171 | default: |
172 | dev_err(aw_dev->dev, "data type[%d] unsupported" , data_type); |
173 | ret = -EINVAL; |
174 | break; |
175 | } |
176 | |
177 | /* clear dsp chip select state*/ |
178 | if (regmap_read(map: aw_dev->regmap, AW88395_ID_REG, val: ®_value)) |
179 | dev_err(aw_dev->dev, "%s fail to clear chip state. Err=%d\n" , __func__, ret); |
180 | mutex_unlock(lock: &aw_dev->dsp_lock); |
181 | |
182 | return ret; |
183 | } |
184 | |
185 | |
186 | static int aw_dev_read_chipid(struct aw_device *aw_dev, u16 *chip_id) |
187 | { |
188 | int reg_val; |
189 | int ret; |
190 | |
191 | ret = regmap_read(map: aw_dev->regmap, AW88395_CHIP_ID_REG, val: ®_val); |
192 | if (ret) { |
193 | dev_err(aw_dev->dev, "%s read chipid error. ret = %d" , __func__, ret); |
194 | return ret; |
195 | } |
196 | |
197 | dev_info(aw_dev->dev, "chip id = %x\n" , reg_val); |
198 | *chip_id = reg_val; |
199 | |
200 | return 0; |
201 | } |
202 | |
203 | static unsigned int reg_val_to_db(unsigned int value) |
204 | { |
205 | return (((value >> AW88395_VOL_6DB_START) * AW88395_VOLUME_STEP_DB) + |
206 | ((value & 0x3f) % AW88395_VOLUME_STEP_DB)); |
207 | } |
208 | |
209 | static unsigned short db_to_reg_val(unsigned short value) |
210 | { |
211 | return (((value / AW88395_VOLUME_STEP_DB) << AW88395_VOL_6DB_START) + |
212 | (value % AW88395_VOLUME_STEP_DB)); |
213 | } |
214 | |
215 | static int aw_dev_dsp_fw_check(struct aw_device *aw_dev) |
216 | { |
217 | struct aw_sec_data_desc *dsp_fw_desc; |
218 | struct aw_prof_desc *set_prof_desc; |
219 | u16 base_addr = AW88395_DSP_FW_ADDR; |
220 | u16 addr = base_addr; |
221 | u32 dsp_val; |
222 | u16 bin_val; |
223 | int ret, i; |
224 | |
225 | ret = aw88395_dev_get_prof_data(aw_dev, index: aw_dev->prof_cur, prof_desc: &set_prof_desc); |
226 | if (ret) |
227 | return ret; |
228 | |
229 | /* update reg */ |
230 | dsp_fw_desc = &set_prof_desc->sec_desc[AW88395_DATA_TYPE_DSP_FW]; |
231 | |
232 | for (i = 0; i < AW88395_FW_CHECK_PART; i++) { |
233 | ret = aw_dev_dsp_read(aw_dev, dsp_addr: addr, dsp_data: &dsp_val, data_type: AW88395_DSP_16_DATA); |
234 | if (ret) { |
235 | dev_err(aw_dev->dev, "dsp read failed" ); |
236 | return ret; |
237 | } |
238 | |
239 | bin_val = be16_to_cpup(p: (void *)&dsp_fw_desc->data[2 * (addr - base_addr)]); |
240 | |
241 | if (dsp_val != bin_val) { |
242 | dev_err(aw_dev->dev, "fw check failed, addr[0x%x], read[0x%x] != bindata[0x%x]" , |
243 | addr, dsp_val, bin_val); |
244 | return -EINVAL; |
245 | } |
246 | |
247 | addr += (dsp_fw_desc->len / 2) / AW88395_FW_CHECK_PART; |
248 | if ((addr - base_addr) > dsp_fw_desc->len) { |
249 | dev_err(aw_dev->dev, "fw check failed, addr[0x%x] too large" , addr); |
250 | return -EINVAL; |
251 | } |
252 | } |
253 | |
254 | return 0; |
255 | } |
256 | |
257 | static int aw_dev_set_volume(struct aw_device *aw_dev, unsigned int value) |
258 | { |
259 | struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; |
260 | unsigned int reg_value; |
261 | u16 real_value, volume; |
262 | int ret; |
263 | |
264 | volume = min((value + vol_desc->init_volume), (unsigned int)AW88395_MUTE_VOL); |
265 | real_value = db_to_reg_val(value: volume); |
266 | |
267 | /* cal real value */ |
268 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSCTRL2_REG, val: ®_value); |
269 | if (ret) |
270 | return ret; |
271 | |
272 | dev_dbg(aw_dev->dev, "value 0x%x , reg:0x%x" , value, real_value); |
273 | |
274 | /* [15 : 6] volume */ |
275 | real_value = (real_value << AW88395_VOL_START_BIT) | (reg_value & AW88395_VOL_MASK); |
276 | |
277 | /* write value */ |
278 | ret = regmap_write(map: aw_dev->regmap, AW88395_SYSCTRL2_REG, val: real_value); |
279 | |
280 | return ret; |
281 | } |
282 | |
283 | void aw88395_dev_set_volume(struct aw_device *aw_dev, unsigned short set_vol) |
284 | { |
285 | int ret; |
286 | |
287 | ret = aw_dev_set_volume(aw_dev, value: set_vol); |
288 | if (ret) |
289 | dev_dbg(aw_dev->dev, "set volume failed" ); |
290 | } |
291 | EXPORT_SYMBOL_GPL(aw88395_dev_set_volume); |
292 | |
293 | static void aw_dev_fade_in(struct aw_device *aw_dev) |
294 | { |
295 | struct aw_volume_desc *desc = &aw_dev->volume_desc; |
296 | u16 fade_in_vol = desc->ctl_volume; |
297 | int fade_step = aw_dev->fade_step; |
298 | int i; |
299 | |
300 | if (fade_step == 0 || aw_dev->fade_in_time == 0) { |
301 | aw_dev_set_volume(aw_dev, value: fade_in_vol); |
302 | return; |
303 | } |
304 | |
305 | for (i = AW88395_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { |
306 | aw_dev_set_volume(aw_dev, value: i); |
307 | usleep_range(min: aw_dev->fade_in_time, max: aw_dev->fade_in_time + 10); |
308 | } |
309 | |
310 | if (i != fade_in_vol) |
311 | aw_dev_set_volume(aw_dev, value: fade_in_vol); |
312 | } |
313 | |
314 | static void aw_dev_fade_out(struct aw_device *aw_dev) |
315 | { |
316 | struct aw_volume_desc *desc = &aw_dev->volume_desc; |
317 | int fade_step = aw_dev->fade_step; |
318 | int i; |
319 | |
320 | if (fade_step == 0 || aw_dev->fade_out_time == 0) { |
321 | aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL); |
322 | return; |
323 | } |
324 | |
325 | for (i = desc->ctl_volume; i <= AW88395_MUTE_VOL; i += fade_step) { |
326 | aw_dev_set_volume(aw_dev, value: i); |
327 | usleep_range(min: aw_dev->fade_out_time, max: aw_dev->fade_out_time + 10); |
328 | } |
329 | |
330 | if (i != AW88395_MUTE_VOL) { |
331 | aw_dev_set_volume(aw_dev, AW88395_MUTE_VOL); |
332 | usleep_range(min: aw_dev->fade_out_time, max: aw_dev->fade_out_time + 10); |
333 | } |
334 | } |
335 | |
336 | static int aw_dev_modify_dsp_cfg(struct aw_device *aw_dev, |
337 | unsigned int addr, unsigned int dsp_data, unsigned char data_type) |
338 | { |
339 | struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; |
340 | unsigned int addr_offset; |
341 | __le16 data1; |
342 | __le32 data2; |
343 | |
344 | dev_dbg(aw_dev->dev, "addr:0x%x, dsp_data:0x%x" , addr, dsp_data); |
345 | |
346 | addr_offset = (addr - AW88395_DSP_CFG_ADDR) * 2; |
347 | if (addr_offset > crc_dsp_cfg->len) { |
348 | dev_err(aw_dev->dev, "addr_offset[%d] > crc_dsp_cfg->len[%d]" , |
349 | addr_offset, crc_dsp_cfg->len); |
350 | return -EINVAL; |
351 | } |
352 | switch (data_type) { |
353 | case AW88395_DSP_16_DATA: |
354 | data1 = cpu_to_le16((u16)dsp_data); |
355 | memcpy(crc_dsp_cfg->data + addr_offset, (u8 *)&data1, 2); |
356 | break; |
357 | case AW88395_DSP_32_DATA: |
358 | data2 = cpu_to_le32(dsp_data); |
359 | memcpy(crc_dsp_cfg->data + addr_offset, (u8 *)&data2, 4); |
360 | break; |
361 | default: |
362 | dev_err(aw_dev->dev, "data type[%d] unsupported" , data_type); |
363 | return -EINVAL; |
364 | } |
365 | |
366 | return 0; |
367 | } |
368 | |
369 | static int aw_dev_dsp_set_cali_re(struct aw_device *aw_dev) |
370 | { |
371 | u32 cali_re; |
372 | int ret; |
373 | |
374 | cali_re = AW88395_SHOW_RE_TO_DSP_RE((aw_dev->cali_desc.cali_re + |
375 | aw_dev->cali_desc.ra), AW88395_DSP_RE_SHIFT); |
376 | |
377 | /* set cali re to device */ |
378 | ret = aw_dev_dsp_write(aw_dev, |
379 | AW88395_DSP_REG_CFG_ADPZ_RE, dsp_data: cali_re, data_type: AW88395_DSP_32_DATA); |
380 | if (ret) { |
381 | dev_err(aw_dev->dev, "set cali re error" ); |
382 | return ret; |
383 | } |
384 | |
385 | ret = aw_dev_modify_dsp_cfg(aw_dev, AW88395_DSP_REG_CFG_ADPZ_RE, |
386 | dsp_data: cali_re, data_type: AW88395_DSP_32_DATA); |
387 | if (ret) |
388 | dev_err(aw_dev->dev, "modify dsp cfg failed" ); |
389 | |
390 | return ret; |
391 | } |
392 | |
393 | static void aw_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) |
394 | { |
395 | int ret; |
396 | |
397 | if (flag) { |
398 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_I2SCFG1_REG, |
399 | mask: ~AW88395_I2STXEN_MASK, AW88395_I2STXEN_ENABLE_VALUE); |
400 | } else { |
401 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_I2SCFG1_REG, |
402 | mask: ~AW88395_I2STXEN_MASK, AW88395_I2STXEN_DISABLE_VALUE); |
403 | } |
404 | |
405 | if (ret) |
406 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
407 | } |
408 | |
409 | static int aw_dev_dsp_set_crc32(struct aw_device *aw_dev) |
410 | { |
411 | struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; |
412 | u32 crc_value, crc_data_len; |
413 | |
414 | /* get crc data len */ |
415 | crc_data_len = (AW88395_DSP_REG_CRC_ADDR - AW88395_DSP_CFG_ADDR) * 2; |
416 | if (crc_data_len > crc_dsp_cfg->len) { |
417 | dev_err(aw_dev->dev, "crc data len :%d > cfg_data len:%d" , |
418 | crc_data_len, crc_dsp_cfg->len); |
419 | return -EINVAL; |
420 | } |
421 | |
422 | if (crc_data_len & 0x11) { |
423 | dev_err(aw_dev->dev, "The crc data len :%d unsupport" , crc_data_len); |
424 | return -EINVAL; |
425 | } |
426 | |
427 | crc_value = __crc32c_le(crc: 0xFFFFFFFF, p: crc_dsp_cfg->data, len: crc_data_len) ^ 0xFFFFFFFF; |
428 | |
429 | return aw_dev_dsp_write(aw_dev, AW88395_DSP_REG_CRC_ADDR, dsp_data: crc_value, |
430 | data_type: AW88395_DSP_32_DATA); |
431 | } |
432 | |
433 | static void aw_dev_dsp_check_crc_enable(struct aw_device *aw_dev, bool flag) |
434 | { |
435 | int ret; |
436 | |
437 | if (flag) { |
438 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_HAGCCFG7_REG, |
439 | mask: ~AW88395_AGC_DSP_CTL_MASK, AW88395_AGC_DSP_CTL_ENABLE_VALUE); |
440 | } else { |
441 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_HAGCCFG7_REG, |
442 | mask: ~AW88395_AGC_DSP_CTL_MASK, AW88395_AGC_DSP_CTL_DISABLE_VALUE); |
443 | } |
444 | if (ret) |
445 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
446 | } |
447 | |
448 | static int aw_dev_dsp_check_st(struct aw_device *aw_dev) |
449 | { |
450 | unsigned int reg_val; |
451 | int ret; |
452 | int i; |
453 | |
454 | for (i = 0; i < AW88395_DSP_ST_CHECK_MAX; i++) { |
455 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSST_REG, val: ®_val); |
456 | if (ret) { |
457 | dev_err(aw_dev->dev, "read reg0x%x failed" , AW88395_SYSST_REG); |
458 | continue; |
459 | } |
460 | |
461 | if ((reg_val & (~AW88395_DSPS_MASK)) != AW88395_DSPS_NORMAL_VALUE) { |
462 | dev_err(aw_dev->dev, "check dsp st fail,reg_val:0x%04x" , reg_val); |
463 | ret = -EPERM; |
464 | continue; |
465 | } else { |
466 | dev_dbg(aw_dev->dev, "dsp st check ok, reg_val:0x%04x" , reg_val); |
467 | return 0; |
468 | } |
469 | } |
470 | |
471 | return ret; |
472 | } |
473 | |
474 | static void aw_dev_dsp_enable(struct aw_device *aw_dev, bool is_enable) |
475 | { |
476 | int ret; |
477 | |
478 | if (is_enable) { |
479 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
480 | mask: ~AW88395_DSPBY_MASK, AW88395_DSPBY_WORKING_VALUE); |
481 | if (ret) |
482 | dev_dbg(aw_dev->dev, "enable dsp failed" ); |
483 | } else { |
484 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
485 | mask: ~AW88395_DSPBY_MASK, AW88395_DSPBY_BYPASS_VALUE); |
486 | if (ret) |
487 | dev_dbg(aw_dev->dev, "disable dsp failed" ); |
488 | } |
489 | } |
490 | |
491 | static int aw_dev_dsp_check_crc32(struct aw_device *aw_dev) |
492 | { |
493 | int ret; |
494 | |
495 | if (aw_dev->dsp_cfg == AW88395_DEV_DSP_BYPASS) { |
496 | dev_info(aw_dev->dev, "dsp bypass" ); |
497 | return 0; |
498 | } |
499 | |
500 | ret = aw_dev_dsp_set_crc32(aw_dev); |
501 | if (ret) { |
502 | dev_err(aw_dev->dev, "set dsp crc32 failed" ); |
503 | return ret; |
504 | } |
505 | |
506 | aw_dev_dsp_check_crc_enable(aw_dev, flag: true); |
507 | |
508 | /* dsp enable */ |
509 | aw_dev_dsp_enable(aw_dev, is_enable: true); |
510 | usleep_range(min: AW88395_5000_US, max: AW88395_5000_US + 100); |
511 | |
512 | ret = aw_dev_dsp_check_st(aw_dev); |
513 | if (ret) { |
514 | dev_err(aw_dev->dev, "check crc32 fail" ); |
515 | } else { |
516 | aw_dev_dsp_check_crc_enable(aw_dev, flag: false); |
517 | aw_dev->dsp_crc_st = AW88395_DSP_CRC_OK; |
518 | } |
519 | |
520 | return ret; |
521 | } |
522 | |
523 | static void aw_dev_pwd(struct aw_device *aw_dev, bool pwd) |
524 | { |
525 | int ret; |
526 | |
527 | if (pwd) { |
528 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
529 | mask: ~AW88395_PWDN_MASK, AW88395_PWDN_POWER_DOWN_VALUE); |
530 | } else { |
531 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
532 | mask: ~AW88395_PWDN_MASK, AW88395_PWDN_WORKING_VALUE); |
533 | } |
534 | if (ret) |
535 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
536 | } |
537 | |
538 | static void aw_dev_amppd(struct aw_device *aw_dev, bool amppd) |
539 | { |
540 | int ret; |
541 | |
542 | if (amppd) { |
543 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
544 | mask: ~AW88395_AMPPD_MASK, AW88395_AMPPD_POWER_DOWN_VALUE); |
545 | } else { |
546 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
547 | mask: ~AW88395_AMPPD_MASK, AW88395_AMPPD_WORKING_VALUE); |
548 | } |
549 | if (ret) |
550 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
551 | } |
552 | |
553 | void aw88395_dev_mute(struct aw_device *aw_dev, bool is_mute) |
554 | { |
555 | int ret; |
556 | |
557 | if (is_mute) { |
558 | aw_dev_fade_out(aw_dev); |
559 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
560 | mask: ~AW88395_HMUTE_MASK, AW88395_HMUTE_ENABLE_VALUE); |
561 | } else { |
562 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_SYSCTRL_REG, |
563 | mask: ~AW88395_HMUTE_MASK, AW88395_HMUTE_DISABLE_VALUE); |
564 | aw_dev_fade_in(aw_dev); |
565 | } |
566 | |
567 | if (ret) |
568 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
569 | } |
570 | EXPORT_SYMBOL_GPL(aw88395_dev_mute); |
571 | |
572 | static int aw_dev_get_icalk(struct aw_device *aw_dev, int16_t *icalk) |
573 | { |
574 | unsigned int reg_val; |
575 | u16 reg_icalk; |
576 | int ret; |
577 | |
578 | ret = regmap_read(map: aw_dev->regmap, AW88395_EFRM2_REG, val: ®_val); |
579 | if (ret) |
580 | return ret; |
581 | |
582 | reg_icalk = reg_val & (~AW88395_EF_ISN_GESLP_MASK); |
583 | |
584 | if (reg_icalk & (~AW88395_EF_ISN_GESLP_SIGN_MASK)) |
585 | reg_icalk = reg_icalk | AW88395_EF_ISN_GESLP_SIGN_NEG; |
586 | |
587 | *icalk = (int16_t)reg_icalk; |
588 | |
589 | return ret; |
590 | } |
591 | |
592 | static int aw_dev_get_vcalk(struct aw_device *aw_dev, int16_t *vcalk) |
593 | { |
594 | unsigned int reg_val; |
595 | u16 reg_vcalk; |
596 | int ret; |
597 | |
598 | ret = regmap_read(map: aw_dev->regmap, AW88395_EFRH_REG, val: ®_val); |
599 | if (ret) |
600 | return ret; |
601 | |
602 | reg_val = reg_val >> AW88395_EF_VSENSE_GAIN_SHIFT; |
603 | |
604 | reg_vcalk = (u16)reg_val & (~AW88395_EF_VSN_GESLP_MASK); |
605 | |
606 | if (reg_vcalk & (~AW88395_EF_VSN_GESLP_SIGN_MASK)) |
607 | reg_vcalk = reg_vcalk | AW88395_EF_VSN_GESLP_SIGN_NEG; |
608 | |
609 | *vcalk = (int16_t)reg_vcalk; |
610 | |
611 | return ret; |
612 | } |
613 | |
614 | static int aw_dev_get_vcalk_dac(struct aw_device *aw_dev, int16_t *vcalk) |
615 | { |
616 | unsigned int reg_val; |
617 | u16 reg_vcalk; |
618 | int ret; |
619 | |
620 | ret = regmap_read(map: aw_dev->regmap, AW88395_EFRM2_REG, val: ®_val); |
621 | if (ret) |
622 | return ret; |
623 | |
624 | reg_vcalk = reg_val >> AW88395_EF_DAC_GESLP_SHIFT; |
625 | |
626 | if (reg_vcalk & AW88395_EF_DAC_GESLP_SIGN_MASK) |
627 | reg_vcalk = reg_vcalk | AW88395_EF_DAC_GESLP_SIGN_NEG; |
628 | |
629 | *vcalk = (int16_t)reg_vcalk; |
630 | |
631 | return ret; |
632 | } |
633 | |
634 | static int aw_dev_vsense_select(struct aw_device *aw_dev, int *vsense_select) |
635 | { |
636 | unsigned int vsense_reg_val; |
637 | int ret; |
638 | |
639 | ret = regmap_read(map: aw_dev->regmap, AW88395_I2SCFG3_REG, val: &vsense_reg_val); |
640 | if (ret) { |
641 | dev_err(aw_dev->dev, "read vsense_reg_val failed" ); |
642 | return ret; |
643 | } |
644 | dev_dbg(aw_dev->dev, "vsense_reg = 0x%x" , vsense_reg_val); |
645 | |
646 | if (vsense_reg_val & (~AW88395_VDSEL_MASK)) { |
647 | *vsense_select = AW88395_DEV_VDSEL_VSENSE; |
648 | dev_dbg(aw_dev->dev, "vsense outside" ); |
649 | } else { |
650 | *vsense_select = AW88395_DEV_VDSEL_DAC; |
651 | dev_dbg(aw_dev->dev, "vsense inside" ); |
652 | } |
653 | |
654 | return 0; |
655 | } |
656 | |
657 | static int aw_dev_set_vcalb(struct aw_device *aw_dev) |
658 | { |
659 | int16_t icalk_val, vcalk_val; |
660 | int icalk, vsense_select; |
661 | u32 vcalb_adj, reg_val; |
662 | int vcalb, vcalk; |
663 | int ret; |
664 | |
665 | ret = aw_dev_dsp_read(aw_dev, AW88395_DSP_REG_VCALB, dsp_data: &vcalb_adj, data_type: AW88395_DSP_16_DATA); |
666 | if (ret) { |
667 | dev_err(aw_dev->dev, "read vcalb_adj failed" ); |
668 | return ret; |
669 | } |
670 | |
671 | ret = aw_dev_vsense_select(aw_dev, vsense_select: &vsense_select); |
672 | if (ret) |
673 | return ret; |
674 | dev_dbg(aw_dev->dev, "vsense_select = %d" , vsense_select); |
675 | |
676 | ret = aw_dev_get_icalk(aw_dev, icalk: &icalk_val); |
677 | if (ret) |
678 | return ret; |
679 | icalk = AW88395_CABL_BASE_VALUE + AW88395_ICABLK_FACTOR * icalk_val; |
680 | |
681 | switch (vsense_select) { |
682 | case AW88395_DEV_VDSEL_VSENSE: |
683 | ret = aw_dev_get_vcalk(aw_dev, vcalk: &vcalk_val); |
684 | if (ret) |
685 | return ret; |
686 | vcalk = AW88395_CABL_BASE_VALUE + AW88395_VCABLK_FACTOR * vcalk_val; |
687 | vcalb = AW88395_VCAL_FACTOR * AW88395_VSCAL_FACTOR / |
688 | AW88395_ISCAL_FACTOR * icalk / vcalk * vcalb_adj; |
689 | |
690 | dev_dbg(aw_dev->dev, "vcalk_factor=%d, vscal_factor=%d, icalk=%d, vcalk=%d" , |
691 | AW88395_VCABLK_FACTOR, AW88395_VSCAL_FACTOR, icalk, vcalk); |
692 | break; |
693 | case AW88395_DEV_VDSEL_DAC: |
694 | ret = aw_dev_get_vcalk_dac(aw_dev, vcalk: &vcalk_val); |
695 | if (ret) |
696 | return ret; |
697 | vcalk = AW88395_CABL_BASE_VALUE + AW88395_VCABLK_FACTOR_DAC * vcalk_val; |
698 | vcalb = AW88395_VCAL_FACTOR * AW88395_VSCAL_FACTOR_DAC / |
699 | AW88395_ISCAL_FACTOR * icalk / vcalk * vcalb_adj; |
700 | |
701 | dev_dbg(aw_dev->dev, "vcalk_dac_factor=%d, vscal_dac_factor=%d, icalk=%d, vcalk=%d" , |
702 | AW88395_VCABLK_FACTOR_DAC, |
703 | AW88395_VSCAL_FACTOR_DAC, icalk, vcalk); |
704 | break; |
705 | default: |
706 | dev_err(aw_dev->dev, "unsupport vsense status" ); |
707 | return -EINVAL; |
708 | } |
709 | |
710 | if ((vcalk == 0) || (AW88395_ISCAL_FACTOR == 0)) { |
711 | dev_err(aw_dev->dev, "vcalk:%d or desc->iscal_factor:%d unsupported" , |
712 | vcalk, AW88395_ISCAL_FACTOR); |
713 | return -EINVAL; |
714 | } |
715 | |
716 | vcalb = vcalb >> AW88395_VCALB_ADJ_FACTOR; |
717 | reg_val = (u32)vcalb; |
718 | |
719 | dev_dbg(aw_dev->dev, "vcalb=%d, reg_val=0x%x, vcalb_adj =0x%x" , |
720 | vcalb, reg_val, vcalb_adj); |
721 | |
722 | ret = aw_dev_dsp_write(aw_dev, AW88395_DSP_REG_VCALB, dsp_data: reg_val, data_type: AW88395_DSP_16_DATA); |
723 | if (ret) { |
724 | dev_err(aw_dev->dev, "write vcalb failed" ); |
725 | return ret; |
726 | } |
727 | |
728 | ret = aw_dev_modify_dsp_cfg(aw_dev, AW88395_DSP_REG_VCALB, |
729 | dsp_data: (u32)reg_val, data_type: AW88395_DSP_16_DATA); |
730 | if (ret) |
731 | dev_err(aw_dev->dev, "modify dsp cfg failed" ); |
732 | |
733 | return ret; |
734 | } |
735 | |
736 | static int aw_dev_get_cali_f0_delay(struct aw_device *aw_dev) |
737 | { |
738 | struct aw_cali_delay_desc *desc = &aw_dev->cali_delay_desc; |
739 | u32 cali_delay; |
740 | int ret; |
741 | |
742 | ret = aw_dev_dsp_read(aw_dev, |
743 | AW88395_DSP_CALI_F0_DELAY, dsp_data: &cali_delay, data_type: AW88395_DSP_16_DATA); |
744 | if (ret) |
745 | dev_err(aw_dev->dev, "read cali delay failed, ret=%d" , ret); |
746 | else |
747 | desc->delay = AW88395_CALI_DELAY_CACL(cali_delay); |
748 | |
749 | dev_dbg(aw_dev->dev, "read cali delay: %d ms" , desc->delay); |
750 | |
751 | return ret; |
752 | } |
753 | |
754 | static void aw_dev_get_int_status(struct aw_device *aw_dev, unsigned short *int_status) |
755 | { |
756 | unsigned int reg_val; |
757 | int ret; |
758 | |
759 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSINT_REG, val: ®_val); |
760 | if (ret) |
761 | dev_err(aw_dev->dev, "read interrupt reg fail, ret=%d" , ret); |
762 | else |
763 | *int_status = reg_val; |
764 | |
765 | dev_dbg(aw_dev->dev, "read interrupt reg = 0x%04x" , *int_status); |
766 | } |
767 | |
768 | static void aw_dev_clear_int_status(struct aw_device *aw_dev) |
769 | { |
770 | u16 int_status; |
771 | |
772 | /* read int status and clear */ |
773 | aw_dev_get_int_status(aw_dev, int_status: &int_status); |
774 | /* make sure int status is clear */ |
775 | aw_dev_get_int_status(aw_dev, int_status: &int_status); |
776 | if (int_status) |
777 | dev_info(aw_dev->dev, "int status(%d) is not cleaned.\n" , int_status); |
778 | } |
779 | |
780 | static int aw_dev_get_iis_status(struct aw_device *aw_dev) |
781 | { |
782 | unsigned int reg_val; |
783 | int ret; |
784 | |
785 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSST_REG, val: ®_val); |
786 | if (ret) |
787 | return -EIO; |
788 | if ((reg_val & AW88395_BIT_PLL_CHECK) != AW88395_BIT_PLL_CHECK) { |
789 | dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x" , reg_val); |
790 | return -EINVAL; |
791 | } |
792 | |
793 | return 0; |
794 | } |
795 | |
796 | static int aw_dev_check_mode1_pll(struct aw_device *aw_dev) |
797 | { |
798 | int ret, i; |
799 | |
800 | for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { |
801 | ret = aw_dev_get_iis_status(aw_dev); |
802 | if (ret < 0) { |
803 | dev_err(aw_dev->dev, "mode1 iis signal check error" ); |
804 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
805 | } else { |
806 | return 0; |
807 | } |
808 | } |
809 | |
810 | return -EPERM; |
811 | } |
812 | |
813 | static int aw_dev_check_mode2_pll(struct aw_device *aw_dev) |
814 | { |
815 | unsigned int reg_val; |
816 | int ret, i; |
817 | |
818 | ret = regmap_read(map: aw_dev->regmap, AW88395_PLLCTRL1_REG, val: ®_val); |
819 | if (ret) |
820 | return ret; |
821 | |
822 | reg_val &= (~AW88395_CCO_MUX_MASK); |
823 | if (reg_val == AW88395_CCO_MUX_DIVIDED_VALUE) { |
824 | dev_dbg(aw_dev->dev, "CCO_MUX is already divider" ); |
825 | return -EPERM; |
826 | } |
827 | |
828 | /* change mode2 */ |
829 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_PLLCTRL1_REG, |
830 | mask: ~AW88395_CCO_MUX_MASK, AW88395_CCO_MUX_DIVIDED_VALUE); |
831 | if (ret) |
832 | return ret; |
833 | |
834 | for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { |
835 | ret = aw_dev_get_iis_status(aw_dev); |
836 | if (ret) { |
837 | dev_err(aw_dev->dev, "mode2 iis signal check error" ); |
838 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
839 | } else { |
840 | break; |
841 | } |
842 | } |
843 | |
844 | /* change mode1 */ |
845 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_PLLCTRL1_REG, |
846 | mask: ~AW88395_CCO_MUX_MASK, AW88395_CCO_MUX_BYPASS_VALUE); |
847 | if (ret == 0) { |
848 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
849 | for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { |
850 | ret = aw_dev_check_mode1_pll(aw_dev); |
851 | if (ret < 0) { |
852 | dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error" ); |
853 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
854 | } else { |
855 | break; |
856 | } |
857 | } |
858 | } |
859 | |
860 | return ret; |
861 | } |
862 | |
863 | static int aw_dev_check_syspll(struct aw_device *aw_dev) |
864 | { |
865 | int ret; |
866 | |
867 | ret = aw_dev_check_mode1_pll(aw_dev); |
868 | if (ret) { |
869 | dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check" ); |
870 | ret = aw_dev_check_mode2_pll(aw_dev); |
871 | if (ret) { |
872 | dev_err(aw_dev->dev, "mode2 check iis failed" ); |
873 | return ret; |
874 | } |
875 | } |
876 | |
877 | return ret; |
878 | } |
879 | |
880 | static int aw_dev_check_sysst(struct aw_device *aw_dev) |
881 | { |
882 | unsigned int check_val; |
883 | unsigned int reg_val; |
884 | int ret, i; |
885 | |
886 | for (i = 0; i < AW88395_DEV_SYSST_CHECK_MAX; i++) { |
887 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSST_REG, val: ®_val); |
888 | if (ret) |
889 | return ret; |
890 | |
891 | check_val = reg_val & (~AW88395_BIT_SYSST_CHECK_MASK) |
892 | & AW88395_BIT_SYSST_CHECK; |
893 | if (check_val != AW88395_BIT_SYSST_CHECK) { |
894 | dev_err(aw_dev->dev, "check sysst fail, cnt=%d, reg_val=0x%04x, check:0x%x" , |
895 | i, reg_val, AW88395_BIT_SYSST_CHECK); |
896 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
897 | } else { |
898 | return 0; |
899 | } |
900 | } |
901 | |
902 | return -EPERM; |
903 | } |
904 | |
905 | static int aw_dev_check_sysint(struct aw_device *aw_dev) |
906 | { |
907 | u16 reg_val; |
908 | |
909 | aw_dev_get_int_status(aw_dev, int_status: ®_val); |
910 | |
911 | if (reg_val & AW88395_BIT_SYSINT_CHECK) { |
912 | dev_err(aw_dev->dev, "pa stop check fail:0x%04x" , reg_val); |
913 | return -EINVAL; |
914 | } |
915 | |
916 | return 0; |
917 | } |
918 | |
919 | static void aw_dev_get_cur_mode_st(struct aw_device *aw_dev) |
920 | { |
921 | struct aw_profctrl_desc *profctrl_desc = &aw_dev->profctrl_desc; |
922 | unsigned int reg_val; |
923 | int ret; |
924 | |
925 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSCTRL_REG, val: ®_val); |
926 | if (ret) { |
927 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
928 | return; |
929 | } |
930 | if ((reg_val & (~AW88395_RCV_MODE_MASK)) == AW88395_RCV_MODE_RECEIVER_VALUE) |
931 | profctrl_desc->cur_mode = AW88395_RCV_MODE; |
932 | else |
933 | profctrl_desc->cur_mode = AW88395_NOT_RCV_MODE; |
934 | } |
935 | |
936 | static void aw_dev_get_dsp_config(struct aw_device *aw_dev, unsigned char *dsp_cfg) |
937 | { |
938 | unsigned int reg_val = 0; |
939 | int ret; |
940 | |
941 | ret = regmap_read(map: aw_dev->regmap, AW88395_SYSCTRL_REG, val: ®_val); |
942 | if (ret) { |
943 | dev_dbg(aw_dev->dev, "%s failed" , __func__); |
944 | return; |
945 | } |
946 | if (reg_val & (~AW88395_DSPBY_MASK)) |
947 | *dsp_cfg = AW88395_DEV_DSP_BYPASS; |
948 | else |
949 | *dsp_cfg = AW88395_DEV_DSP_WORK; |
950 | } |
951 | |
952 | static void aw_dev_select_memclk(struct aw_device *aw_dev, unsigned char flag) |
953 | { |
954 | int ret; |
955 | |
956 | switch (flag) { |
957 | case AW88395_DEV_MEMCLK_PLL: |
958 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_DBGCTRL_REG, |
959 | mask: ~AW88395_MEM_CLKSEL_MASK, |
960 | AW88395_MEM_CLKSEL_DAP_HCLK_VALUE); |
961 | if (ret) |
962 | dev_err(aw_dev->dev, "memclk select pll failed" ); |
963 | break; |
964 | case AW88395_DEV_MEMCLK_OSC: |
965 | ret = regmap_update_bits(map: aw_dev->regmap, AW88395_DBGCTRL_REG, |
966 | mask: ~AW88395_MEM_CLKSEL_MASK, |
967 | AW88395_MEM_CLKSEL_OSC_CLK_VALUE); |
968 | if (ret) |
969 | dev_err(aw_dev->dev, "memclk select OSC failed" ); |
970 | break; |
971 | default: |
972 | dev_err(aw_dev->dev, "unknown memclk config, flag=0x%x" , flag); |
973 | break; |
974 | } |
975 | } |
976 | |
977 | static int aw_dev_get_dsp_status(struct aw_device *aw_dev) |
978 | { |
979 | unsigned int reg_val; |
980 | int ret; |
981 | |
982 | ret = regmap_read(map: aw_dev->regmap, AW88395_WDT_REG, val: ®_val); |
983 | if (ret) |
984 | return ret; |
985 | if (!(reg_val & (~AW88395_WDT_CNT_MASK))) |
986 | ret = -EPERM; |
987 | |
988 | return ret; |
989 | } |
990 | |
991 | static int aw_dev_get_vmax(struct aw_device *aw_dev, unsigned int *vmax) |
992 | { |
993 | return aw_dev_dsp_read(aw_dev, AW88395_DSP_REG_VMAX, dsp_data: vmax, data_type: AW88395_DSP_16_DATA); |
994 | } |
995 | |
996 | static int aw_dev_update_reg_container(struct aw_device *aw_dev, |
997 | unsigned char *data, unsigned int len) |
998 | { |
999 | struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; |
1000 | unsigned int read_val; |
1001 | int16_t *reg_data; |
1002 | int data_len; |
1003 | u16 read_vol; |
1004 | u16 reg_val; |
1005 | u8 reg_addr; |
1006 | int i, ret; |
1007 | |
1008 | reg_data = (int16_t *)data; |
1009 | data_len = len >> 1; |
1010 | |
1011 | if (data_len & 0x1) { |
1012 | dev_err(aw_dev->dev, "data len:%d unsupported" , data_len); |
1013 | return -EINVAL; |
1014 | } |
1015 | |
1016 | for (i = 0; i < data_len; i += 2) { |
1017 | reg_addr = reg_data[i]; |
1018 | reg_val = reg_data[i + 1]; |
1019 | |
1020 | if (reg_addr == AW88395_SYSCTRL_REG) { |
1021 | ret = regmap_read(map: aw_dev->regmap, reg: reg_addr, val: &read_val); |
1022 | if (ret) |
1023 | break; |
1024 | read_val &= (~AW88395_HMUTE_MASK); |
1025 | reg_val &= AW88395_HMUTE_MASK; |
1026 | reg_val |= read_val; |
1027 | } |
1028 | if (reg_addr == AW88395_HAGCCFG7_REG) |
1029 | reg_val &= AW88395_AGC_DSP_CTL_MASK; |
1030 | |
1031 | if (reg_addr == AW88395_I2SCFG1_REG) { |
1032 | /* close tx */ |
1033 | reg_val &= AW88395_I2STXEN_MASK; |
1034 | reg_val |= AW88395_I2STXEN_DISABLE_VALUE; |
1035 | } |
1036 | |
1037 | if (reg_addr == AW88395_SYSCTRL2_REG) { |
1038 | read_vol = (reg_val & (~AW88395_VOL_MASK)) >> |
1039 | AW88395_VOL_START_BIT; |
1040 | aw_dev->volume_desc.init_volume = |
1041 | reg_val_to_db(value: read_vol); |
1042 | } |
1043 | ret = regmap_write(map: aw_dev->regmap, reg: reg_addr, val: reg_val); |
1044 | if (ret) |
1045 | break; |
1046 | |
1047 | } |
1048 | |
1049 | aw_dev_get_cur_mode_st(aw_dev); |
1050 | |
1051 | if (aw_dev->prof_cur != aw_dev->prof_index) { |
1052 | /* clear control volume when PA change profile */ |
1053 | vol_desc->ctl_volume = 0; |
1054 | } else { |
1055 | /* keep control volume when PA start with sync mode */ |
1056 | aw_dev_set_volume(aw_dev, value: vol_desc->ctl_volume); |
1057 | } |
1058 | |
1059 | aw_dev_get_dsp_config(aw_dev, dsp_cfg: &aw_dev->dsp_cfg); |
1060 | |
1061 | return ret; |
1062 | } |
1063 | |
1064 | static int aw_dev_reg_update(struct aw_device *aw_dev, |
1065 | unsigned char *data, unsigned int len) |
1066 | { |
1067 | int ret; |
1068 | |
1069 | if (!len || !data) { |
1070 | dev_err(aw_dev->dev, "reg data is null or len is 0" ); |
1071 | return -EINVAL; |
1072 | } |
1073 | |
1074 | ret = aw_dev_update_reg_container(aw_dev, data, len); |
1075 | if (ret) { |
1076 | dev_err(aw_dev->dev, "reg update failed" ); |
1077 | return ret; |
1078 | } |
1079 | |
1080 | return 0; |
1081 | } |
1082 | |
1083 | static int aw_dev_get_ra(struct aw_cali_desc *cali_desc) |
1084 | { |
1085 | struct aw_device *aw_dev = |
1086 | container_of(cali_desc, struct aw_device, cali_desc); |
1087 | u32 dsp_ra; |
1088 | int ret; |
1089 | |
1090 | ret = aw_dev_dsp_read(aw_dev, AW88395_DSP_REG_CFG_ADPZ_RA, |
1091 | dsp_data: &dsp_ra, data_type: AW88395_DSP_32_DATA); |
1092 | if (ret) { |
1093 | dev_err(aw_dev->dev, "read ra error" ); |
1094 | return ret; |
1095 | } |
1096 | |
1097 | cali_desc->ra = AW88395_DSP_RE_TO_SHOW_RE(dsp_ra, |
1098 | AW88395_DSP_RE_SHIFT); |
1099 | |
1100 | return ret; |
1101 | } |
1102 | |
1103 | static int aw_dev_dsp_update_container(struct aw_device *aw_dev, |
1104 | unsigned char *data, unsigned int len, unsigned short base) |
1105 | { |
1106 | int i, ret; |
1107 | |
1108 | #ifdef AW88395_DSP_I2C_WRITES |
1109 | u32 tmp_len; |
1110 | |
1111 | mutex_lock(&aw_dev->dsp_lock); |
1112 | ret = regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: base); |
1113 | if (ret) |
1114 | goto error_operation; |
1115 | |
1116 | for (i = 0; i < len; i += AW88395_MAX_RAM_WRITE_BYTE_SIZE) { |
1117 | if ((len - i) < AW88395_MAX_RAM_WRITE_BYTE_SIZE) |
1118 | tmp_len = len - i; |
1119 | else |
1120 | tmp_len = AW88395_MAX_RAM_WRITE_BYTE_SIZE; |
1121 | |
1122 | ret = regmap_raw_write(map: aw_dev->regmap, AW88395_DSPMDAT_REG, |
1123 | val: &data[i], val_len: tmp_len); |
1124 | if (ret) |
1125 | goto error_operation; |
1126 | } |
1127 | mutex_unlock(lock: &aw_dev->dsp_lock); |
1128 | #else |
1129 | __be16 reg_val; |
1130 | |
1131 | mutex_lock(&aw_dev->dsp_lock); |
1132 | /* i2c write */ |
1133 | ret = regmap_write(aw_dev->regmap, AW88395_DSPMADD_REG, base); |
1134 | if (ret) |
1135 | goto error_operation; |
1136 | for (i = 0; i < len; i += 2) { |
1137 | reg_val = cpu_to_be16p((u16 *)(data + i)); |
1138 | ret = regmap_write(aw_dev->regmap, AW88395_DSPMDAT_REG, |
1139 | (u16)reg_val); |
1140 | if (ret) |
1141 | goto error_operation; |
1142 | } |
1143 | mutex_unlock(&aw_dev->dsp_lock); |
1144 | #endif |
1145 | |
1146 | return 0; |
1147 | |
1148 | error_operation: |
1149 | mutex_unlock(lock: &aw_dev->dsp_lock); |
1150 | return ret; |
1151 | } |
1152 | |
1153 | static int aw_dev_dsp_update_fw(struct aw_device *aw_dev, |
1154 | unsigned char *data, unsigned int len) |
1155 | { |
1156 | |
1157 | dev_dbg(aw_dev->dev, "dsp firmware len:%d" , len); |
1158 | |
1159 | if (!len || !data) { |
1160 | dev_err(aw_dev->dev, "dsp firmware data is null or len is 0" ); |
1161 | return -EINVAL; |
1162 | } |
1163 | aw_dev_dsp_update_container(aw_dev, data, len, AW88395_DSP_FW_ADDR); |
1164 | aw_dev->dsp_fw_len = len; |
1165 | |
1166 | return 0; |
1167 | } |
1168 | |
1169 | static int aw_dev_copy_to_crc_dsp_cfg(struct aw_device *aw_dev, |
1170 | unsigned char *data, unsigned int size) |
1171 | { |
1172 | struct aw_sec_data_desc *crc_dsp_cfg = &aw_dev->crc_dsp_cfg; |
1173 | |
1174 | if (!crc_dsp_cfg->data) { |
1175 | crc_dsp_cfg->data = devm_kzalloc(dev: aw_dev->dev, size, GFP_KERNEL); |
1176 | if (!crc_dsp_cfg->data) |
1177 | return -ENOMEM; |
1178 | crc_dsp_cfg->len = size; |
1179 | } else if (crc_dsp_cfg->len < size) { |
1180 | devm_kfree(dev: aw_dev->dev, p: crc_dsp_cfg->data); |
1181 | crc_dsp_cfg->data = devm_kzalloc(dev: aw_dev->dev, size, GFP_KERNEL); |
1182 | if (!crc_dsp_cfg->data) |
1183 | return -ENOMEM; |
1184 | crc_dsp_cfg->len = size; |
1185 | } |
1186 | memcpy(crc_dsp_cfg->data, data, size); |
1187 | swab16_array(buf: (u16 *)crc_dsp_cfg->data, words: size >> 1); |
1188 | |
1189 | return 0; |
1190 | } |
1191 | |
1192 | static int aw_dev_dsp_update_cfg(struct aw_device *aw_dev, |
1193 | unsigned char *data, unsigned int len) |
1194 | { |
1195 | int ret; |
1196 | |
1197 | dev_dbg(aw_dev->dev, "dsp config len:%d" , len); |
1198 | |
1199 | if (!len || !data) { |
1200 | dev_err(aw_dev->dev, "dsp config data is null or len is 0" ); |
1201 | return -EINVAL; |
1202 | } |
1203 | |
1204 | aw_dev_dsp_update_container(aw_dev, data, len, AW88395_DSP_CFG_ADDR); |
1205 | aw_dev->dsp_cfg_len = len; |
1206 | |
1207 | ret = aw_dev_copy_to_crc_dsp_cfg(aw_dev, data, size: len); |
1208 | if (ret) |
1209 | return ret; |
1210 | |
1211 | ret = aw_dev_set_vcalb(aw_dev); |
1212 | if (ret) |
1213 | return ret; |
1214 | ret = aw_dev_get_ra(cali_desc: &aw_dev->cali_desc); |
1215 | if (ret) |
1216 | return ret; |
1217 | ret = aw_dev_get_cali_f0_delay(aw_dev); |
1218 | if (ret) |
1219 | return ret; |
1220 | |
1221 | ret = aw_dev_get_vmax(aw_dev, vmax: &aw_dev->vmax_desc.init_vmax); |
1222 | if (ret) { |
1223 | dev_err(aw_dev->dev, "get vmax failed" ); |
1224 | return ret; |
1225 | } |
1226 | dev_dbg(aw_dev->dev, "get init vmax:0x%x" , aw_dev->vmax_desc.init_vmax); |
1227 | aw_dev->dsp_crc_st = AW88395_DSP_CRC_NA; |
1228 | |
1229 | return 0; |
1230 | } |
1231 | |
1232 | static int aw_dev_check_sram(struct aw_device *aw_dev) |
1233 | { |
1234 | unsigned int reg_val; |
1235 | |
1236 | mutex_lock(&aw_dev->dsp_lock); |
1237 | /* check the odd bits of reg 0x40 */ |
1238 | regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, AW88395_DSP_ODD_NUM_BIT_TEST); |
1239 | regmap_read(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: ®_val); |
1240 | if (reg_val != AW88395_DSP_ODD_NUM_BIT_TEST) { |
1241 | dev_err(aw_dev->dev, "check reg 0x40 odd bit failed, read[0x%x] != write[0x%x]" , |
1242 | reg_val, AW88395_DSP_ODD_NUM_BIT_TEST); |
1243 | goto error; |
1244 | } |
1245 | |
1246 | /* check the even bits of reg 0x40 */ |
1247 | regmap_write(map: aw_dev->regmap, AW88395_DSPMADD_REG, AW88395_DSP_EVEN_NUM_BIT_TEST); |
1248 | regmap_read(map: aw_dev->regmap, AW88395_DSPMADD_REG, val: ®_val); |
1249 | if (reg_val != AW88395_DSP_EVEN_NUM_BIT_TEST) { |
1250 | dev_err(aw_dev->dev, "check reg 0x40 even bit failed, read[0x%x] != write[0x%x]" , |
1251 | reg_val, AW88395_DSP_EVEN_NUM_BIT_TEST); |
1252 | goto error; |
1253 | } |
1254 | |
1255 | /* check dsp_fw_base_addr */ |
1256 | aw_dev_dsp_write_16bit(aw_dev, AW88395_DSP_FW_ADDR, AW88395_DSP_EVEN_NUM_BIT_TEST); |
1257 | aw_dev_dsp_read_16bit(aw_dev, AW88395_DSP_FW_ADDR, dsp_data: ®_val); |
1258 | if (reg_val != AW88395_DSP_EVEN_NUM_BIT_TEST) { |
1259 | dev_err(aw_dev->dev, "check dsp fw addr failed, read[0x%x] != write[0x%x]" , |
1260 | reg_val, AW88395_DSP_EVEN_NUM_BIT_TEST); |
1261 | goto error; |
1262 | } |
1263 | |
1264 | /* check dsp_cfg_base_addr */ |
1265 | aw_dev_dsp_write_16bit(aw_dev, AW88395_DSP_CFG_ADDR, AW88395_DSP_ODD_NUM_BIT_TEST); |
1266 | aw_dev_dsp_read_16bit(aw_dev, AW88395_DSP_CFG_ADDR, dsp_data: ®_val); |
1267 | if (reg_val != AW88395_DSP_ODD_NUM_BIT_TEST) { |
1268 | dev_err(aw_dev->dev, "check dsp cfg failed, read[0x%x] != write[0x%x]" , |
1269 | reg_val, AW88395_DSP_ODD_NUM_BIT_TEST); |
1270 | goto error; |
1271 | } |
1272 | mutex_unlock(lock: &aw_dev->dsp_lock); |
1273 | |
1274 | return 0; |
1275 | |
1276 | error: |
1277 | mutex_unlock(lock: &aw_dev->dsp_lock); |
1278 | return -EPERM; |
1279 | } |
1280 | |
1281 | int aw88395_dev_fw_update(struct aw_device *aw_dev, bool up_dsp_fw_en, bool force_up_en) |
1282 | { |
1283 | struct aw_prof_desc *prof_index_desc; |
1284 | struct aw_sec_data_desc *sec_desc; |
1285 | char *prof_name; |
1286 | int ret; |
1287 | |
1288 | if ((aw_dev->prof_cur == aw_dev->prof_index) && |
1289 | (force_up_en == AW88395_FORCE_UPDATE_OFF)) { |
1290 | dev_dbg(aw_dev->dev, "scene no change, not update" ); |
1291 | return 0; |
1292 | } |
1293 | |
1294 | if (aw_dev->fw_status == AW88395_DEV_FW_FAILED) { |
1295 | dev_err(aw_dev->dev, "fw status[%d] error" , aw_dev->fw_status); |
1296 | return -EPERM; |
1297 | } |
1298 | |
1299 | ret = aw88395_dev_get_prof_name(aw_dev, index: aw_dev->prof_index, prof_name: &prof_name); |
1300 | if (ret) |
1301 | return ret; |
1302 | |
1303 | dev_dbg(aw_dev->dev, "start update %s" , prof_name); |
1304 | |
1305 | ret = aw88395_dev_get_prof_data(aw_dev, index: aw_dev->prof_index, prof_desc: &prof_index_desc); |
1306 | if (ret) |
1307 | return ret; |
1308 | |
1309 | /* update reg */ |
1310 | sec_desc = prof_index_desc->sec_desc; |
1311 | ret = aw_dev_reg_update(aw_dev, data: sec_desc[AW88395_DATA_TYPE_REG].data, |
1312 | len: sec_desc[AW88395_DATA_TYPE_REG].len); |
1313 | if (ret) { |
1314 | dev_err(aw_dev->dev, "update reg failed" ); |
1315 | return ret; |
1316 | } |
1317 | |
1318 | aw88395_dev_mute(aw_dev, true); |
1319 | |
1320 | if (aw_dev->dsp_cfg == AW88395_DEV_DSP_WORK) |
1321 | aw_dev_dsp_enable(aw_dev, is_enable: false); |
1322 | |
1323 | aw_dev_select_memclk(aw_dev, flag: AW88395_DEV_MEMCLK_OSC); |
1324 | |
1325 | if (up_dsp_fw_en) { |
1326 | ret = aw_dev_check_sram(aw_dev); |
1327 | if (ret) { |
1328 | dev_err(aw_dev->dev, "check sram failed" ); |
1329 | goto error; |
1330 | } |
1331 | |
1332 | /* update dsp firmware */ |
1333 | dev_dbg(aw_dev->dev, "fw_ver: [%x]" , prof_index_desc->fw_ver); |
1334 | ret = aw_dev_dsp_update_fw(aw_dev, data: sec_desc[AW88395_DATA_TYPE_DSP_FW].data, |
1335 | len: sec_desc[AW88395_DATA_TYPE_DSP_FW].len); |
1336 | if (ret) { |
1337 | dev_err(aw_dev->dev, "update dsp fw failed" ); |
1338 | goto error; |
1339 | } |
1340 | } |
1341 | |
1342 | /* update dsp config */ |
1343 | ret = aw_dev_dsp_update_cfg(aw_dev, data: sec_desc[AW88395_DATA_TYPE_DSP_CFG].data, |
1344 | len: sec_desc[AW88395_DATA_TYPE_DSP_CFG].len); |
1345 | if (ret) { |
1346 | dev_err(aw_dev->dev, "update dsp cfg failed" ); |
1347 | goto error; |
1348 | } |
1349 | |
1350 | aw_dev_select_memclk(aw_dev, flag: AW88395_DEV_MEMCLK_PLL); |
1351 | |
1352 | aw_dev->prof_cur = aw_dev->prof_index; |
1353 | |
1354 | return 0; |
1355 | |
1356 | error: |
1357 | aw_dev_select_memclk(aw_dev, flag: AW88395_DEV_MEMCLK_PLL); |
1358 | return ret; |
1359 | } |
1360 | EXPORT_SYMBOL_GPL(aw88395_dev_fw_update); |
1361 | |
1362 | static int aw_dev_dsp_check(struct aw_device *aw_dev) |
1363 | { |
1364 | int ret, i; |
1365 | |
1366 | switch (aw_dev->dsp_cfg) { |
1367 | case AW88395_DEV_DSP_BYPASS: |
1368 | dev_dbg(aw_dev->dev, "dsp bypass" ); |
1369 | ret = 0; |
1370 | break; |
1371 | case AW88395_DEV_DSP_WORK: |
1372 | aw_dev_dsp_enable(aw_dev, is_enable: false); |
1373 | aw_dev_dsp_enable(aw_dev, is_enable: true); |
1374 | usleep_range(min: AW88395_1000_US, max: AW88395_1000_US + 10); |
1375 | for (i = 0; i < AW88395_DEV_DSP_CHECK_MAX; i++) { |
1376 | ret = aw_dev_get_dsp_status(aw_dev); |
1377 | if (ret) { |
1378 | dev_err(aw_dev->dev, "dsp wdt status error=%d" , ret); |
1379 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
1380 | } |
1381 | } |
1382 | break; |
1383 | default: |
1384 | dev_err(aw_dev->dev, "unknown dsp cfg=%d" , aw_dev->dsp_cfg); |
1385 | ret = -EINVAL; |
1386 | break; |
1387 | } |
1388 | |
1389 | return ret; |
1390 | } |
1391 | |
1392 | static void aw_dev_update_cali_re(struct aw_cali_desc *cali_desc) |
1393 | { |
1394 | struct aw_device *aw_dev = |
1395 | container_of(cali_desc, struct aw_device, cali_desc); |
1396 | int ret; |
1397 | |
1398 | if ((aw_dev->cali_desc.cali_re < AW88395_CALI_RE_MAX) && |
1399 | (aw_dev->cali_desc.cali_re > AW88395_CALI_RE_MIN)) { |
1400 | |
1401 | ret = aw_dev_dsp_set_cali_re(aw_dev); |
1402 | if (ret) |
1403 | dev_err(aw_dev->dev, "set cali re failed" ); |
1404 | } |
1405 | } |
1406 | |
1407 | int aw88395_dev_start(struct aw_device *aw_dev) |
1408 | { |
1409 | int ret; |
1410 | |
1411 | if (aw_dev->status == AW88395_DEV_PW_ON) { |
1412 | dev_info(aw_dev->dev, "already power on" ); |
1413 | return 0; |
1414 | } |
1415 | /* power on */ |
1416 | aw_dev_pwd(aw_dev, pwd: false); |
1417 | usleep_range(min: AW88395_2000_US, max: AW88395_2000_US + 10); |
1418 | |
1419 | ret = aw_dev_check_syspll(aw_dev); |
1420 | if (ret) { |
1421 | dev_err(aw_dev->dev, "pll check failed cannot start" ); |
1422 | goto pll_check_fail; |
1423 | } |
1424 | |
1425 | /* amppd on */ |
1426 | aw_dev_amppd(aw_dev, amppd: false); |
1427 | usleep_range(min: AW88395_1000_US, max: AW88395_1000_US + 50); |
1428 | |
1429 | /* check i2s status */ |
1430 | ret = aw_dev_check_sysst(aw_dev); |
1431 | if (ret) { |
1432 | dev_err(aw_dev->dev, "sysst check failed" ); |
1433 | goto sysst_check_fail; |
1434 | } |
1435 | |
1436 | if (aw_dev->dsp_cfg == AW88395_DEV_DSP_WORK) { |
1437 | /* dsp bypass */ |
1438 | aw_dev_dsp_enable(aw_dev, is_enable: false); |
1439 | ret = aw_dev_dsp_fw_check(aw_dev); |
1440 | if (ret) |
1441 | goto dev_dsp_fw_check_fail; |
1442 | |
1443 | aw_dev_update_cali_re(cali_desc: &aw_dev->cali_desc); |
1444 | |
1445 | if (aw_dev->dsp_crc_st != AW88395_DSP_CRC_OK) { |
1446 | ret = aw_dev_dsp_check_crc32(aw_dev); |
1447 | if (ret) { |
1448 | dev_err(aw_dev->dev, "dsp crc check failed" ); |
1449 | goto crc_check_fail; |
1450 | } |
1451 | } |
1452 | |
1453 | ret = aw_dev_dsp_check(aw_dev); |
1454 | if (ret) { |
1455 | dev_err(aw_dev->dev, "dsp status check failed" ); |
1456 | goto dsp_check_fail; |
1457 | } |
1458 | } else { |
1459 | dev_dbg(aw_dev->dev, "start pa with dsp bypass" ); |
1460 | } |
1461 | |
1462 | /* enable tx feedback */ |
1463 | aw_dev_i2s_tx_enable(aw_dev, flag: true); |
1464 | |
1465 | /* close mute */ |
1466 | aw88395_dev_mute(aw_dev, false); |
1467 | /* clear inturrupt */ |
1468 | aw_dev_clear_int_status(aw_dev); |
1469 | aw_dev->status = AW88395_DEV_PW_ON; |
1470 | |
1471 | return 0; |
1472 | |
1473 | dsp_check_fail: |
1474 | crc_check_fail: |
1475 | aw_dev_dsp_enable(aw_dev, is_enable: false); |
1476 | dev_dsp_fw_check_fail: |
1477 | sysst_check_fail: |
1478 | aw_dev_clear_int_status(aw_dev); |
1479 | aw_dev_amppd(aw_dev, amppd: true); |
1480 | pll_check_fail: |
1481 | aw_dev_pwd(aw_dev, pwd: true); |
1482 | aw_dev->status = AW88395_DEV_PW_OFF; |
1483 | |
1484 | return ret; |
1485 | } |
1486 | EXPORT_SYMBOL_GPL(aw88395_dev_start); |
1487 | |
1488 | int aw88395_dev_stop(struct aw_device *aw_dev) |
1489 | { |
1490 | struct aw_sec_data_desc *dsp_cfg = |
1491 | &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_CFG]; |
1492 | struct aw_sec_data_desc *dsp_fw = |
1493 | &aw_dev->prof_info.prof_desc[aw_dev->prof_cur].sec_desc[AW88395_DATA_TYPE_DSP_FW]; |
1494 | int int_st = 0; |
1495 | int ret; |
1496 | |
1497 | if (aw_dev->status == AW88395_DEV_PW_OFF) { |
1498 | dev_info(aw_dev->dev, "already power off" ); |
1499 | return 0; |
1500 | } |
1501 | |
1502 | aw_dev->status = AW88395_DEV_PW_OFF; |
1503 | |
1504 | /* set mute */ |
1505 | aw88395_dev_mute(aw_dev, true); |
1506 | usleep_range(min: AW88395_4000_US, max: AW88395_4000_US + 100); |
1507 | |
1508 | /* close tx feedback */ |
1509 | aw_dev_i2s_tx_enable(aw_dev, flag: false); |
1510 | usleep_range(min: AW88395_1000_US, max: AW88395_1000_US + 100); |
1511 | |
1512 | /* check sysint state */ |
1513 | int_st = aw_dev_check_sysint(aw_dev); |
1514 | |
1515 | /* close dsp */ |
1516 | aw_dev_dsp_enable(aw_dev, is_enable: false); |
1517 | |
1518 | /* enable amppd */ |
1519 | aw_dev_amppd(aw_dev, amppd: true); |
1520 | |
1521 | if (int_st < 0) { |
1522 | /* system status anomaly */ |
1523 | aw_dev_select_memclk(aw_dev, flag: AW88395_DEV_MEMCLK_OSC); |
1524 | ret = aw_dev_dsp_update_fw(aw_dev, data: dsp_fw->data, len: dsp_fw->len); |
1525 | if (ret) |
1526 | dev_err(aw_dev->dev, "update dsp fw failed" ); |
1527 | ret = aw_dev_dsp_update_cfg(aw_dev, data: dsp_cfg->data, len: dsp_cfg->len); |
1528 | if (ret) |
1529 | dev_err(aw_dev->dev, "update dsp cfg failed" ); |
1530 | aw_dev_select_memclk(aw_dev, flag: AW88395_DEV_MEMCLK_PLL); |
1531 | } |
1532 | |
1533 | /* set power down */ |
1534 | aw_dev_pwd(aw_dev, pwd: true); |
1535 | |
1536 | return 0; |
1537 | } |
1538 | EXPORT_SYMBOL_GPL(aw88395_dev_stop); |
1539 | |
1540 | int aw88395_dev_init(struct aw_device *aw_dev, struct aw_container *aw_cfg) |
1541 | { |
1542 | int ret; |
1543 | |
1544 | if ((!aw_dev) || (!aw_cfg)) { |
1545 | pr_err("aw_dev is NULL or aw_cfg is NULL" ); |
1546 | return -ENOMEM; |
1547 | } |
1548 | ret = aw88395_dev_cfg_load(aw_dev, aw_cfg); |
1549 | if (ret) { |
1550 | dev_err(aw_dev->dev, "aw_dev acf parse failed" ); |
1551 | return -EINVAL; |
1552 | } |
1553 | aw_dev->fade_in_time = AW88395_1000_US / 10; |
1554 | aw_dev->fade_out_time = AW88395_1000_US >> 1; |
1555 | aw_dev->prof_cur = aw_dev->prof_info.prof_desc[0].id; |
1556 | aw_dev->prof_index = aw_dev->prof_info.prof_desc[0].id; |
1557 | |
1558 | ret = aw88395_dev_fw_update(aw_dev, AW88395_FORCE_UPDATE_ON, AW88395_DSP_FW_UPDATE_ON); |
1559 | if (ret) { |
1560 | dev_err(aw_dev->dev, "fw update failed ret = %d\n" , ret); |
1561 | return ret; |
1562 | } |
1563 | |
1564 | /* set mute */ |
1565 | aw88395_dev_mute(aw_dev, true); |
1566 | usleep_range(min: AW88395_4000_US, max: AW88395_4000_US + 100); |
1567 | |
1568 | /* close tx feedback */ |
1569 | aw_dev_i2s_tx_enable(aw_dev, flag: false); |
1570 | usleep_range(min: AW88395_1000_US, max: AW88395_1000_US + 100); |
1571 | |
1572 | /* close dsp */ |
1573 | aw_dev_dsp_enable(aw_dev, is_enable: false); |
1574 | /* enable amppd */ |
1575 | aw_dev_amppd(aw_dev, amppd: true); |
1576 | /* set power down */ |
1577 | aw_dev_pwd(aw_dev, pwd: true); |
1578 | |
1579 | return 0; |
1580 | } |
1581 | EXPORT_SYMBOL_GPL(aw88395_dev_init); |
1582 | |
1583 | static void aw88395_parse_channel_dt(struct aw_device *aw_dev) |
1584 | { |
1585 | struct device_node *np = aw_dev->dev->of_node; |
1586 | u32 channel_value; |
1587 | int ret; |
1588 | |
1589 | ret = of_property_read_u32(np, propname: "awinic,audio-channel" , out_value: &channel_value); |
1590 | if (ret) { |
1591 | dev_dbg(aw_dev->dev, |
1592 | "read audio-channel failed,use default 0" ); |
1593 | aw_dev->channel = AW88395_DEV_DEFAULT_CH; |
1594 | return; |
1595 | } |
1596 | |
1597 | dev_dbg(aw_dev->dev, "read audio-channel value is: %d" , |
1598 | channel_value); |
1599 | aw_dev->channel = channel_value; |
1600 | } |
1601 | |
1602 | static int aw_dev_init(struct aw_device *aw_dev) |
1603 | { |
1604 | aw_dev->chip_id = AW88395_CHIP_ID; |
1605 | /* call aw device init func */ |
1606 | aw_dev->acf = NULL; |
1607 | aw_dev->prof_info.prof_desc = NULL; |
1608 | aw_dev->prof_info.count = 0; |
1609 | aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; |
1610 | aw_dev->channel = 0; |
1611 | aw_dev->fw_status = AW88395_DEV_FW_FAILED; |
1612 | |
1613 | aw_dev->fade_step = AW88395_VOLUME_STEP_DB; |
1614 | aw_dev->volume_desc.ctl_volume = AW88395_VOL_DEFAULT_VALUE; |
1615 | aw88395_parse_channel_dt(aw_dev); |
1616 | |
1617 | return 0; |
1618 | } |
1619 | |
1620 | int aw88395_dev_get_profile_count(struct aw_device *aw_dev) |
1621 | { |
1622 | return aw_dev->prof_info.count; |
1623 | } |
1624 | EXPORT_SYMBOL_GPL(aw88395_dev_get_profile_count); |
1625 | |
1626 | int aw88395_dev_get_profile_index(struct aw_device *aw_dev) |
1627 | { |
1628 | return aw_dev->prof_index; |
1629 | } |
1630 | EXPORT_SYMBOL_GPL(aw88395_dev_get_profile_index); |
1631 | |
1632 | int aw88395_dev_set_profile_index(struct aw_device *aw_dev, int index) |
1633 | { |
1634 | /* check the index whether is valid */ |
1635 | if ((index >= aw_dev->prof_info.count) || (index < 0)) |
1636 | return -EINVAL; |
1637 | /* check the index whether change */ |
1638 | if (aw_dev->prof_index == index) |
1639 | return -EINVAL; |
1640 | |
1641 | aw_dev->prof_index = index; |
1642 | dev_dbg(aw_dev->dev, "set prof[%s]" , |
1643 | aw_dev->prof_info.prof_name_list[aw_dev->prof_info.prof_desc[index].id]); |
1644 | |
1645 | return 0; |
1646 | } |
1647 | EXPORT_SYMBOL_GPL(aw88395_dev_set_profile_index); |
1648 | |
1649 | int aw88395_dev_get_prof_name(struct aw_device *aw_dev, int index, char **prof_name) |
1650 | { |
1651 | struct aw_prof_info *prof_info = &aw_dev->prof_info; |
1652 | struct aw_prof_desc *prof_desc; |
1653 | |
1654 | if ((index >= aw_dev->prof_info.count) || (index < 0)) { |
1655 | dev_err(aw_dev->dev, "index[%d] overflow count[%d]" , |
1656 | index, aw_dev->prof_info.count); |
1657 | return -EINVAL; |
1658 | } |
1659 | |
1660 | prof_desc = &aw_dev->prof_info.prof_desc[index]; |
1661 | |
1662 | *prof_name = prof_info->prof_name_list[prof_desc->id]; |
1663 | |
1664 | return 0; |
1665 | } |
1666 | EXPORT_SYMBOL_GPL(aw88395_dev_get_prof_name); |
1667 | |
1668 | int aw88395_dev_get_prof_data(struct aw_device *aw_dev, int index, |
1669 | struct aw_prof_desc **prof_desc) |
1670 | { |
1671 | if ((index >= aw_dev->prof_info.count) || (index < 0)) { |
1672 | dev_err(aw_dev->dev, "%s: index[%d] overflow count[%d]\n" , |
1673 | __func__, index, aw_dev->prof_info.count); |
1674 | return -EINVAL; |
1675 | } |
1676 | |
1677 | *prof_desc = &aw_dev->prof_info.prof_desc[index]; |
1678 | |
1679 | return 0; |
1680 | } |
1681 | EXPORT_SYMBOL_GPL(aw88395_dev_get_prof_data); |
1682 | |
1683 | int aw88395_init(struct aw_device **aw_dev, struct i2c_client *i2c, struct regmap *regmap) |
1684 | { |
1685 | u16 chip_id; |
1686 | int ret; |
1687 | |
1688 | if (*aw_dev) { |
1689 | dev_info(&i2c->dev, "it should be initialized here.\n" ); |
1690 | } else { |
1691 | *aw_dev = devm_kzalloc(dev: &i2c->dev, size: sizeof(struct aw_device), GFP_KERNEL); |
1692 | if (!(*aw_dev)) |
1693 | return -ENOMEM; |
1694 | } |
1695 | |
1696 | (*aw_dev)->i2c = i2c; |
1697 | (*aw_dev)->dev = &i2c->dev; |
1698 | (*aw_dev)->regmap = regmap; |
1699 | mutex_init(&(*aw_dev)->dsp_lock); |
1700 | |
1701 | /* read chip id */ |
1702 | ret = aw_dev_read_chipid(aw_dev: (*aw_dev), chip_id: &chip_id); |
1703 | if (ret) { |
1704 | dev_err(&i2c->dev, "dev_read_chipid failed ret=%d" , ret); |
1705 | return ret; |
1706 | } |
1707 | |
1708 | switch (chip_id) { |
1709 | case AW88395_CHIP_ID: |
1710 | ret = aw_dev_init(aw_dev: (*aw_dev)); |
1711 | break; |
1712 | default: |
1713 | ret = -EINVAL; |
1714 | dev_err((*aw_dev)->dev, "unsupported device" ); |
1715 | break; |
1716 | } |
1717 | |
1718 | return ret; |
1719 | } |
1720 | EXPORT_SYMBOL_GPL(aw88395_init); |
1721 | |
1722 | MODULE_DESCRIPTION("AW88395 device lib" ); |
1723 | MODULE_LICENSE("GPL v2" ); |
1724 | |