xref: /OK3568_Linux_fs/kernel/sound/soc/codecs/aw883xx/aw_monitor.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * awinic_monitor.c monitor_module
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Version: v0.1.17
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (c) 2019 AWINIC Technology CO., LTD
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *  Author: Nick Li <liweilei@awinic.com.cn>
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * This program is free software; you can redistribute  it and/or modify it
12*4882a593Smuzhiyun  * under  the terms of  the GNU General  Public License as published by the
13*4882a593Smuzhiyun  * Free Software Foundation;  either version 2 of the  License, or (at your
14*4882a593Smuzhiyun  * option) any later version.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/i2c.h>
18*4882a593Smuzhiyun #include <sound/core.h>
19*4882a593Smuzhiyun #include <sound/pcm.h>
20*4882a593Smuzhiyun #include <sound/pcm_params.h>
21*4882a593Smuzhiyun #include <sound/soc.h>
22*4882a593Smuzhiyun #include <linux/of_gpio.h>
23*4882a593Smuzhiyun #include <linux/delay.h>
24*4882a593Smuzhiyun #include <linux/device.h>
25*4882a593Smuzhiyun #include <linux/firmware.h>
26*4882a593Smuzhiyun #include <linux/of.h>
27*4882a593Smuzhiyun #include <linux/version.h>
28*4882a593Smuzhiyun #include <linux/input.h>
29*4882a593Smuzhiyun #include <linux/timer.h>
30*4882a593Smuzhiyun #include <linux/workqueue.h>
31*4882a593Smuzhiyun #include <linux/hrtimer.h>
32*4882a593Smuzhiyun #include <linux/power_supply.h>
33*4882a593Smuzhiyun #include "aw_monitor.h"
34*4882a593Smuzhiyun #include "aw_log.h"
35*4882a593Smuzhiyun #include "aw_device.h"
36*4882a593Smuzhiyun #include "aw883xx.h"
37*4882a593Smuzhiyun #include "aw_calib.h"
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define AW883XX_MONITOR_NAME "aw883xx_monitor.bin"
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /*****************************************************
43*4882a593Smuzhiyun  * device monitor
44*4882a593Smuzhiyun  *****************************************************/
45*4882a593Smuzhiyun  #ifndef AW_SYS_BATTERY_ST
aw_monitor_get_chip_voltage(struct aw_device * aw_dev,unsigned int * vol)46*4882a593Smuzhiyun static int aw_monitor_get_chip_voltage(struct aw_device *aw_dev,
47*4882a593Smuzhiyun 						unsigned int *vol)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	int ret = -1;
50*4882a593Smuzhiyun 	uint16_t local_vol = 0;
51*4882a593Smuzhiyun 	struct aw_voltage_desc *desc = &aw_dev->voltage_desc;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_reg_read(aw_dev, desc->reg, (uint16_t *)vol);
54*4882a593Smuzhiyun 	if (ret < 0) {
55*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "read voltage failed!");
56*4882a593Smuzhiyun 		return ret;
57*4882a593Smuzhiyun 	}
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	if (desc->int_bit == 0) {
60*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "desc->int_bit:%d unsupported", desc->int_bit);
61*4882a593Smuzhiyun 		return -EINVAL;
62*4882a593Smuzhiyun 	}
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	local_vol = ((*vol) * desc->vbat_range) / desc->int_bit;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	*vol = local_vol;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "chip voltage is %d", *vol);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return 0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
aw_monitor_get_chip_temperature(struct aw_device * aw_dev,int * temp)73*4882a593Smuzhiyun static int aw_monitor_get_chip_temperature(struct aw_device *aw_dev, int *temp)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	int ret = -1;
76*4882a593Smuzhiyun 	uint16_t reg_val = 0;
77*4882a593Smuzhiyun 	uint16_t local_temp;
78*4882a593Smuzhiyun 	struct aw_temperature_desc *desc = &aw_dev->temp_desc;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_reg_read(aw_dev, desc->reg, &reg_val);
81*4882a593Smuzhiyun 	if (ret < 0) {
82*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "get temperature failed!");
83*4882a593Smuzhiyun 		return ret;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	local_temp = reg_val;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	if (local_temp & (~desc->sign_mask))
89*4882a593Smuzhiyun 		local_temp = local_temp | desc->neg_mask;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	*temp = (int)((int16_t)local_temp);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "chip temperature = %d", *temp);
94*4882a593Smuzhiyun 	return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun #endif
97*4882a593Smuzhiyun 
aw_monitor_get_battery_state(struct aw_device * aw_dev,int * data,int data_type)98*4882a593Smuzhiyun static int aw_monitor_get_battery_state(struct aw_device *aw_dev,
99*4882a593Smuzhiyun 			int *data, int data_type)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	char name[] = "battery";
102*4882a593Smuzhiyun 	int ret = -1;
103*4882a593Smuzhiyun 	union power_supply_propval prop = { 0 };
104*4882a593Smuzhiyun 	struct power_supply *psy = NULL;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	psy = power_supply_get_by_name(name);
107*4882a593Smuzhiyun 	if (psy) {
108*4882a593Smuzhiyun 		ret = power_supply_get_property(psy, data_type, &prop);
109*4882a593Smuzhiyun 		if (ret < 0) {
110*4882a593Smuzhiyun 			aw_dev_err(aw_dev->dev, "get data failed");
111*4882a593Smuzhiyun 			return -EINVAL;
112*4882a593Smuzhiyun 		}
113*4882a593Smuzhiyun 		*data = prop.intval;
114*4882a593Smuzhiyun 		aw_dev_dbg(aw_dev->dev, "get system data: %d", *data);
115*4882a593Smuzhiyun 	} else {
116*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "no struct power supply name : %s", name);
117*4882a593Smuzhiyun 		return -EINVAL;
118*4882a593Smuzhiyun 	}
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	return 0;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
aw_monitor_get_system_temperature(struct aw_device * aw_dev,int * temp)123*4882a593Smuzhiyun static int aw_monitor_get_system_temperature(struct aw_device *aw_dev, int *temp)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	int ret = -1;
126*4882a593Smuzhiyun 	int sys_temp;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	ret = aw_monitor_get_battery_state(aw_dev, &sys_temp, POWER_SUPPLY_PROP_TEMP);
129*4882a593Smuzhiyun 	if (ret < 0) {
130*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "get system temperature failed!");
131*4882a593Smuzhiyun 		return ret;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	*temp = sys_temp / 10;
135*4882a593Smuzhiyun 	aw_dev_dbg(aw_dev->dev, "system temperature = %d", *temp);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	return ret;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
aw_monitor_set_system_temperature(struct aw_device * aw_dev,int sys_temp)140*4882a593Smuzhiyun static int aw_monitor_set_system_temperature(struct aw_device *aw_dev, int sys_temp)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	int ret = -1;
143*4882a593Smuzhiyun 	struct aw_hw_temp_desc *hw_temp_desc = &aw_dev->hw_temp_desc;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_dsp_write(aw_dev, hw_temp_desc->dsp_reg,
146*4882a593Smuzhiyun 				sys_temp, hw_temp_desc->data_type);
147*4882a593Smuzhiyun 	if (ret < 0) {
148*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "set system temperature failed!");
149*4882a593Smuzhiyun 		return ret;
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return ret;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun #ifdef AW_SYS_BATTERY_ST
aw_monitor_get_system_voltage(struct aw_device * aw_dev,unsigned int * vol)156*4882a593Smuzhiyun static int aw_monitor_get_system_voltage(struct aw_device *aw_dev, unsigned int *vol)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	int ret = -1;
159*4882a593Smuzhiyun 	unsigned int sys_vol;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	ret = aw_monitor_get_battery_state(aw_dev, &sys_vol, POWER_SUPPLY_PROP_VOLTAGE_NOW);
162*4882a593Smuzhiyun 	if (ret < 0) {
163*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "get system voltage failed!");
164*4882a593Smuzhiyun 		return ret;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	*vol = sys_vol / 1000;
168*4882a593Smuzhiyun 	aw_dev_dbg(aw_dev->dev, "system voltage = %d", *vol);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	return ret;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun #endif
173*4882a593Smuzhiyun 
aw_monitor_get_temperature(struct aw_device * aw_dev,int * temp)174*4882a593Smuzhiyun static int aw_monitor_get_temperature(struct aw_device *aw_dev, int *temp)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun #ifdef AW_SYS_BATTERY_ST
177*4882a593Smuzhiyun 	return aw_monitor_get_system_temperature(aw_dev, temp);
178*4882a593Smuzhiyun #else
179*4882a593Smuzhiyun 	return aw_monitor_get_chip_temperature(aw_dev, temp);
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
aw_monitor_get_voltage(struct aw_device * aw_dev,unsigned int * vol)183*4882a593Smuzhiyun static int aw_monitor_get_voltage(struct aw_device *aw_dev, unsigned int *vol)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun #ifdef AW_SYS_BATTERY_ST
186*4882a593Smuzhiyun 	return aw_monitor_get_system_voltage(aw_dev, vol);
187*4882a593Smuzhiyun #else
188*4882a593Smuzhiyun 	return aw_monitor_get_chip_voltage(aw_dev, vol);
189*4882a593Smuzhiyun #endif
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
aw_monitor_get_temp_and_vol(struct aw_device * aw_dev)192*4882a593Smuzhiyun static int aw_monitor_get_temp_and_vol(struct aw_device *aw_dev)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
195*4882a593Smuzhiyun 	unsigned int voltage = 0;
196*4882a593Smuzhiyun 	int current_temp = 0;
197*4882a593Smuzhiyun 	int ret = -1;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun #ifdef AW_DEBUG
200*4882a593Smuzhiyun 	if (monitor->test_vol == 0) {
201*4882a593Smuzhiyun 		ret = aw_monitor_get_voltage(aw_dev, &voltage);
202*4882a593Smuzhiyun 		if (ret < 0)
203*4882a593Smuzhiyun 			return ret;
204*4882a593Smuzhiyun 	} else {
205*4882a593Smuzhiyun 		voltage = monitor->test_vol;
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	if (monitor->test_temp == 0) {
209*4882a593Smuzhiyun 		ret = aw_monitor_get_temperature(aw_dev, &current_temp);
210*4882a593Smuzhiyun 		if (ret < 0)
211*4882a593Smuzhiyun 			return ret;
212*4882a593Smuzhiyun 	} else {
213*4882a593Smuzhiyun 		current_temp = monitor->test_temp;
214*4882a593Smuzhiyun 	}
215*4882a593Smuzhiyun #else
216*4882a593Smuzhiyun 	ret = aw_monitor_get_voltage(aw_dev, &voltage);
217*4882a593Smuzhiyun 	if (ret < 0)
218*4882a593Smuzhiyun 		return ret;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	ret = aw_monitor_get_temperature(aw_dev, &current_temp);
221*4882a593Smuzhiyun 	if (ret < 0)
222*4882a593Smuzhiyun 		return ret;
223*4882a593Smuzhiyun #endif
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	monitor->vol_trace.sum_val += voltage;
226*4882a593Smuzhiyun 	monitor->temp_trace.sum_val += current_temp;
227*4882a593Smuzhiyun 	monitor->samp_count++;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	return 0;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
aw_monitor_first_get_data_form_table(struct aw_device * aw_dev,struct aw_table_info table_info,struct aw_monitor_trace * data_trace)232*4882a593Smuzhiyun static int aw_monitor_first_get_data_form_table(struct aw_device *aw_dev,
233*4882a593Smuzhiyun 				struct aw_table_info table_info,
234*4882a593Smuzhiyun 			struct aw_monitor_trace *data_trace)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	int i;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (table_info.aw_table == NULL) {
239*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "table_info.aw_table is null");
240*4882a593Smuzhiyun 		return -EINVAL;
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	for (i = 0; i < table_info.table_num; i++) {
244*4882a593Smuzhiyun 		if (data_trace->sum_val >= table_info.aw_table[i].min_val) {
245*4882a593Smuzhiyun 			memcpy(&data_trace->aw_table, &table_info.aw_table[i],
246*4882a593Smuzhiyun 				sizeof(struct aw_table));
247*4882a593Smuzhiyun 			break;
248*4882a593Smuzhiyun 		}
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 	return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
aw_monitor_trace_data_from_table(struct aw_device * aw_dev,struct aw_table_info table_info,struct aw_monitor_trace * data_trace)253*4882a593Smuzhiyun static int aw_monitor_trace_data_from_table(struct aw_device *aw_dev,
254*4882a593Smuzhiyun 			struct aw_table_info table_info,
255*4882a593Smuzhiyun 			struct aw_monitor_trace *data_trace)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun 	int i;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (table_info.aw_table == NULL) {
260*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "table_info.aw_table is null");
261*4882a593Smuzhiyun 		return -EINVAL;
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	for (i = 0; i < table_info.table_num; i++) {
265*4882a593Smuzhiyun 		if (data_trace->sum_val >= table_info.aw_table[i].min_val &&
266*4882a593Smuzhiyun 			data_trace->sum_val <= table_info.aw_table[i].max_val) {
267*4882a593Smuzhiyun 			memcpy(&data_trace->aw_table, &table_info.aw_table[i],
268*4882a593Smuzhiyun 				sizeof(struct aw_table));
269*4882a593Smuzhiyun 			break;
270*4882a593Smuzhiyun 		}
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return 0;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
aw_monitor_get_data_from_table(struct aw_device * aw_dev,struct aw_table_info table_info,struct aw_monitor_trace * data_trace,uint32_t aplha)276*4882a593Smuzhiyun static int aw_monitor_get_data_from_table(struct aw_device *aw_dev,
277*4882a593Smuzhiyun 					struct aw_table_info table_info,
278*4882a593Smuzhiyun 					struct aw_monitor_trace *data_trace,
279*4882a593Smuzhiyun 					uint32_t aplha)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	if (monitor->first_entry == AW_FIRST_ENTRY) {
284*4882a593Smuzhiyun 		return aw_monitor_first_get_data_form_table(aw_dev,
285*4882a593Smuzhiyun 						table_info, data_trace);
286*4882a593Smuzhiyun 	} else {
287*4882a593Smuzhiyun 		if (monitor->samp_count == 0) {
288*4882a593Smuzhiyun 			aw_dev_err(aw_dev->dev, "monitor->samp_count:%d unsupported", monitor->samp_count);
289*4882a593Smuzhiyun 			return -EINVAL;
290*4882a593Smuzhiyun 		}
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 		data_trace->sum_val = data_trace->sum_val / monitor->samp_count;
293*4882a593Smuzhiyun 		data_trace->sum_val = ((int32_t)aplha * data_trace->sum_val +
294*4882a593Smuzhiyun 			(1000 - (int32_t)aplha) * data_trace->pre_val) / 1000;
295*4882a593Smuzhiyun 		return aw_monitor_trace_data_from_table(aw_dev,
296*4882a593Smuzhiyun 						table_info, data_trace);
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	return 0;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
aw_monitor_get_data(struct aw_device * aw_dev)302*4882a593Smuzhiyun static int aw_monitor_get_data(struct aw_device *aw_dev)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
305*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &monitor->monitor_cfg;
306*4882a593Smuzhiyun 	struct aw_monitor_trace *vol_trace = &monitor->vol_trace;
307*4882a593Smuzhiyun 	struct aw_monitor_trace *temp_trace = &monitor->temp_trace;
308*4882a593Smuzhiyun 	int ret;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	if (monitor_cfg->vol_switch) {
311*4882a593Smuzhiyun 		ret = aw_monitor_get_data_from_table(aw_dev,
312*4882a593Smuzhiyun 			monitor_cfg->vol_info, vol_trace,
313*4882a593Smuzhiyun 			monitor_cfg->vol_aplha);
314*4882a593Smuzhiyun 		if (ret < 0)
315*4882a593Smuzhiyun 			return ret;
316*4882a593Smuzhiyun 	} else {
317*4882a593Smuzhiyun 		vol_trace->aw_table.ipeak = IPEAK_NONE;
318*4882a593Smuzhiyun 		vol_trace->aw_table.gain = GAIN_NONE;
319*4882a593Smuzhiyun 		vol_trace->aw_table.vmax = VMAX_NONE;
320*4882a593Smuzhiyun 	}
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	if (monitor_cfg->temp_switch) {
323*4882a593Smuzhiyun 		ret = aw_monitor_get_data_from_table(aw_dev,
324*4882a593Smuzhiyun 			monitor_cfg->temp_info, temp_trace,
325*4882a593Smuzhiyun 			monitor_cfg->temp_aplha);
326*4882a593Smuzhiyun 		if (ret < 0)
327*4882a593Smuzhiyun 			return ret;
328*4882a593Smuzhiyun 	} else {
329*4882a593Smuzhiyun 		temp_trace->aw_table.ipeak = IPEAK_NONE;
330*4882a593Smuzhiyun 		temp_trace->aw_table.gain = GAIN_NONE;
331*4882a593Smuzhiyun 		temp_trace->aw_table.vmax = VMAX_NONE;
332*4882a593Smuzhiyun 	}
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	aw_dev_dbg(aw_dev->dev,
335*4882a593Smuzhiyun 			"filter_vol:%d, vol: ipeak = 0x%x, gain = 0x%x, vmax = 0x%x",
336*4882a593Smuzhiyun 			monitor->vol_trace.sum_val, vol_trace->aw_table.ipeak,
337*4882a593Smuzhiyun 			vol_trace->aw_table.gain, vol_trace->aw_table.vmax);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	aw_dev_dbg(aw_dev->dev,
340*4882a593Smuzhiyun 			"filter_temp:%d, temp: ipeak = 0x%x, gain = 0x%x, vmax = 0x%x",
341*4882a593Smuzhiyun 			monitor->temp_trace.sum_val, temp_trace->aw_table.ipeak,
342*4882a593Smuzhiyun 			temp_trace->aw_table.gain, temp_trace->aw_table.vmax);
343*4882a593Smuzhiyun 	return 0;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
aw_monitor_get_cfg(struct aw_device * aw_dev,struct aw_table * set_table)346*4882a593Smuzhiyun static void aw_monitor_get_cfg(struct aw_device *aw_dev,
347*4882a593Smuzhiyun 					struct aw_table *set_table)
348*4882a593Smuzhiyun {
349*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
350*4882a593Smuzhiyun 	struct aw_table *temp_data = &monitor->temp_trace.aw_table;
351*4882a593Smuzhiyun 	struct aw_table *vol_data = &monitor->vol_trace.aw_table;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	if (temp_data->ipeak == IPEAK_NONE && vol_data->ipeak == IPEAK_NONE) {
354*4882a593Smuzhiyun 		memcpy(set_table, temp_data, sizeof(struct aw_table));
355*4882a593Smuzhiyun 	} else if (temp_data->ipeak == IPEAK_NONE) {
356*4882a593Smuzhiyun 		memcpy(set_table, vol_data, sizeof(struct aw_table));
357*4882a593Smuzhiyun 	} else if (vol_data->ipeak == IPEAK_NONE) {
358*4882a593Smuzhiyun 		memcpy(set_table, temp_data, sizeof(struct aw_table));
359*4882a593Smuzhiyun 	} else {
360*4882a593Smuzhiyun 		if (monitor->monitor_cfg.logic_switch == AW_MON_LOGIC_OR) {
361*4882a593Smuzhiyun 			set_table->ipeak = (temp_data->ipeak < vol_data->ipeak ?
362*4882a593Smuzhiyun 					temp_data->ipeak : vol_data->ipeak);
363*4882a593Smuzhiyun 			set_table->gain = (temp_data->gain < vol_data->gain ?
364*4882a593Smuzhiyun 					vol_data->gain : temp_data->gain);
365*4882a593Smuzhiyun 			set_table->vmax = (temp_data->vmax < vol_data->vmax ?
366*4882a593Smuzhiyun 					vol_data->vmax : temp_data->vmax);
367*4882a593Smuzhiyun 		} else {
368*4882a593Smuzhiyun 			set_table->ipeak = (temp_data->ipeak < vol_data->ipeak ?
369*4882a593Smuzhiyun 				vol_data->ipeak : temp_data->ipeak);
370*4882a593Smuzhiyun 			set_table->gain = (temp_data->gain < vol_data->gain ?
371*4882a593Smuzhiyun 					temp_data->gain : vol_data->gain);
372*4882a593Smuzhiyun 			set_table->vmax = (temp_data->vmax < vol_data->vmax ?
373*4882a593Smuzhiyun 					temp_data->vmax : vol_data->vmax);
374*4882a593Smuzhiyun 		}
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
aw_monitor_set_ipeak(struct aw_device * aw_dev,uint16_t ipeak)378*4882a593Smuzhiyun static void aw_monitor_set_ipeak(struct aw_device *aw_dev,
379*4882a593Smuzhiyun 				uint16_t ipeak)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &aw_dev->monitor_desc.monitor_cfg;
382*4882a593Smuzhiyun 	uint16_t reg_val = 0;
383*4882a593Smuzhiyun 	uint16_t read_reg_val;
384*4882a593Smuzhiyun 	int ret;
385*4882a593Smuzhiyun 	struct aw_ipeak_desc *desc = &aw_dev->ipeak_desc;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	if (ipeak == IPEAK_NONE || (!monitor_cfg->ipeak_switch))
388*4882a593Smuzhiyun 		return;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_reg_read(aw_dev, desc->reg, &reg_val);
391*4882a593Smuzhiyun 	if (ret < 0) {
392*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "read ipeak failed");
393*4882a593Smuzhiyun 		return;
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	read_reg_val = reg_val;
397*4882a593Smuzhiyun 	read_reg_val &= (~desc->mask);
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	if (read_reg_val == ipeak) {
400*4882a593Smuzhiyun 		aw_dev_dbg(aw_dev->dev, "ipeak = 0x%x, no change",
401*4882a593Smuzhiyun 					read_reg_val);
402*4882a593Smuzhiyun 		return;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun 	reg_val &= desc->mask;
405*4882a593Smuzhiyun 	read_reg_val = ipeak;
406*4882a593Smuzhiyun 	reg_val |= read_reg_val;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_reg_write(aw_dev, desc->reg, reg_val);
409*4882a593Smuzhiyun 	if (ret < 0) {
410*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "write ipeak failed");
411*4882a593Smuzhiyun 		return;
412*4882a593Smuzhiyun 	}
413*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "set reg val = 0x%x, ipeak = 0x%x",
414*4882a593Smuzhiyun 				reg_val, ipeak);
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
aw_monitor_set_gain(struct aw_device * aw_dev,uint16_t gain)418*4882a593Smuzhiyun static void aw_monitor_set_gain(struct aw_device *aw_dev, uint16_t gain)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &aw_dev->monitor_desc.monitor_cfg;
421*4882a593Smuzhiyun 	uint16_t read_volume;
422*4882a593Smuzhiyun 	uint16_t set_volume;
423*4882a593Smuzhiyun 	int ret;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	if (gain == GAIN_NONE || (!monitor_cfg->gain_switch))
426*4882a593Smuzhiyun 		return;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_get_volume(aw_dev, &read_volume);
429*4882a593Smuzhiyun 	if (ret < 0) {
430*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "read volume failed");
431*4882a593Smuzhiyun 		return;
432*4882a593Smuzhiyun 	}
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	gain = aw_dev->ops.aw_reg_val_to_db(gain);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	/*add offset*/
437*4882a593Smuzhiyun 	set_volume = gain + aw_dev->volume_desc.init_volume;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	if (read_volume == set_volume) {
440*4882a593Smuzhiyun 		aw_dev_dbg(aw_dev->dev, "gain = 0x%x, no change", read_volume);
441*4882a593Smuzhiyun 		return;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_set_volume(aw_dev, set_volume);
445*4882a593Smuzhiyun 	if (ret < 0) {
446*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "set gain failed");
447*4882a593Smuzhiyun 		return;
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "set reg val = 0x%x, gain = 0x%x",
450*4882a593Smuzhiyun 				set_volume, gain);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun 
aw_monitor_vmax_check(struct aw_device * aw_dev)454*4882a593Smuzhiyun static int aw_monitor_vmax_check(struct aw_device *aw_dev)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	int ret = -1;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	ret = aw_dev_syspll_check(aw_dev);
459*4882a593Smuzhiyun 	if (ret < 0) {
460*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "no iis signal");
461*4882a593Smuzhiyun 		return ret;
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	ret = aw_dev_get_dsp_status(aw_dev);
465*4882a593Smuzhiyun 	if (ret < 0) {
466*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "dsp not work");
467*4882a593Smuzhiyun 		return ret;
468*4882a593Smuzhiyun 	}
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	return 0;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
aw_monitor_set_vmax(struct aw_device * aw_dev,uint32_t vmax)473*4882a593Smuzhiyun static void aw_monitor_set_vmax(struct aw_device *aw_dev,
474*4882a593Smuzhiyun 						uint32_t vmax)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &aw_dev->monitor_desc.monitor_cfg;
477*4882a593Smuzhiyun 	struct aw_vmax_desc *desc = &aw_dev->vmax_desc;
478*4882a593Smuzhiyun 	uint16_t vmax_set;
479*4882a593Smuzhiyun 	int ret = -1;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	if (vmax == VMAX_NONE || (!monitor_cfg->vmax_switch))
482*4882a593Smuzhiyun 		return;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	ret = aw_monitor_vmax_check(aw_dev);
485*4882a593Smuzhiyun 	if (ret < 0) {
486*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "vmax_check fail, ret=%d", ret);
487*4882a593Smuzhiyun 		return;
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	if ((vmax == aw_dev->monitor_desc.pre_vmax) &&
491*4882a593Smuzhiyun 		(aw_dev->monitor_desc.first_entry != AW_FIRST_ENTRY)) {
492*4882a593Smuzhiyun 		aw_dev_dbg(aw_dev->dev, "vmax = 0x%x, no change", vmax);
493*4882a593Smuzhiyun 		return;
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	vmax_set = (uint16_t)((int16_t)vmax +
497*4882a593Smuzhiyun 		(int16_t)aw_dev->vmax_desc.init_vmax);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	ret = aw_dev->ops.aw_dsp_write(aw_dev,
501*4882a593Smuzhiyun 		desc->dsp_reg, vmax_set, desc->data_type);
502*4882a593Smuzhiyun 	if (ret < 0)
503*4882a593Smuzhiyun 		return;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "get monitor vmax = 0x%x, set vmax = 0x%x",
506*4882a593Smuzhiyun 		vmax, vmax_set);
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
aw_monitor_check_sysint(struct aw_device * aw_dev)509*4882a593Smuzhiyun static void aw_monitor_check_sysint(struct aw_device *aw_dev)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun 	int ret = -1;
512*4882a593Smuzhiyun 	uint16_t sysint;
513*4882a593Smuzhiyun 	struct aw_int_desc *desc = &aw_dev->int_desc;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	ret = aw_dev_get_int_status(aw_dev, &sysint);
516*4882a593Smuzhiyun 	if (ret < 0)
517*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "get_sysint fail, ret=%d", ret);
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	if (sysint & (desc->intst_mask)) {
520*4882a593Smuzhiyun 		desc->sysint_st = sysint;
521*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "check sysint fail, reg=0x%04x", sysint);
522*4882a593Smuzhiyun 	}
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun 
aw_monitor_work(struct aw_device * aw_dev)525*4882a593Smuzhiyun static int aw_monitor_work(struct aw_device *aw_dev)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
528*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &monitor->monitor_cfg;
529*4882a593Smuzhiyun 	struct aw_table set_table;
530*4882a593Smuzhiyun 	int ret = -1;
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun 	if (aw_cali_svc_get_cali_status(&aw_dev->cali_desc)) {
533*4882a593Smuzhiyun 		aw_dev_info(aw_dev->dev, "done nothing during calibration");
534*4882a593Smuzhiyun 		return 0;
535*4882a593Smuzhiyun 	}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	ret = aw_monitor_get_temp_and_vol(aw_dev);
538*4882a593Smuzhiyun 	if (ret < 0)
539*4882a593Smuzhiyun 		return ret;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	if (monitor->samp_count < monitor_cfg->monitor_count &&
542*4882a593Smuzhiyun 		(monitor->first_entry == AW_NOT_FIRST_ENTRY))
543*4882a593Smuzhiyun 		return 0;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	ret = aw_monitor_get_data(aw_dev);
546*4882a593Smuzhiyun 	if (ret < 0)
547*4882a593Smuzhiyun 		return ret;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	aw_monitor_get_cfg(aw_dev, &set_table);
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	aw_dev_dbg(aw_dev->dev,
552*4882a593Smuzhiyun 		"set_ipeak = 0x%x, set_gain = 0x%x, set_vmax = 0x%x",
553*4882a593Smuzhiyun 		set_table.ipeak, set_table.gain, set_table.vmax);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	aw_monitor_set_ipeak(aw_dev, set_table.ipeak);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	aw_monitor_set_gain(aw_dev, set_table.gain);
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	aw_monitor_set_vmax(aw_dev, set_table.vmax);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	aw_monitor_check_sysint(aw_dev);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	monitor->samp_count = 0;
564*4882a593Smuzhiyun 	monitor->temp_trace.pre_val = monitor->temp_trace.sum_val;
565*4882a593Smuzhiyun 	monitor->temp_trace.sum_val = 0;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	monitor->vol_trace.pre_val = monitor->vol_trace.sum_val;
568*4882a593Smuzhiyun 	monitor->vol_trace.sum_val = 0;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	if (monitor->first_entry == AW_FIRST_ENTRY)
571*4882a593Smuzhiyun 		monitor->first_entry = AW_NOT_FIRST_ENTRY;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	return 0;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
aw_monitor_work_func(struct work_struct * work)576*4882a593Smuzhiyun static void aw_monitor_work_func(struct work_struct *work)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun 	struct aw_device *aw_dev  = container_of(work,
579*4882a593Smuzhiyun 		struct aw_device, monitor_desc.delay_work.work);
580*4882a593Smuzhiyun 	struct aw883xx *aw883xx = (struct aw883xx *)aw_dev->private_data;
581*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &aw_dev->monitor_desc.monitor_cfg;
582*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	aw_dev_dbg(aw_dev->dev, "scene_mode %d,monitor_status:%d, monitor_switch:%d",
585*4882a593Smuzhiyun 		aw_dev->cur_prof, monitor_cfg->monitor_status,
586*4882a593Smuzhiyun 		monitor_cfg->monitor_switch);
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	if ((monitor_cfg->monitor_status == AW_MON_CFG_OK) &&
589*4882a593Smuzhiyun 		monitor_cfg->monitor_switch) {
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 		if (!aw_dev_get_hmute(aw_dev)) {
592*4882a593Smuzhiyun 			aw_monitor_work(aw_dev);
593*4882a593Smuzhiyun 			queue_delayed_work(aw883xx->work_queue,
594*4882a593Smuzhiyun 				&monitor->delay_work,
595*4882a593Smuzhiyun 				msecs_to_jiffies(monitor_cfg->monitor_time));
596*4882a593Smuzhiyun 		}
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	}
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
aw_hw_monitor_work(struct aw_device * aw_dev)601*4882a593Smuzhiyun static int aw_hw_monitor_work(struct aw_device *aw_dev)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun 	int32_t sys_temp = 0;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	aw_monitor_get_system_temperature(aw_dev, &sys_temp);
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun 	aw_monitor_set_system_temperature(aw_dev, sys_temp);
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	return 0;
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
aw_hw_monitor_work_func(struct work_struct * work)612*4882a593Smuzhiyun static void aw_hw_monitor_work_func(struct work_struct *work)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun 	struct aw_device *aw_dev  = container_of(work,
615*4882a593Smuzhiyun 		struct aw_device, monitor_desc.hw_monitor_work.work);
616*4882a593Smuzhiyun 	struct aw883xx *aw883xx = (struct aw883xx *)aw_dev->private_data;
617*4882a593Smuzhiyun 	struct aw_monitor_desc *monitor = &aw_dev->monitor_desc;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	if (!aw_dev_get_hmute(aw_dev)) {
620*4882a593Smuzhiyun 		aw_hw_monitor_work(aw_dev);
621*4882a593Smuzhiyun 		queue_delayed_work(aw883xx->work_queue,
622*4882a593Smuzhiyun 					&monitor->hw_monitor_work,
623*4882a593Smuzhiyun 					msecs_to_jiffies(monitor->hw_monitor_delay));
624*4882a593Smuzhiyun 	}
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun 
aw_monitor_start(struct aw_monitor_desc * monitor_desc)627*4882a593Smuzhiyun void aw_monitor_start(struct aw_monitor_desc *monitor_desc)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	uint8_t temp_flag = monitor_desc->hw_temp_flag;
630*4882a593Smuzhiyun 	struct aw_device *aw_dev = container_of(monitor_desc,
631*4882a593Smuzhiyun 			struct aw_device, monitor_desc);
632*4882a593Smuzhiyun 	struct aw883xx *aw883xx = (struct aw883xx *)aw_dev->private_data;
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "enter");
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	if (aw_dev->profctrl_desc.cur_mode == AW_RCV_MODE) {
637*4882a593Smuzhiyun 		aw_dev_dbg(aw_dev->dev, "receiver mode no need to start monitor");
638*4882a593Smuzhiyun 		return;
639*4882a593Smuzhiyun 	}
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	if (monitor_desc->hw_mon_en) {
642*4882a593Smuzhiyun 		aw_dev_info(aw_dev->dev, "hardware monitor is enable");
643*4882a593Smuzhiyun 		if (temp_flag == AW_EXTERNAL_TEMP) {
644*4882a593Smuzhiyun 			queue_delayed_work(aw883xx->work_queue,
645*4882a593Smuzhiyun 					&monitor_desc->hw_monitor_work, 0);
646*4882a593Smuzhiyun 		} else {
647*4882a593Smuzhiyun 			aw_dev_dbg(aw_dev->dev, "Internal chip temperature used");
648*4882a593Smuzhiyun 		}
649*4882a593Smuzhiyun 		return;
650*4882a593Smuzhiyun 	}
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	monitor_desc->first_entry = AW_FIRST_ENTRY;
653*4882a593Smuzhiyun 	monitor_desc->samp_count = 0;
654*4882a593Smuzhiyun 	monitor_desc->vol_trace.sum_val = 0;
655*4882a593Smuzhiyun 	monitor_desc->temp_trace.sum_val = 0;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	queue_delayed_work(aw883xx->work_queue,
658*4882a593Smuzhiyun 				&monitor_desc->delay_work, 0);
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun 
aw_monitor_stop(struct aw_monitor_desc * monitor_desc)661*4882a593Smuzhiyun int aw_monitor_stop(struct aw_monitor_desc *monitor_desc)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun 	struct aw_device *aw_dev = container_of(monitor_desc,
664*4882a593Smuzhiyun 			struct aw_device, monitor_desc);
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "enter");
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	cancel_delayed_work_sync(&monitor_desc->delay_work);
669*4882a593Smuzhiyun 	cancel_delayed_work_sync(&monitor_desc->hw_monitor_work);
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	return 0;
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun /*****************************************************
676*4882a593Smuzhiyun * load monitor config
677*4882a593Smuzhiyun *****************************************************/
aw_monitor_param_check_sum(struct aw_device * aw_dev,uint8_t * data,uint32_t data_len)678*4882a593Smuzhiyun static int aw_monitor_param_check_sum(struct aw_device *aw_dev,
679*4882a593Smuzhiyun 					uint8_t *data, uint32_t data_len)
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun 	int i, check_sum = 0;
682*4882a593Smuzhiyun 	struct aw_monitor_hdr_v_0_1_1 *monitor_hdr =
683*4882a593Smuzhiyun 		(struct aw_monitor_hdr_v_0_1_1 *)data;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	if (data_len < sizeof(struct aw_monitor_hdr_v_0_1_1)) {
686*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev,
687*4882a593Smuzhiyun 			"data size smaller than hdr , please check monitor bin");
688*4882a593Smuzhiyun 		return -ENOMEM;
689*4882a593Smuzhiyun 	}
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	for (i = 4 ; i < data_len; i++)
692*4882a593Smuzhiyun 		check_sum += (uint8_t)data[i];
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	if (monitor_hdr->check_sum != check_sum) {
695*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev,
696*4882a593Smuzhiyun 			"check_sum[%d] is not equal to actual check_sum[%d]",
697*4882a593Smuzhiyun 				monitor_hdr->check_sum, check_sum);
698*4882a593Smuzhiyun 		return -ENOMEM;
699*4882a593Smuzhiyun 	}
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	return 0;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun 
aw_monitor_write_data_to_table(struct aw_device * aw_dev,struct aw_table_info * table_info,const char * offset_ptr)704*4882a593Smuzhiyun static void aw_monitor_write_data_to_table(struct aw_device *aw_dev,
705*4882a593Smuzhiyun 		struct aw_table_info *table_info, const char *offset_ptr)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	int i;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	for (i = 0; i < table_info->table_num * AW_TABLE_SIZE; i += AW_TABLE_SIZE) {
710*4882a593Smuzhiyun 		table_info->aw_table[i / AW_TABLE_SIZE].min_val =
711*4882a593Smuzhiyun 			AW_GET_16_DATA(offset_ptr[1 + i], offset_ptr[i]);
712*4882a593Smuzhiyun 		table_info->aw_table[i / AW_TABLE_SIZE].max_val =
713*4882a593Smuzhiyun 			AW_GET_16_DATA(offset_ptr[3 + i], offset_ptr[2 + i]);
714*4882a593Smuzhiyun 		table_info->aw_table[i / AW_TABLE_SIZE].ipeak =
715*4882a593Smuzhiyun 			AW_GET_16_DATA(offset_ptr[5 + i], offset_ptr[4 + i]);
716*4882a593Smuzhiyun 		table_info->aw_table[i / AW_TABLE_SIZE].gain =
717*4882a593Smuzhiyun 			AW_GET_16_DATA(offset_ptr[7 + i], offset_ptr[6 + i]);
718*4882a593Smuzhiyun 		table_info->aw_table[i / AW_TABLE_SIZE].vmax =
719*4882a593Smuzhiyun 			AW_GET_32_DATA(offset_ptr[11 + i], offset_ptr[10 + i],
720*4882a593Smuzhiyun 				offset_ptr[9 + i], offset_ptr[8 + i]);
721*4882a593Smuzhiyun 	}
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	for (i = 0; i < table_info->table_num; i++)
724*4882a593Smuzhiyun 		aw_dev_info(aw_dev->dev,
725*4882a593Smuzhiyun 			"min_val:%d, max_val:%d, ipeak:0x%x, gain:0x%x, vmax:0x%x",
726*4882a593Smuzhiyun 			table_info->aw_table[i].min_val,
727*4882a593Smuzhiyun 			table_info->aw_table[i].max_val,
728*4882a593Smuzhiyun 			table_info->aw_table[i].ipeak,
729*4882a593Smuzhiyun 			table_info->aw_table[i].gain,
730*4882a593Smuzhiyun 			table_info->aw_table[i].vmax);
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun 
aw_monitor_parse_vol_data_v_0_1_1(struct aw_device * aw_dev,uint8_t * data)734*4882a593Smuzhiyun static int aw_monitor_parse_vol_data_v_0_1_1(struct aw_device *aw_dev, uint8_t *data)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	struct aw_monitor_hdr_v_0_1_1 *monitor_hdr =
737*4882a593Smuzhiyun 			(struct aw_monitor_hdr_v_0_1_1 *)data;
738*4882a593Smuzhiyun 	struct aw_table_info *vol_info =
739*4882a593Smuzhiyun 		&aw_dev->monitor_desc.monitor_cfg.vol_info;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "===parse vol start ===");
742*4882a593Smuzhiyun 	if (vol_info->aw_table != NULL) {
743*4882a593Smuzhiyun 		devm_kfree(aw_dev->dev, vol_info->aw_table);
744*4882a593Smuzhiyun 		vol_info->aw_table = NULL;
745*4882a593Smuzhiyun 	}
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	vol_info->aw_table = devm_kzalloc(aw_dev->dev,
748*4882a593Smuzhiyun 					(monitor_hdr->vol_num * AW_TABLE_SIZE),
749*4882a593Smuzhiyun 					GFP_KERNEL);
750*4882a593Smuzhiyun 	if (vol_info->aw_table == NULL)
751*4882a593Smuzhiyun 		return -ENOMEM;
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	vol_info->table_num = monitor_hdr->vol_num;
754*4882a593Smuzhiyun 	aw_monitor_write_data_to_table(aw_dev, vol_info,
755*4882a593Smuzhiyun 		&data[monitor_hdr->vol_offset]);
756*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "===parse vol end ===");
757*4882a593Smuzhiyun 	return 0;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun 
aw_monitor_parse_temp_data_v_0_1_1(struct aw_device * aw_dev,uint8_t * data)760*4882a593Smuzhiyun static int aw_monitor_parse_temp_data_v_0_1_1(struct aw_device *aw_dev, uint8_t *data)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun 	struct aw_monitor_hdr_v_0_1_1 *monitor_hdr =
763*4882a593Smuzhiyun 			(struct aw_monitor_hdr_v_0_1_1 *)data;
764*4882a593Smuzhiyun 	struct aw_table_info *temp_info =
765*4882a593Smuzhiyun 		&aw_dev->monitor_desc.monitor_cfg.temp_info;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "===parse temp start ===");
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	if (temp_info->aw_table != NULL) {
770*4882a593Smuzhiyun 		devm_kfree(aw_dev->dev, temp_info->aw_table);
771*4882a593Smuzhiyun 		temp_info->aw_table = NULL;
772*4882a593Smuzhiyun 	}
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	temp_info->aw_table = devm_kzalloc(aw_dev->dev,
775*4882a593Smuzhiyun 					(monitor_hdr->temp_num * AW_TABLE_SIZE),
776*4882a593Smuzhiyun 					GFP_KERNEL);
777*4882a593Smuzhiyun 	if (temp_info->aw_table == NULL)
778*4882a593Smuzhiyun 		return -ENOMEM;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	temp_info->table_num = monitor_hdr->temp_num;
781*4882a593Smuzhiyun 	aw_monitor_write_data_to_table(aw_dev, temp_info,
782*4882a593Smuzhiyun 		&data[monitor_hdr->temp_offset]);
783*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "===parse temp end ===");
784*4882a593Smuzhiyun 	return 0;
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun 
aw_monitor_parse_hdr_v_0_1_1(struct aw_device * aw_dev,uint8_t * data)787*4882a593Smuzhiyun static void aw_monitor_parse_hdr_v_0_1_1(struct aw_device *aw_dev, uint8_t *data)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun 	struct aw_monitor_hdr_v_0_1_1 *monitor_hdr =
790*4882a593Smuzhiyun 			(struct aw_monitor_hdr_v_0_1_1 *)data;
791*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &aw_dev->monitor_desc.monitor_cfg;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	monitor_cfg->monitor_switch =
794*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_EN_BIT) & MONITOR_EN_MASK;
795*4882a593Smuzhiyun 	monitor_cfg->monitor_time = monitor_hdr->monitor_time;
796*4882a593Smuzhiyun 	monitor_cfg->monitor_count = monitor_hdr->monitor_count;
797*4882a593Smuzhiyun 	monitor_cfg->ipeak_switch =
798*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_IPEAK_EN_BIT) & MONITOR_EN_MASK;
799*4882a593Smuzhiyun 	monitor_cfg->logic_switch =
800*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_LOGIC_BIT) & MONITOR_EN_MASK;
801*4882a593Smuzhiyun 	monitor_cfg->gain_switch =
802*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_GAIN_EN_BIT) & MONITOR_EN_MASK;
803*4882a593Smuzhiyun 	monitor_cfg->vmax_switch =
804*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_VMAX_EN_BIT) & MONITOR_EN_MASK;
805*4882a593Smuzhiyun 	monitor_cfg->temp_switch =
806*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_TEMP_EN_BIT) & MONITOR_EN_MASK;
807*4882a593Smuzhiyun 	monitor_cfg->temp_aplha = monitor_hdr->temp_aplha;
808*4882a593Smuzhiyun 	monitor_cfg->vol_switch =
809*4882a593Smuzhiyun 		(monitor_hdr->enable_flag >> MONITOR_VOL_EN_BIT) & MONITOR_EN_MASK;
810*4882a593Smuzhiyun 	monitor_cfg->vol_aplha = monitor_hdr->vol_aplha;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "chip name:%s",
813*4882a593Smuzhiyun 		monitor_hdr->chip_type);
814*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "ui ver:0x%x",
815*4882a593Smuzhiyun 		monitor_hdr->ui_ver);
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev,
818*4882a593Smuzhiyun 		"monitor_switch:%d, monitor_time:%d (ms), monitor_count:%d",
819*4882a593Smuzhiyun 		monitor_cfg->monitor_switch, monitor_cfg->monitor_time,
820*4882a593Smuzhiyun 		monitor_cfg->monitor_count);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev,
823*4882a593Smuzhiyun 		"logic_switch:%d, ipeak_switch:%d, gain_switch:%d, vmax_switch:%d",
824*4882a593Smuzhiyun 		monitor_cfg->logic_switch, monitor_cfg->ipeak_switch,
825*4882a593Smuzhiyun 		monitor_cfg->gain_switch, monitor_cfg->vmax_switch);
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev,
828*4882a593Smuzhiyun 		"temp_switch:%d, temp_aplha:%d, vol_switch:%d, vol_aplha:%d",
829*4882a593Smuzhiyun 		monitor_cfg->temp_switch, monitor_cfg->temp_aplha,
830*4882a593Smuzhiyun 		monitor_cfg->vol_switch, monitor_cfg->vol_aplha);
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun 
aw_monitor_check_fw_v_0_1_1(struct aw_device * aw_dev,uint8_t * data,uint32_t data_len)833*4882a593Smuzhiyun static int aw_monitor_check_fw_v_0_1_1(struct aw_device *aw_dev,
834*4882a593Smuzhiyun 					uint8_t *data, uint32_t data_len)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun 	struct aw_monitor_hdr_v_0_1_1 *monitor_hdr =
837*4882a593Smuzhiyun 				(struct aw_monitor_hdr_v_0_1_1 *)data;
838*4882a593Smuzhiyun 	int temp_size, vol_size;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	if (data_len < sizeof(struct aw_monitor_hdr_v_0_1_1)) {
841*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev,
842*4882a593Smuzhiyun 			"params size[%d] < struct aw_monitor_hdr size[%d]!",
843*4882a593Smuzhiyun 			data_len, (int)sizeof(struct aw_monitor_hdr_v_0_1_1));
844*4882a593Smuzhiyun 		return -ENOMEM;
845*4882a593Smuzhiyun 	}
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	if (monitor_hdr->temp_offset > data_len) {
848*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "temp_offset[%d] overflow file size[%d]!",
849*4882a593Smuzhiyun 			monitor_hdr->temp_offset, data_len);
850*4882a593Smuzhiyun 		return -ENOMEM;
851*4882a593Smuzhiyun 	}
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun 	if (monitor_hdr->vol_offset > data_len) {
854*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "vol_offset[%d] overflow file size[%d]!",
855*4882a593Smuzhiyun 			monitor_hdr->vol_offset, data_len);
856*4882a593Smuzhiyun 		return -ENOMEM;
857*4882a593Smuzhiyun 	}
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	temp_size = monitor_hdr->temp_num * monitor_hdr->single_temp_size;
860*4882a593Smuzhiyun 	if (temp_size > data_len) {
861*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "temp_size:[%d] overflow file size[%d]!",
862*4882a593Smuzhiyun 			temp_size, data_len);
863*4882a593Smuzhiyun 		return -ENOMEM;
864*4882a593Smuzhiyun 	}
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun 	vol_size = monitor_hdr->vol_num * monitor_hdr->single_vol_size;
867*4882a593Smuzhiyun 	if (vol_size > data_len) {
868*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "vol_size:[%d] overflow file size[%d]!",
869*4882a593Smuzhiyun 			vol_size, data_len);
870*4882a593Smuzhiyun 		return -ENOMEM;
871*4882a593Smuzhiyun 	}
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	return 0;
874*4882a593Smuzhiyun }
875*4882a593Smuzhiyun 
aw_monitor_parse_data_v_0_1_1(struct aw_device * aw_dev,uint8_t * data,uint32_t data_len)876*4882a593Smuzhiyun static int aw_monitor_parse_data_v_0_1_1(struct aw_device *aw_dev,
877*4882a593Smuzhiyun 				uint8_t *data, uint32_t data_len)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun 	int ret;
880*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg = &aw_dev->monitor_desc.monitor_cfg;
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun 	ret = aw_monitor_check_fw_v_0_1_1(aw_dev, data, data_len);
883*4882a593Smuzhiyun 	if (ret < 0) {
884*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "check monitor failed");
885*4882a593Smuzhiyun 		return ret;
886*4882a593Smuzhiyun 	}
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 	aw_monitor_parse_hdr_v_0_1_1(aw_dev, data);
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	ret = aw_monitor_parse_temp_data_v_0_1_1(aw_dev, data);
891*4882a593Smuzhiyun 	if (ret < 0)
892*4882a593Smuzhiyun 		return ret;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 	ret = aw_monitor_parse_vol_data_v_0_1_1(aw_dev, data);
895*4882a593Smuzhiyun 	if (ret < 0) {
896*4882a593Smuzhiyun 		if (monitor_cfg->temp_info.aw_table != NULL) {
897*4882a593Smuzhiyun 			devm_kfree(aw_dev->dev, monitor_cfg->temp_info.aw_table);
898*4882a593Smuzhiyun 			monitor_cfg->temp_info.aw_table = NULL;
899*4882a593Smuzhiyun 			monitor_cfg->temp_info.table_num = 0;
900*4882a593Smuzhiyun 		}
901*4882a593Smuzhiyun 		return ret;
902*4882a593Smuzhiyun 	}
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	monitor_cfg->monitor_status = AW_MON_CFG_OK;
905*4882a593Smuzhiyun 	return 0;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun 
aw_monitor_parse_fw(struct aw_monitor_desc * monitor_desc,uint8_t * data,uint32_t data_len)908*4882a593Smuzhiyun int aw_monitor_parse_fw(struct aw_monitor_desc *monitor_desc,
909*4882a593Smuzhiyun 				uint8_t *data, uint32_t data_len)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun 	struct aw_monitor_hdr_v_0_1_1 *monitor_hdr = NULL;
912*4882a593Smuzhiyun 	struct aw_device *aw_dev = NULL;
913*4882a593Smuzhiyun 	int ret;
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	if (monitor_desc == NULL || data == NULL) {
916*4882a593Smuzhiyun 		pr_err("monitor_desc or data is NULL");
917*4882a593Smuzhiyun 		return -EINVAL;
918*4882a593Smuzhiyun 	}
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	monitor_hdr = (struct aw_monitor_hdr_v_0_1_1 *)data;
921*4882a593Smuzhiyun 	aw_dev = container_of(monitor_desc,
922*4882a593Smuzhiyun 			struct aw_device, monitor_desc);
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	ret = aw_monitor_param_check_sum(aw_dev, data, data_len);
925*4882a593Smuzhiyun 	if (ret < 0)
926*4882a593Smuzhiyun 		return ret;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	switch (monitor_hdr->monitor_ver) {
929*4882a593Smuzhiyun 	case AW_MONITOR_HDR_VER_0_1_1:
930*4882a593Smuzhiyun 		return aw_monitor_parse_data_v_0_1_1(aw_dev, data, data_len);
931*4882a593Smuzhiyun 	default:
932*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "cfg version:0x%x unsupported",
933*4882a593Smuzhiyun 				monitor_hdr->monitor_ver);
934*4882a593Smuzhiyun 		return -EINVAL;
935*4882a593Smuzhiyun 	}
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun 
aw_monitor_free_firmware(struct aw_device * aw_dev)938*4882a593Smuzhiyun static void aw_monitor_free_firmware(struct aw_device *aw_dev)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun 	struct aw_monitor_cfg *monitor_cfg =
941*4882a593Smuzhiyun 				&aw_dev->monitor_desc.monitor_cfg;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	monitor_cfg->monitor_status = AW_MON_CFG_ST;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	if (monitor_cfg->temp_info.aw_table != NULL) {
946*4882a593Smuzhiyun 		devm_kfree(aw_dev->dev, monitor_cfg->temp_info.aw_table);
947*4882a593Smuzhiyun 		monitor_cfg->temp_info.aw_table = NULL;
948*4882a593Smuzhiyun 	}
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	if (monitor_cfg->vol_info.aw_table != NULL) {
951*4882a593Smuzhiyun 		devm_kfree(aw_dev->dev, monitor_cfg->vol_info.aw_table);
952*4882a593Smuzhiyun 		monitor_cfg->vol_info.aw_table = NULL;
953*4882a593Smuzhiyun 	}
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun 	memset(monitor_cfg, 0, sizeof(struct aw_monitor_cfg));
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun 
aw_monitor_real_time_update_monitor(struct aw_device * aw_dev)958*4882a593Smuzhiyun static int aw_monitor_real_time_update_monitor(struct aw_device *aw_dev)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun 	const struct firmware *cont = NULL;
961*4882a593Smuzhiyun 	struct aw_container *aw_monitor_cnt = NULL;
962*4882a593Smuzhiyun 	int ret;
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 	ret = request_firmware(&cont, AW883XX_MONITOR_NAME, aw_dev->dev);
965*4882a593Smuzhiyun 	if (ret < 0) {
966*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "failed to read %s", AW883XX_MONITOR_NAME);
967*4882a593Smuzhiyun 		release_firmware(cont);
968*4882a593Smuzhiyun 		return ret;
969*4882a593Smuzhiyun 	}
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	aw_monitor_cnt = devm_kzalloc(aw_dev->dev,
972*4882a593Smuzhiyun 			cont->size + sizeof(uint32_t), GFP_KERNEL);
973*4882a593Smuzhiyun 	if (aw_monitor_cnt == NULL) {
974*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "alloc failed!");
975*4882a593Smuzhiyun 		release_firmware(cont);
976*4882a593Smuzhiyun 		return ret;
977*4882a593Smuzhiyun 	}
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun 	aw_monitor_cnt->len = cont->size;
980*4882a593Smuzhiyun 	memcpy(aw_monitor_cnt->data, cont->data, cont->size);
981*4882a593Smuzhiyun 	release_firmware(cont);
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	ret = aw_monitor_parse_fw(&aw_dev->monitor_desc,
984*4882a593Smuzhiyun 			aw_monitor_cnt->data, aw_monitor_cnt->len);
985*4882a593Smuzhiyun 	if (ret < 0)
986*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "parse monitor firmware failed!");
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	devm_kfree(aw_dev->dev, aw_monitor_cnt);
989*4882a593Smuzhiyun 	aw_monitor_cnt = NULL;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	return ret;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun /*****************************************************
995*4882a593Smuzhiyun  * monitor init
996*4882a593Smuzhiyun  *****************************************************/
997*4882a593Smuzhiyun #ifdef AW_DEBUG
aw_vol_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)998*4882a593Smuzhiyun static ssize_t aw_vol_store(struct device *dev,
999*4882a593Smuzhiyun 	struct device_attribute *attr, const char *buf, size_t count)
1000*4882a593Smuzhiyun {
1001*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1002*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1003*4882a593Smuzhiyun 	uint32_t vol = 0;
1004*4882a593Smuzhiyun 	int ret = -1;
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	if (count == 0)
1007*4882a593Smuzhiyun 		return 0;
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun 	ret = kstrtouint(buf, 0, &vol);
1010*4882a593Smuzhiyun 	if (ret < 0)
1011*4882a593Smuzhiyun 		return ret;
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "vol set =%d", vol);
1014*4882a593Smuzhiyun 	aw_dev->monitor_desc.test_vol = vol;
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	return count;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun 
aw_vol_show(struct device * dev,struct device_attribute * attr,char * buf)1019*4882a593Smuzhiyun static ssize_t aw_vol_show(struct device *dev,
1020*4882a593Smuzhiyun 	struct device_attribute *attr, char *buf)
1021*4882a593Smuzhiyun {
1022*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1023*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1024*4882a593Smuzhiyun 	ssize_t len = 0;
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	len += snprintf(buf+len, PAGE_SIZE-len,
1027*4882a593Smuzhiyun 		"vol: %d\n",
1028*4882a593Smuzhiyun 		aw_dev->monitor_desc.test_vol);
1029*4882a593Smuzhiyun 	return len;
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun 
aw_temp_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1032*4882a593Smuzhiyun static ssize_t aw_temp_store(struct device *dev,
1033*4882a593Smuzhiyun 	struct device_attribute *attr, const char *buf, size_t count)
1034*4882a593Smuzhiyun {
1035*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1036*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1037*4882a593Smuzhiyun 	int32_t temp = 0;
1038*4882a593Smuzhiyun 	int ret = -1;
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	if (count == 0)
1041*4882a593Smuzhiyun 		return 0;
1042*4882a593Smuzhiyun 
1043*4882a593Smuzhiyun 	ret = kstrtoint(buf, 0, &temp);
1044*4882a593Smuzhiyun 	if (ret < 0)
1045*4882a593Smuzhiyun 		return ret;
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "temp set =%d", temp);
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun 	aw_dev->monitor_desc.test_temp = temp;
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun 	return count;
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun 
aw_temp_show(struct device * dev,struct device_attribute * attr,char * buf)1054*4882a593Smuzhiyun static ssize_t aw_temp_show(struct device *dev,
1055*4882a593Smuzhiyun 	struct device_attribute *attr, char *buf)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1058*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1059*4882a593Smuzhiyun 	ssize_t len = 0;
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	len += snprintf(buf+len, PAGE_SIZE-len,
1062*4882a593Smuzhiyun 		"aw883xx temp: %d\n",
1063*4882a593Smuzhiyun 		aw_dev->monitor_desc.test_temp);
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 	return len;
1066*4882a593Smuzhiyun }
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun static DEVICE_ATTR(vol, S_IWUSR | S_IRUGO,
1069*4882a593Smuzhiyun 	aw_vol_show, aw_vol_store);
1070*4882a593Smuzhiyun static DEVICE_ATTR(temp, S_IWUSR | S_IRUGO,
1071*4882a593Smuzhiyun 	aw_temp_show, aw_temp_store);
1072*4882a593Smuzhiyun #endif
1073*4882a593Smuzhiyun 
aw_monitor_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1074*4882a593Smuzhiyun static ssize_t aw_monitor_store(struct device *dev,
1075*4882a593Smuzhiyun 	struct device_attribute *attr, const char *buf, size_t count)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1078*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1079*4882a593Smuzhiyun 	uint32_t enable = 0;
1080*4882a593Smuzhiyun 	int ret = -1;
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun 	if (count == 0)
1083*4882a593Smuzhiyun 		return 0;
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun 	ret = kstrtouint(buf, 0, &enable);
1086*4882a593Smuzhiyun 	if (ret < 0)
1087*4882a593Smuzhiyun 		return ret;
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "monitor enable set =%d", enable);
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	if (aw_dev->monitor_desc.monitor_cfg.monitor_switch == enable) {
1092*4882a593Smuzhiyun 		return count;
1093*4882a593Smuzhiyun 	} else {
1094*4882a593Smuzhiyun 		aw_dev->monitor_desc.monitor_cfg.monitor_switch = enable;
1095*4882a593Smuzhiyun 		if (enable)
1096*4882a593Smuzhiyun 			aw_monitor_start(&aw_dev->monitor_desc);
1097*4882a593Smuzhiyun 	}
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun 	return count;
1100*4882a593Smuzhiyun }
1101*4882a593Smuzhiyun 
aw_monitor_show(struct device * dev,struct device_attribute * attr,char * buf)1102*4882a593Smuzhiyun static ssize_t aw_monitor_show(struct device *dev,
1103*4882a593Smuzhiyun 	struct device_attribute *attr, char *buf)
1104*4882a593Smuzhiyun {
1105*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1106*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1107*4882a593Smuzhiyun 	ssize_t len = 0;
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	len += snprintf(buf+len, PAGE_SIZE-len,
1111*4882a593Smuzhiyun 		"aw883xx monitor_flag=%u\n",
1112*4882a593Smuzhiyun 		aw_dev->monitor_desc.monitor_cfg.monitor_switch);
1113*4882a593Smuzhiyun 	return len;
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun 
aw_monitor_update_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1116*4882a593Smuzhiyun static ssize_t aw_monitor_update_store(struct device *dev,
1117*4882a593Smuzhiyun 	struct device_attribute *attr, const char *buf, size_t count)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun 	struct aw883xx *aw883xx = dev_get_drvdata(dev);
1120*4882a593Smuzhiyun 	struct aw_device *aw_dev = aw883xx->aw_pa;
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun 	uint32_t update = 0;
1123*4882a593Smuzhiyun 	int ret = -1;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun 	if (count == 0)
1126*4882a593Smuzhiyun 		return 0;
1127*4882a593Smuzhiyun 
1128*4882a593Smuzhiyun 	ret = kstrtouint(buf, 0, &update);
1129*4882a593Smuzhiyun 	if (ret < 0)
1130*4882a593Smuzhiyun 		return ret;
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "monitor update = %d", update);
1133*4882a593Smuzhiyun 
1134*4882a593Smuzhiyun 	if (update) {
1135*4882a593Smuzhiyun 		aw_monitor_stop(&aw_dev->monitor_desc);
1136*4882a593Smuzhiyun 		aw_monitor_free_firmware(aw_dev);
1137*4882a593Smuzhiyun 		ret = aw_monitor_real_time_update_monitor(aw_dev);
1138*4882a593Smuzhiyun 		if (ret < 0)
1139*4882a593Smuzhiyun 			return ret;
1140*4882a593Smuzhiyun 		aw_monitor_start(&aw_dev->monitor_desc);
1141*4882a593Smuzhiyun 	}
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 	return count;
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun static DEVICE_ATTR(monitor, S_IWUSR | S_IRUGO,
1147*4882a593Smuzhiyun 	aw_monitor_show, aw_monitor_store);
1148*4882a593Smuzhiyun static DEVICE_ATTR(monitor_update, S_IWUSR,
1149*4882a593Smuzhiyun 	NULL, aw_monitor_update_store);
1150*4882a593Smuzhiyun 
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun static struct attribute *aw_monitor_attr[] = {
1153*4882a593Smuzhiyun 	&dev_attr_monitor.attr,
1154*4882a593Smuzhiyun 	&dev_attr_monitor_update.attr,
1155*4882a593Smuzhiyun #ifdef AW_DEBUG
1156*4882a593Smuzhiyun 	&dev_attr_vol.attr,
1157*4882a593Smuzhiyun 	&dev_attr_temp.attr,
1158*4882a593Smuzhiyun #endif
1159*4882a593Smuzhiyun 	NULL
1160*4882a593Smuzhiyun };
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun static struct attribute_group aw_monitor_attr_group = {
1163*4882a593Smuzhiyun 	.attrs = aw_monitor_attr,
1164*4882a593Smuzhiyun };
1165*4882a593Smuzhiyun 
aw_monitor_parse_dt(struct aw_device * aw_dev)1166*4882a593Smuzhiyun static void aw_monitor_parse_dt(struct aw_device *aw_dev)
1167*4882a593Smuzhiyun {
1168*4882a593Smuzhiyun 	int ret = -1;
1169*4882a593Smuzhiyun 	uint32_t monitor_delay;
1170*4882a593Smuzhiyun 	struct device_node *np = aw_dev->dev->of_node;
1171*4882a593Smuzhiyun 
1172*4882a593Smuzhiyun 	ret = of_property_read_u32(np, "hw-monitor-delay", &monitor_delay);
1173*4882a593Smuzhiyun 	if (ret < 0) {
1174*4882a593Smuzhiyun 		aw_dev_info(aw_dev->dev,
1175*4882a593Smuzhiyun 			"read hw-monitor-delay failed, set deafult value:[%d]ms",
1176*4882a593Smuzhiyun 			aw_dev->monitor_desc.hw_monitor_delay);
1177*4882a593Smuzhiyun 	} else {
1178*4882a593Smuzhiyun 		aw_dev_info(aw_dev->dev,
1179*4882a593Smuzhiyun 			"parse hw-monitor-delay:[%d]", monitor_delay);
1180*4882a593Smuzhiyun 		aw_dev->monitor_desc.hw_monitor_delay = monitor_delay;
1181*4882a593Smuzhiyun 	}
1182*4882a593Smuzhiyun }
1183*4882a593Smuzhiyun 
aw_monitor_init(struct aw_monitor_desc * monitor_desc)1184*4882a593Smuzhiyun void aw_monitor_init(struct aw_monitor_desc *monitor_desc)
1185*4882a593Smuzhiyun {
1186*4882a593Smuzhiyun 	int ret;
1187*4882a593Smuzhiyun 	struct aw_device *aw_dev = container_of(monitor_desc,
1188*4882a593Smuzhiyun 				struct aw_device, monitor_desc);
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun 	aw_dev_info(aw_dev->dev, "enter");
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun 	aw_monitor_parse_dt(aw_dev);
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun #ifdef AW_DEBUG
1195*4882a593Smuzhiyun 	monitor_desc->test_vol = 0;
1196*4882a593Smuzhiyun 	monitor_desc->test_temp = 0;
1197*4882a593Smuzhiyun #endif
1198*4882a593Smuzhiyun 
1199*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&monitor_desc->delay_work, aw_monitor_work_func);
1200*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&monitor_desc->hw_monitor_work, aw_hw_monitor_work_func);
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun 	ret = sysfs_create_group(&aw_dev->dev->kobj,
1203*4882a593Smuzhiyun 				&aw_monitor_attr_group);
1204*4882a593Smuzhiyun 	if (ret < 0)
1205*4882a593Smuzhiyun 		aw_dev_err(aw_dev->dev, "error creating sysfs attr files");
1206*4882a593Smuzhiyun }
1207*4882a593Smuzhiyun 
aw_monitor_deinit(struct aw_monitor_desc * monitor_desc)1208*4882a593Smuzhiyun void aw_monitor_deinit(struct aw_monitor_desc *monitor_desc)
1209*4882a593Smuzhiyun {
1210*4882a593Smuzhiyun 	struct aw_device *aw_dev =
1211*4882a593Smuzhiyun 		container_of(monitor_desc, struct aw_device, monitor_desc);
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun 	aw_monitor_stop(monitor_desc);
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun 	sysfs_remove_group(&aw_dev->dev->kobj, &aw_monitor_attr_group);
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun 
1218