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