xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/cyttsp5/cyttsp5_device_access.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * cyttsp5_device_access.c
3  * Parade TrueTouch(TM) Standard Product V5 Device Access Module.
4  * Configuration and Test command/status user interface.
5  * For use with Parade touchscreen controllers.
6  * Supported parts include:
7  * CYTMA5XX
8  * CYTMA448
9  * CYTMA445A
10  * CYTT21XXX
11  * CYTT31XXX
12  *
13  * Copyright (C) 2015 Parade Technologies
14  * Copyright (C) 2012-2015 Cypress Semiconductor
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * version 2, and only version 2, as published by the
19  * Free Software Foundation.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
27  *
28  */
29 
30 #include "cyttsp5_regs.h"
31 #include <linux/firmware.h>
32 
33 #include <linux/timer.h>
34 #include <linux/timex.h>
35 #include <linux/rtc.h>
36 
37 #define CY_CMCP_THRESHOLD_FILE_NAME "cyttsp5_thresholdfile.csv"
38 #define CMCP_THRESHOLD_FILE_NAME "ttdl_cmcp_thresholdfile.csv"
39 
40 /* Max test case number */
41 #define MAX_CASE_NUM            (22)
42 
43 /* ASCII */
44 #define ASCII_LF                (0x0A)
45 #define ASCII_CR                (0x0D)
46 #define ASCII_COMMA             (0x2C)
47 #define ASCII_ZERO              (0x30)
48 #define ASCII_NINE              (0x39)
49 
50 /* Max characters of test case name */
51 #define NAME_SIZE_MAX           (50)
52 
53 /* Max sensor and button number */
54 #define MAX_BUTTONS             (HID_SYSINFO_MAX_BTN)
55 #define MAX_SENSORS             (1024)
56 #define MAX_TX_SENSORS          (128)
57 #define MAX_RX_SENSORS          (128)
58 
59 /* Multiply by 2 for double (min, max) values */
60 #define TABLE_BUTTON_MAX_SIZE   (MAX_BUTTONS * 2)
61 #define TABLE_SENSOR_MAX_SIZE   (MAX_SENSORS * 2)
62 #define TABLE_TX_MAX_SIZE       (MAX_TX_SENSORS*2)
63 #define TABLE_RX_MAX_SIZE       (MAX_RX_SENSORS*2)
64 
65 #define CM_PANEL_DATA_OFFSET    (6)
66 #define CM_BTN_DATA_OFFSET      (6)
67 #define CP_PANEL_DATA_OFFSET    (6)
68 #define CP_BTN_DATA_OFFSET      (6)
69 #define MAX_BUF_LEN             (50000)
70 
71 /* cmcp csv file information */
72 struct configuration {
73 	u32 cm_range_limit_row;
74 	u32 cm_range_limit_col;
75 	u32 cm_min_limit_cal;
76 	u32 cm_max_limit_cal;
77 	u32 cm_max_delta_sensor_percent;
78 	u32 cm_max_delta_button_percent;
79 	u32 min_sensor_rx;
80 	u32 max_sensor_rx;
81 	u32 min_sensor_tx;
82 	u32 max_sensor_tx;
83 	u32 min_button;
84 	u32 max_button;
85 	u32 max_delta_sensor;
86 	u32 cp_max_delta_sensor_rx_percent;
87 	u32 cp_max_delta_sensor_tx_percent;
88 	u32 cm_min_max_table_button[TABLE_BUTTON_MAX_SIZE];
89 	u32 cp_min_max_table_button[TABLE_BUTTON_MAX_SIZE];
90 	u32 cm_min_max_table_sensor[TABLE_SENSOR_MAX_SIZE];
91 	u32 cp_min_max_table_rx[TABLE_RX_MAX_SIZE];
92 	u32 cp_min_max_table_tx[TABLE_TX_MAX_SIZE];
93 	u32 cm_min_max_table_button_size;
94 	u32 cp_min_max_table_button_size;
95 	u32 cm_min_max_table_sensor_size;
96 	u32 cp_min_max_table_rx_size;
97 	u32 cp_min_max_table_tx_size;
98 	u32 cp_max_delta_button_percent;
99 	u32 cm_max_table_gradient_cols_percent[TABLE_TX_MAX_SIZE];
100 	u32 cm_max_table_gradient_cols_percent_size;
101 	u32 cm_max_table_gradient_rows_percent[TABLE_RX_MAX_SIZE];
102 	u32 cm_max_table_gradient_rows_percent_size;
103 	u32 cm_excluding_row_edge;
104 	u32 cm_excluding_col_edge;
105 	u32 rx_num;
106 	u32 tx_num;
107 	u32 btn_num;
108 	u32 cm_enabled;
109 	u32 cp_enabled;
110 	u32 is_valid_or_not;
111 };
112 
113 /* Test case search definition */
114 struct test_case_search {
115 	char name[NAME_SIZE_MAX]; /* Test case name */
116 	u32 name_size;            /* Test case name size */
117 	u32 offset;               /* Test case offset */
118 };
119 
120 /* Test case field definition */
121 struct test_case_field {
122 	char *name;     /* Test case name */
123 	u32 name_size;  /* Test case name size */
124 	u32 type;       /* Test case type */
125 	u32 *bufptr;    /* Buffer to store value information */
126 	u32 exist_or_not;/* Test case exist or not */
127 	u32 data_num;   /* Buffer data number */
128 	u32 line_num;   /* Buffer line number */
129 };
130 
131 /* Test case type */
132 enum test_case_type {
133 	TEST_CASE_TYPE_NO,
134 	TEST_CASE_TYPE_ONE,
135 	TEST_CASE_TYPE_MUL,
136 	TEST_CASE_TYPE_MUL_LINES,
137 };
138 
139 /* Test case order in test_case_field_array */
140 enum case_order {
141 	CM_TEST_INPUTS,
142 	CM_EXCLUDING_COL_EDGE,
143 	CM_EXCLUDING_ROW_EDGE,
144 	CM_GRADIENT_CHECK_COL,
145 	CM_GRADIENT_CHECK_ROW,
146 	CM_RANGE_LIMIT_ROW,
147 	CM_RANGE_LIMIT_COL,
148 	CM_MIN_LIMIT_CAL,
149 	CM_MAX_LIMIT_CAL,
150 	CM_MAX_DELTA_SENSOR_PERCENT,
151 	CM_MAX_DELTA_BUTTON_PERCENT,
152 	PER_ELEMENT_MIN_MAX_TABLE_BUTTON,
153 	PER_ELEMENT_MIN_MAX_TABLE_SENSOR,
154 	CP_TEST_INPUTS,
155 	CP_MAX_DELTA_SENSOR_RX_PERCENT,
156 	CP_MAX_DELTA_SENSOR_TX_PERCENT,
157 	CP_MAX_DELTA_BUTTON_PERCENT,
158 	CP_PER_ELEMENT_MIN_MAX_BUTTON,
159 	MIN_BUTTON,
160 	MAX_BUTTON,
161 	PER_ELEMENT_MIN_MAX_RX,
162 	PER_ELEMENT_MIN_MAX_TX,
163 	CASE_ORDER_MAX,
164 };
165 
166 enum cmcp_test_item {
167 	CMCP_FULL = 0,
168 	CMCP_CM_PANEL,
169 	CMCP_CP_PANEL,
170 	CMCP_CM_BTN,
171 	CMCP_CP_BTN,
172 };
173 
174 #define CM_ENABLED 0x10
175 #define CP_ENABLED 0x20
176 #define CM_PANEL (0x01 | CM_ENABLED)
177 #define CP_PANEL (0x02 | CP_ENABLED)
178 #define CM_BTN (0x04 | CM_ENABLED)
179 #define CP_BTN (0x08 | CP_ENABLED)
180 #define CMCP_FULL_CASE\
181 	(CM_PANEL | CP_PANEL | CM_BTN | CP_BTN | CM_ENABLED | CP_ENABLED)
182 
183 #define CYTTSP5_DEVICE_ACCESS_NAME "cyttsp5_device_access"
184 #define CYTTSP5_INPUT_ELEM_SZ (sizeof("0xHH") + 1)
185 
186 #define STATUS_SUCCESS	0
187 #define STATUS_FAIL	-1
188 #define PIP_CMD_MAX_LENGTH ((1 << 16) - 1)
189 
190 #ifdef TTHE_TUNER_SUPPORT
191 struct heatmap_param {
192 	bool scan_start;
193 	enum scan_data_type_list data_type; /* raw, base, diff */
194 	int num_element;
195 };
196 #endif
197 #define ABS(x)			(((x) < 0) ? -(x) : (x))
198 
199 #define CY_MAX_CONFIG_BYTES    256
200 #define CYTTSP5_TTHE_TUNER_GET_PANEL_DATA_FILE_NAME "get_panel_data"
201 #define TTHE_TUNER_MAX_BUF	(CY_MAX_PRBUF_SIZE * 3)
202 
203 struct cyttsp5_device_access_data {
204 	struct device *dev;
205 	struct cyttsp5_sysinfo *si;
206 	struct mutex sysfs_lock;
207 	u8 status;
208 	u16 response_length;
209 	bool sysfs_nodes_created;
210 	struct kobject mfg_test;
211 	u8 panel_scan_data_id;
212 	u8 get_idac_data_id;
213 	u8 calibrate_sensing_mode;
214 	u8 calibrate_initialize_baselines;
215 	u8 baseline_sensing_mode;
216 #ifdef TTHE_TUNER_SUPPORT
217 	struct heatmap_param heatmap;
218 	struct dentry *tthe_get_panel_data_debugfs;
219 	struct mutex debugfs_lock;
220 	u8 tthe_get_panel_data_buf[TTHE_TUNER_MAX_BUF];
221 	u8 tthe_get_panel_data_is_open;
222 #endif
223 	struct dentry *cmcp_results_debugfs;
224 
225 	struct dentry *base_dentry;
226 	struct dentry *mfg_test_dentry;
227 	u8 ic_buf[CY_MAX_PRBUF_SIZE];
228 	u8 response_buf[CY_MAX_PRBUF_SIZE];
229 	struct mutex cmcp_threshold_lock;
230 	u8 *cmcp_threshold_data;
231 	int cmcp_threshold_size;
232 	bool cmcp_threshold_loading;
233 	struct work_struct cmcp_threshold_update;
234 	struct completion builtin_cmcp_threshold_complete;
235 	int builtin_cmcp_threshold_status;
236 	bool is_manual_upgrade_enabled;
237 	struct configuration *configs;
238 	struct cmcp_data *cmcp_info;
239 	struct result *result;
240 	struct test_case_search *test_search_array;
241 	struct test_case_field *test_field_array;
242 	int cmcp_test_items;
243 	int test_executed;
244 	int cmcp_range_check;
245 	int cmcp_force_calibrate;
246 	int cmcp_test_in_progress;
247 };
248 
249 struct cmcp_data {
250 	struct gd_sensor *gd_sensor_col;
251 	struct gd_sensor *gd_sensor_row;
252 	int32_t *cm_data_panel;
253 	int32_t *cp_tx_data_panel;
254 	int32_t *cp_rx_data_panel;
255 	int32_t *cp_tx_cal_data_panel;
256 	int32_t *cp_rx_cal_data_panel;
257 	int32_t cp_sensor_rx_delta;
258 	int32_t cp_sensor_tx_delta;
259 	int32_t cp_button_delta;
260 	int32_t *cm_btn_data;
261 	int32_t *cp_btn_data;
262 	int32_t *cm_sensor_column_delta;
263 	int32_t *cm_sensor_row_delta;
264 	int32_t cp_btn_cal;
265 	int32_t cm_btn_cal;
266 	int32_t cp_button_ave;
267 	int32_t cm_ave_data_panel;
268 	int32_t cp_tx_ave_data_panel;
269 	int32_t cp_rx_ave_data_panel;
270 	int32_t cm_cal_data_panel;
271 	int32_t cm_ave_data_btn;
272 	int32_t cm_cal_data_btn;
273 	int32_t cm_delta_data_btn;
274 	int32_t cm_sensor_delta;
275 
276 	int32_t tx_num;
277 	int32_t rx_num;
278 	int32_t btn_num;
279 };
280 
281 struct result {
282 	int32_t sensor_assignment;
283 	int32_t config_ver;
284 	int32_t revision_ctrl;
285 	int32_t device_id_high;
286 	int32_t device_id_low;
287 	bool cm_test_run;
288 	bool cp_test_run;
289 	/* Sensor Cm validation */
290 	bool cm_test_pass;
291 	bool cm_sensor_validation_pass;
292 	bool cm_sensor_row_delta_pass;
293 	bool cm_sensor_col_delta_pass;
294 	bool cm_sensor_gd_row_pass;
295 	bool cm_sensor_gd_col_pass;
296 	bool cm_sensor_calibration_pass;
297 	bool cm_sensor_delta_pass;
298 	bool cm_button_validation_pass;
299 	bool cm_button_delta_pass;
300 
301 	int32_t *cm_sensor_raw_data;
302 	int32_t cm_sensor_calibration;
303 	int32_t cm_sensor_delta;
304 	int32_t *cm_button_raw_data;
305 	int32_t cm_button_delta;
306 
307 	/* Sensor Cp validation */
308 	bool cp_test_pass;
309 	bool cp_sensor_delta_pass;
310 	bool cp_sensor_rx_delta_pass;
311 	bool cp_sensor_tx_delta_pass;
312 	bool cp_sensor_average_pass;
313 	bool cp_button_delta_pass;
314 	bool cp_button_average_pass;
315 	bool cp_rx_validation_pass;
316 	bool cp_tx_validation_pass;
317 	bool cp_button_validation_pass;
318 
319 	int32_t *cp_sensor_rx_raw_data;
320 	int32_t *cp_sensor_tx_raw_data;
321 	int32_t cp_sensor_rx_delta;
322 	int32_t cp_sensor_tx_delta;
323 	int32_t cp_sensor_rx_calibration;
324 	int32_t cp_sensor_tx_calibration;
325 	int32_t *cp_button_raw_data;
326 	int32_t cp_button_delta;
327 
328 	/*other validation*/
329 	bool short_test_pass;
330 	bool test_summary;
331 	uint8_t *cm_open_pwc;
332 };
333 
334 static struct cyttsp5_core_commands *cmd;
335 
336 static struct cyttsp5_module device_access_module;
337 
338 static ssize_t cyttsp5_run_and_get_selftest_result_noprint(struct device *dev,
339 		char *buf, size_t buf_len, u8 test_id, u16 read_length,
340 		bool get_result_on_pass);
341 
342 static int _cyttsp5_calibrate_idacs_cmd(struct device *dev,
343 		u8 sensing_mode, u8 *status);
344 
cyttsp5_get_device_access_data(struct device * dev)345 static inline struct cyttsp5_device_access_data *cyttsp5_get_device_access_data(
346 		struct device *dev)
347 {
348 	return cyttsp5_get_module_data(dev, &device_access_module);
349 }
350 
cyttsp5_status_show(struct device * dev,struct device_attribute * attr,char * buf)351 static ssize_t cyttsp5_status_show(struct device *dev,
352 		struct device_attribute *attr, char *buf)
353 {
354 	struct cyttsp5_device_access_data *dad
355 		= cyttsp5_get_device_access_data(dev);
356 	u8 val;
357 
358 	mutex_lock(&dad->sysfs_lock);
359 	val = dad->status;
360 	mutex_unlock(&dad->sysfs_lock);
361 
362 	return scnprintf(buf, CY_MAX_PRBUF_SIZE, "%d\n", val);
363 }
364 
365 static DEVICE_ATTR(status, S_IRUSR, cyttsp5_status_show, NULL);
366 
cyttsp5_response_show(struct device * dev,struct device_attribute * attr,char * buf)367 static ssize_t cyttsp5_response_show(struct device *dev,
368 		struct device_attribute *attr, char *buf)
369 {
370 	struct cyttsp5_device_access_data *dad
371 		= cyttsp5_get_device_access_data(dev);
372 	int i;
373 	ssize_t num_read;
374 	int index;
375 
376 	mutex_lock(&dad->sysfs_lock);
377 	index = scnprintf(buf, CY_MAX_PRBUF_SIZE,
378 			"Status %d\n", dad->status);
379 	if (!dad->status)
380 		goto error;
381 
382 	num_read = dad->response_length;
383 
384 	for (i = 0; i < num_read; i++)
385 		index += scnprintf(buf + index, CY_MAX_PRBUF_SIZE - index,
386 				"0x%02X\n", dad->response_buf[i]);
387 
388 	index += scnprintf(buf + index, CY_MAX_PRBUF_SIZE - index,
389 			"(%zd bytes)\n", num_read);
390 
391 error:
392 	mutex_unlock(&dad->sysfs_lock);
393 	return index;
394 }
395 
396 static DEVICE_ATTR(response, S_IRUSR, cyttsp5_response_show, NULL);
397 
398 /*
399  * Gets user input from sysfs and parse it
400  * return size of parsed output buffer
401  */
cyttsp5_ic_parse_input(struct device * dev,const char * buf,size_t buf_size,u8 * ic_buf,size_t ic_buf_size)402 static int cyttsp5_ic_parse_input(struct device *dev, const char *buf,
403 		size_t buf_size, u8 *ic_buf, size_t ic_buf_size)
404 {
405 	const char *pbuf = buf;
406 	unsigned long value;
407 	char scan_buf[CYTTSP5_INPUT_ELEM_SZ];
408 	u32 i = 0;
409 	u32 j;
410 	int last = 0;
411 	int ret;
412 
413 	parade_debug(dev, DEBUG_LEVEL_1,
414 		"%s: pbuf=%p buf=%p size=%zu %s=%zu buf=%s\n",
415 		__func__, pbuf, buf, buf_size, "scan buf size",
416 		CYTTSP5_INPUT_ELEM_SZ, buf);
417 
418 	while (pbuf <= (buf + buf_size)) {
419 		if (i >= CY_MAX_CONFIG_BYTES) {
420 			dev_err(dev, "%s: %s size=%d max=%d\n", __func__,
421 					"Max cmd size exceeded", i,
422 					CY_MAX_CONFIG_BYTES);
423 			return -EINVAL;
424 		}
425 		if (i >= ic_buf_size) {
426 			dev_err(dev, "%s: %s size=%d buf_size=%zu\n", __func__,
427 					"Buffer size exceeded", i, ic_buf_size);
428 			return -EINVAL;
429 		}
430 		while (((*pbuf == ' ') || (*pbuf == ','))
431 				&& (pbuf < (buf + buf_size))) {
432 			last = *pbuf;
433 			pbuf++;
434 		}
435 
436 		if (pbuf >= (buf + buf_size))
437 			break;
438 
439 		memset(scan_buf, 0, CYTTSP5_INPUT_ELEM_SZ);
440 		if ((last == ',') && (*pbuf == ',')) {
441 			dev_err(dev, "%s: %s \",,\" not allowed.\n", __func__,
442 					"Invalid data format.");
443 			return -EINVAL;
444 		}
445 		for (j = 0; j < (CYTTSP5_INPUT_ELEM_SZ - 1)
446 				&& (pbuf < (buf + buf_size))
447 				&& (*pbuf != ' ')
448 				&& (*pbuf != ','); j++) {
449 			last = *pbuf;
450 			scan_buf[j] = *pbuf++;
451 		}
452 
453 		ret = kstrtoul(scan_buf, 16, &value);
454 		if (ret < 0) {
455 			dev_err(dev, "%s: %s '%s' %s%s i=%d r=%d\n", __func__,
456 					"Invalid data format. ", scan_buf,
457 					"Use \"0xHH,...,0xHH\"", " instead.",
458 					i, ret);
459 			return ret;
460 		}
461 
462 		ic_buf[i] = value;
463 		i++;
464 	}
465 
466 	return i;
467 }
468 
cyttsp5_command_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)469 static ssize_t cyttsp5_command_store(struct device *dev,
470 		struct device_attribute *attr, const char *buf, size_t size)
471 {
472 	struct cyttsp5_device_access_data *dad
473 		= cyttsp5_get_device_access_data(dev);
474 	ssize_t length;
475 	int rc;
476 
477 	mutex_lock(&dad->sysfs_lock);
478 	dad->status = 0;
479 	dad->response_length = 0;
480 	length = cyttsp5_ic_parse_input(dev, buf, size, dad->ic_buf,
481 			CY_MAX_PRBUF_SIZE);
482 	if (length <= 0) {
483 		dev_err(dev, "%s: %s Group Data store\n", __func__,
484 				"Malformed input for");
485 		goto exit;
486 	}
487 
488 	/* write ic_buf to log */
489 	cyttsp5_pr_buf(dev, dad->ic_buf, length, "ic_buf");
490 
491 	pm_runtime_get_sync(dev);
492 	rc = cmd->nonhid_cmd->user_cmd(dev, 1, CY_MAX_PRBUF_SIZE,
493 			dad->response_buf, length, dad->ic_buf,
494 			&dad->response_length);
495 	pm_runtime_put(dev);
496 	if (rc) {
497 		dad->response_length = 0;
498 		dev_err(dev, "%s: Failed to store command\n", __func__);
499 	} else {
500 		dad->status = 1;
501 	}
502 
503 exit:
504 	mutex_unlock(&dad->sysfs_lock);
505 	parade_debug(dev, DEBUG_LEVEL_2, "%s: return size=%zu\n",
506 		__func__, size);
507 	return size;
508 }
509 
510 static DEVICE_ATTR(command, S_IWUSR, NULL, cyttsp5_command_store);
511 
cmcp_check_config_fw_match(struct device * dev,struct configuration * configuration)512 static int cmcp_check_config_fw_match(struct device *dev,
513 	struct configuration *configuration)
514 {
515 	struct cyttsp5_device_access_data *dad
516 		= cyttsp5_get_device_access_data(dev);
517 	int32_t tx_num = dad->configs->tx_num;
518 	int32_t rx_num = dad->configs->rx_num;
519 	int32_t button_num = dad->configs->btn_num;
520 	int ret = 0;
521 
522 	if (tx_num != dad->si->sensing_conf_data.tx_num) {
523 		dev_err(dev, "%s: TX number mismatch!\n", __func__);
524 		ret = -EINVAL;
525 	}
526 
527 	if (rx_num != dad->si->sensing_conf_data.rx_num) {
528 		dev_err(dev, "%s: RX number mismatch!\n", __func__);
529 		ret = -EINVAL;
530 	}
531 
532 	if (button_num != dad->si->num_btns) {
533 		dev_err(dev, "%s: Button number mismatch!\n", __func__);
534 		ret = -EINVAL;
535 	}
536 
537 	return ret;
538 }
539 
validate_cm_test_results(struct device * dev,struct configuration * configuration,struct cmcp_data * cmcp_info,struct result * result,bool * pass,int test_item)540 static int validate_cm_test_results(struct device *dev,
541 	struct configuration *configuration, struct cmcp_data *cmcp_info,
542 	struct result *result, bool *pass, int test_item)
543 {
544 	int32_t tx_num = cmcp_info->tx_num;
545 	int32_t rx_num = cmcp_info->rx_num;
546 	int32_t button_num =  cmcp_info->btn_num;
547 	uint32_t sensor_num = tx_num * rx_num;
548 	int32_t *cm_sensor_data = cmcp_info->cm_data_panel;
549 	int32_t cm_button_delta;
550 	int32_t cm_sensor_calibration;
551 	int32_t *cm_button_data = cmcp_info->cm_btn_data;
552 	struct gd_sensor *gd_sensor_col = cmcp_info->gd_sensor_col;
553 	struct gd_sensor *gd_sensor_row = cmcp_info->gd_sensor_row;
554 	int32_t *cm_sensor_column_delta = cmcp_info->cm_sensor_column_delta;
555 	int32_t *cm_sensor_row_delta = cmcp_info->cm_sensor_row_delta;
556 	int ret = 0;
557 	int i, j;
558 
559 	parade_debug(dev, DEBUG_LEVEL_2, "%s: start\n", __func__);
560 
561 	if ((test_item & CM_PANEL) == CM_PANEL) {
562 		parade_debug(dev, DEBUG_LEVEL_2, "Check each sensor Cm data for min max value\n ");
563 
564 		/* Check each sensor Cm data for min/max values */
565 		result->cm_sensor_validation_pass = true;
566 
567 	for (i = 0; i < sensor_num; i++) {
568 		int row = i % rx_num;
569 		int col = i / rx_num;
570 		int32_t cm_sensor_min =
571 		configuration->cm_min_max_table_sensor[(row*tx_num+col)*2];
572 		int32_t cm_sensor_max =
573 		configuration->cm_min_max_table_sensor[(row*tx_num+col)*2+1];
574 		if ((cm_sensor_data[i] < cm_sensor_min)
575 		|| (cm_sensor_data[i] > cm_sensor_max)) {
576 			dev_err(dev, "%s: Sensor[%d,%d]:%d (%d,%d)\n",
577 					"Cm sensor min/max test",
578 					row, col,
579 					cm_sensor_data[i],
580 					cm_sensor_min, cm_sensor_max);
581 			result->cm_sensor_validation_pass = false;
582 		}
583 	}
584 
585 	/*check cm gradient column data*/
586 	result->cm_sensor_gd_col_pass = true;
587 	for (i = 0;
588 	i < configuration->cm_max_table_gradient_cols_percent_size;
589 	i++) {
590 		if ((gd_sensor_col + i)->gradient_val >
591 		10 * configuration->cm_max_table_gradient_cols_percent[i]){
592 			dev_err(dev,
593 		"%s: cm_max_table_gradient_cols_percent[%d]:%d, gradient_val:%d\n",
594 		__func__,
595 		i,
596 		configuration->cm_max_table_gradient_cols_percent[i],
597 		(gd_sensor_col + i)->gradient_val);
598 			result->cm_sensor_gd_col_pass = false;
599 		}
600 	}
601 
602 	/*check cm gradient row data*/
603 	result->cm_sensor_gd_row_pass = true;
604 	for (j = 0;
605 	j < configuration->cm_max_table_gradient_rows_percent_size;
606 	j++) {
607 		if ((gd_sensor_row + j)->gradient_val >
608 		10 * configuration->cm_max_table_gradient_rows_percent[j]) {
609 			dev_err(dev,
610 		"%s: cm_max_table_gradient_rows_percent[%d]:%d, gradient_val:%d\n",
611 		__func__,
612 		j, configuration->cm_max_table_gradient_rows_percent[j],
613 		(gd_sensor_row + j)->gradient_val);
614 			result->cm_sensor_gd_row_pass = false;
615 		}
616 	}
617 
618 	result->cm_sensor_row_delta_pass = true;
619 	result->cm_sensor_col_delta_pass = true;
620 	result->cm_sensor_calibration_pass = true;
621 	result->cm_sensor_delta_pass = true;
622 
623 
624 	/*
625 	 * Check each row Cm data
626 	 * with neighbor for difference
627 	 */
628 	for (i = 0; i < tx_num; i++) {
629 		for (j = 1; j < rx_num; j++) {
630 			int32_t cm_sensor_row_diff =
631 			ABS(cm_sensor_data[i * rx_num + j] -
632 			cm_sensor_data[i * rx_num + j - 1]);
633 		cm_sensor_row_delta[i * rx_num + j - 1] =
634 			cm_sensor_row_diff;
635 			if (cm_sensor_row_diff
636 			> configuration->cm_range_limit_row) {
637 				dev_err(dev,
638 				"%s: Sensor[%d,%d]:%d (%d)\n",
639 				"Cm sensor row range limit test",
640 				j, i,
641 				cm_sensor_row_diff,
642 			configuration->cm_range_limit_row);
643 		result->cm_sensor_row_delta_pass = false;
644 			}
645 		}
646 	}
647 
648 	/*
649 	 * Check each column Cm data
650 	 * with neighbor for difference
651 	 */
652 	for (i = 1; i < tx_num; i++) {
653 		for (j = 0; j < rx_num; j++) {
654 			int32_t cm_sensor_col_diff =
655 		ABS((int)cm_sensor_data[i * rx_num + j] -
656 		(int)cm_sensor_data[(i - 1) * rx_num + j]);
657 		cm_sensor_column_delta[(i - 1) * rx_num + j] =
658 			cm_sensor_col_diff;
659 		if (cm_sensor_col_diff >
660 			configuration->cm_range_limit_col) {
661 			dev_err(dev,
662 			"%s: Sensor[%d,%d]:%d (%d)\n",
663 			"Cm sensor column range limit test",
664 			j, i,
665 			cm_sensor_col_diff,
666 			configuration->cm_range_limit_col);
667 		result->cm_sensor_col_delta_pass = false;
668 			}
669 		}
670 	}
671 
672 	/* Check sensor calculated Cm for min/max values */
673 	cm_sensor_calibration = cmcp_info->cm_cal_data_panel;
674 	if (cm_sensor_calibration <
675 		configuration->cm_min_limit_cal
676 		|| cm_sensor_calibration >
677 		configuration->cm_max_limit_cal) {
678 		dev_err(dev, "%s: Cm_cal:%d (%d,%d)\n",
679 			"Cm sensor Cm_cal min/max test",
680 			cm_sensor_calibration,
681 			configuration->cm_min_limit_cal,
682 			configuration->cm_max_limit_cal);
683 		result->cm_sensor_calibration_pass = false;
684 	}
685 
686 	/* Check sensor Cm delta for range limit */
687 	if (cmcp_info->cm_sensor_delta
688 		 > 10 * configuration->cm_max_delta_sensor_percent) {
689 		dev_err(dev,
690 			"%s: Cm_sensor_delta:%d (%d)\n",
691 			"Cm sensor delta range limit test",
692 			cmcp_info->cm_sensor_delta,
693 		configuration->cm_max_delta_sensor_percent);
694 		result->cm_sensor_delta_pass = false;
695 	}
696 
697 	result->cm_test_pass = result->cm_sensor_gd_col_pass
698 			&& result->cm_sensor_gd_row_pass
699 			&& result->cm_sensor_validation_pass
700 			&& result->cm_sensor_row_delta_pass
701 			&& result->cm_sensor_col_delta_pass
702 			&& result->cm_sensor_calibration_pass
703 			&& result->cm_sensor_delta_pass;
704 	}
705 
706 	if (((test_item & CM_BTN) == CM_BTN) && (cmcp_info->btn_num)) {
707 		/* Check each button Cm data for min/max values */
708 		result->cm_button_validation_pass = true;
709 		for (i = 0; i < button_num; i++) {
710 			int32_t  cm_button_min =
711 			configuration->cm_min_max_table_button[i * 2];
712 			int32_t  cm_button_max =
713 			configuration->cm_min_max_table_button[i * 2 + 1];
714 			if ((cm_button_data[i] <= cm_button_min)
715 				|| (cm_button_data[i] >= cm_button_max)) {
716 				dev_err(dev,
717 					"%s: Button[%d]:%d (%d,%d)\n",
718 					"Cm button min/max test",
719 					i,
720 					cm_button_data[i],
721 					cm_button_min, cm_button_max);
722 				result->cm_button_validation_pass = false;
723 			}
724 		}
725 
726 		/* Check button Cm delta for range limit */
727 		result->cm_button_delta_pass = true;
728 
729 		cm_button_delta = ABS((cmcp_info->cm_ave_data_btn -
730 			cmcp_info->cm_cal_data_btn) * 100 /
731 			cmcp_info->cm_ave_data_btn);
732 		if (cm_button_delta >
733 		configuration->cm_max_delta_button_percent) {
734 			dev_err(dev,
735 				"%s: Cm_button_delta:%d (%d)\n",
736 				"Cm button delta range limit test",
737 				cm_button_delta,
738 			configuration->cm_max_delta_button_percent);
739 			result->cm_button_delta_pass = false;
740 		}
741 
742 		result->cm_test_pass = result->cm_test_pass
743 				&& result->cm_button_validation_pass
744 				&& result->cm_button_delta_pass;
745 	}
746 
747 	if (pass)
748 		*pass = result->cm_test_pass;
749 
750 	return ret;
751 }
validate_cp_test_results(struct device * dev,struct configuration * configuration,struct cmcp_data * cmcp_info,struct result * result,bool * pass,int test_item)752 static int validate_cp_test_results(struct device *dev,
753 	struct configuration *configuration, struct cmcp_data *cmcp_info,
754 	struct result *result, bool *pass, int test_item)
755 {
756 	int i = 0;
757 	uint32_t configuration_rx_num;
758 	uint32_t configuration_tx_num;
759 	int32_t *cp_sensor_tx_data = cmcp_info->cp_tx_data_panel;
760 	int32_t *cp_sensor_rx_data = cmcp_info->cp_rx_data_panel;
761 	int32_t cp_button_delta;
762 	int32_t cp_button_average;
763 
764 	result->cp_test_pass = true;
765 	configuration_rx_num = configuration->cp_min_max_table_rx_size/2;
766 	configuration_tx_num = configuration->cp_min_max_table_tx_size/2;
767 
768 	parade_debug(dev, DEBUG_LEVEL_2, "%s start\n", __func__);
769 
770 	if ((test_item & CP_PANEL) == CP_PANEL) {
771 		int32_t cp_sensor_tx_delta;
772 		int32_t cp_sensor_rx_delta;
773 
774 		/* Check Sensor Cp delta for range limit */
775 		result->cp_sensor_delta_pass = true;
776 		/*check cp_sensor_tx_delta */
777 		for (i = 0; i < configuration_tx_num; i++) {
778 			cp_sensor_tx_delta =
779 			ABS((cmcp_info->cp_tx_cal_data_panel[i]-
780 			cmcp_info->cp_tx_data_panel[i]) * 100 /
781 			cmcp_info->cp_tx_data_panel[i]);
782 
783 			if (cp_sensor_tx_delta >
784 			configuration->cp_max_delta_sensor_tx_percent) {
785 				dev_err(dev,
786 				"%s: Cp_sensor_tx_delta:%d (%d)\n",
787 				"Cp sensor delta range limit test",
788 				cp_sensor_tx_delta,
789 			configuration->cp_max_delta_sensor_tx_percent);
790 				result->cp_sensor_delta_pass = false;
791 			}
792 		}
793 
794 		/*check cp_sensor_rx_delta */
795 		for (i = 0; i < configuration_rx_num; i++) {
796 			cp_sensor_rx_delta =
797 			ABS((cmcp_info->cp_rx_cal_data_panel[i] -
798 			cmcp_info->cp_rx_data_panel[i]) * 100 /
799 			cmcp_info->cp_rx_data_panel[i]);
800 			if (cp_sensor_rx_delta >
801 			configuration->cp_max_delta_sensor_rx_percent) {
802 				dev_err(dev,
803 				"%s: Cp_sensor_rx_delta:%d(%d)\n",
804 				"Cp sensor delta range limit test",
805 				cp_sensor_rx_delta,
806 			configuration->cp_max_delta_sensor_rx_percent);
807 				result->cp_sensor_delta_pass = false;
808 			}
809 		}
810 
811 		/* Check sensor Cp rx for min/max values */
812 		result->cp_rx_validation_pass = true;
813 		for (i = 0; i < configuration_rx_num; i++) {
814 			int32_t cp_rx_min =
815 				configuration->cp_min_max_table_rx[i * 2];
816 			int32_t cp_rx_max =
817 				configuration->cp_min_max_table_rx[i * 2 + 1];
818 			if ((cp_sensor_rx_data[i] <= cp_rx_min)
819 				|| (cp_sensor_rx_data[i] >= cp_rx_max)) {
820 				dev_err(dev,
821 				"%s: Cp Rx[%d]:%d (%d,%d)\n",
822 				"Cp Rx min/max test",
823 				i,
824 				(int)cp_sensor_rx_data[i],
825 				cp_rx_min, cp_rx_max);
826 				result->cp_rx_validation_pass = false;
827 			}
828 		}
829 
830 		/* Check sensor Cp tx for min/max values */
831 		result->cp_tx_validation_pass = true;
832 		for (i = 0; i < configuration_tx_num; i++) {
833 			int32_t cp_tx_min =
834 				configuration->cp_min_max_table_tx[i * 2];
835 			int32_t cp_tx_max =
836 				configuration->cp_min_max_table_tx[i * 2 + 1];
837 			if ((cp_sensor_tx_data[i] <= cp_tx_min)
838 				|| (cp_sensor_tx_data[i] >= cp_tx_max)) {
839 				dev_err(dev,
840 				"%s: Cp Tx[%d]:%d(%d,%d)\n",
841 				"Cp Tx min/max test",
842 				i,
843 				cp_sensor_tx_data[i],
844 				cp_tx_min, cp_tx_max);
845 				result->cp_tx_validation_pass = false;
846 			}
847 		}
848 
849 		result->cp_test_pass = result->cp_test_pass
850 				&& result->cp_sensor_delta_pass
851 				&& result->cp_rx_validation_pass
852 				&& result->cp_tx_validation_pass;
853 	}
854 
855 	if (((test_item & CP_BTN) == CP_BTN) && (cmcp_info->btn_num)) {
856 		result->cp_button_delta_pass = true;
857 
858 		/* Check button Cp delta for range limit */
859 		cp_button_delta = ABS((cmcp_info->cp_btn_cal
860 		- cmcp_info->cp_button_ave) * 100 /
861 		cmcp_info->cp_button_ave);
862 		if (cp_button_delta >
863 		configuration->cp_max_delta_button_percent) {
864 			dev_err(dev,
865 			"%s: Cp_button_delta:%d (%d)\n",
866 			"Cp button delta range limit test",
867 			cp_button_delta,
868 			configuration->cp_max_delta_button_percent);
869 			result->cp_button_delta_pass = false;
870 		}
871 
872 		/* Check button Cp average for min/max values */
873 		result->cp_button_average_pass = true;
874 		cp_button_average = cmcp_info->cp_button_ave;
875 		if (cp_button_average < configuration->min_button
876 				|| cp_button_average >
877 					configuration->max_button) {
878 			dev_err(dev,
879 				"%s: Button Cp average fails min/max test\n",
880 				__func__);
881 			dev_err(dev,
882 				"%s: Cp_button_average:%d (%d,%d)\n",
883 				"Cp button average min/max test",
884 				cp_button_average,
885 				configuration->min_button,
886 				configuration->max_button);
887 			result->cp_button_average_pass = false;
888 		}
889 
890 		/* Check each button Cp data for min/max values */
891 		result->cp_button_validation_pass = true;
892 		for (i = 0; i < cmcp_info->btn_num; i++) {
893 			int32_t  cp_button_min =
894 			configuration->cp_min_max_table_button[i * 2];
895 			int32_t  cp_button_max =
896 			configuration->cp_min_max_table_button[i * 2 + 1];
897 			if ((cmcp_info->cp_btn_data[i] <= cp_button_min)
898 			|| (cmcp_info->cp_btn_data[i] >= cp_button_max)) {
899 				dev_err(dev,
900 					"%s: Button[%d]:%d (%d,%d)\n",
901 					"Cp button min/max test",
902 					i,
903 					cmcp_info->cp_btn_data[i],
904 					cp_button_min, cp_button_max);
905 				result->cp_button_validation_pass = false;
906 			}
907 		}
908 
909 		result->cp_test_pass = result->cp_test_pass
910 				&& result->cp_button_delta_pass
911 				&& result->cp_button_average_pass
912 				&& result->cp_button_validation_pass;
913 	}
914 
915 	if (pass)
916 		*pass = result->cp_test_pass;
917 
918 	return 0;
919 }
920 
calculate_gradient_row(struct gd_sensor * gd_sensor_row_head,uint16_t row_num,int exclude_row_edge,int exclude_col_edge)921 static void calculate_gradient_row(struct gd_sensor *gd_sensor_row_head,
922 		 uint16_t row_num, int exclude_row_edge, int exclude_col_edge)
923 {
924 	int i = 0;
925 	uint16_t cm_min_cur = 0;
926 	uint16_t cm_max_cur = 0;
927 	uint16_t cm_ave_cur = 0;
928 	uint16_t cm_ave_next = 0;
929 	uint16_t cm_ave_prev = 0;
930 	struct gd_sensor *p = gd_sensor_row_head;
931 
932 	if (exclude_row_edge) {
933 		for (i = 0; i < row_num; i++) {
934 			if (!exclude_col_edge) {
935 				cm_ave_cur = (p + i)->cm_ave;
936 				cm_min_cur = (p + i)->cm_min;
937 				cm_max_cur = (p + i)->cm_max;
938 				if (i < (row_num-1))
939 					cm_ave_next = (p + i+1)->cm_ave;
940 				if (i > 0)
941 					cm_ave_prev = (p + i-1)->cm_ave;
942 			} else {
943 				cm_ave_cur = (p + i)->cm_ave_exclude_edge;
944 				cm_min_cur = (p + i)->cm_min_exclude_edge;
945 				cm_max_cur = (p + i)->cm_max_exclude_edge;
946 				if (i < (row_num-1))
947 					cm_ave_next =
948 					(p + i+1)->cm_ave_exclude_edge;
949 				if (i > 0)
950 					cm_ave_prev =
951 					(p + i-1)->cm_ave_exclude_edge;
952 			}
953 
954 			if (cm_ave_cur == 0)
955 				cm_ave_cur = 1;
956 
957 			/*multiple 1000 to increate accuracy*/
958 			if ((i == 0) || (i == (row_num-1))) {
959 				(p + i)->gradient_val =
960 				(cm_max_cur - cm_min_cur) * 1000 /
961 				cm_ave_cur;
962 			} else if (i == 1) {
963 				(p + i)->gradient_val = (cm_max_cur - cm_min_cur
964 				+ ABS(cm_ave_cur - cm_ave_next)) * 1000 /
965 				cm_ave_cur;
966 			} else {
967 				(p + i)->gradient_val = (cm_max_cur - cm_min_cur
968 				+ ABS(cm_ave_cur - cm_ave_prev)) * 1000 /
969 				cm_ave_cur;
970 			}
971 		}
972 	} else if (!exclude_row_edge) {
973 		for (i = 0; i < row_num; i++) {
974 			if (!exclude_col_edge) {
975 				cm_ave_cur = (p + i)->cm_ave;
976 				cm_min_cur = (p + i)->cm_min;
977 				cm_max_cur = (p + i)->cm_max;
978 				if (i < (row_num-1))
979 					cm_ave_next = (p + i+1)->cm_ave;
980 				if (i > 0)
981 					cm_ave_prev = (p + i-1)->cm_ave;
982 			} else {
983 				cm_ave_cur = (p + i)->cm_ave_exclude_edge;
984 				cm_min_cur = (p + i)->cm_min_exclude_edge;
985 				cm_max_cur = (p + i)->cm_max_exclude_edge;
986 				if (i < (row_num-1))
987 					cm_ave_next =
988 					(p + i+1)->cm_ave_exclude_edge;
989 				if (i > 0)
990 					cm_ave_prev =
991 					(p + i-1)->cm_ave_exclude_edge;
992 			}
993 
994 			if (cm_ave_cur == 0)
995 				cm_ave_cur = 1;
996 			/*multiple 1000 to increate accuracy*/
997 			if (i <= 1)
998 				(p + i)->gradient_val = (cm_max_cur - cm_min_cur
999 				+ ABS(cm_ave_cur - cm_ave_next)) * 1000 /
1000 				cm_ave_cur;
1001 			else
1002 				(p + i)->gradient_val = (cm_max_cur - cm_min_cur
1003 				+ ABS(cm_ave_cur - cm_ave_prev)) * 1000 /
1004 				cm_ave_cur;
1005 		}
1006 	}
1007 }
1008 
calculate_gradient_col(struct gd_sensor * gd_sensor_row_head,uint16_t col_num,int exclude_row_edge,int exclude_col_edge)1009 static void calculate_gradient_col(struct gd_sensor *gd_sensor_row_head,
1010 	uint16_t col_num, int exclude_row_edge, int exclude_col_edge)
1011 {
1012 	int i = 0;
1013 	int32_t cm_min_cur = 0;
1014 	int32_t cm_max_cur = 0;
1015 	int32_t cm_ave_cur = 0;
1016 	int32_t cm_ave_next = 0;
1017 	int32_t cm_ave_prev = 0;
1018 	struct gd_sensor *p = gd_sensor_row_head;
1019 
1020 	if (!exclude_col_edge) {
1021 		for (i = 0; i < col_num; i++) {
1022 			if (!exclude_row_edge) {
1023 				cm_ave_cur = (p + i)->cm_ave;
1024 				cm_min_cur = (p + i)->cm_min;
1025 				cm_max_cur = (p + i)->cm_max;
1026 				if (i < (col_num-1))
1027 					cm_ave_next = (p + i+1)->cm_ave;
1028 				if (i > 0)
1029 					cm_ave_prev = (p + i-1)->cm_ave;
1030 			} else {
1031 				cm_ave_cur = (p + i)->cm_ave_exclude_edge;
1032 				cm_min_cur = (p + i)->cm_min_exclude_edge;
1033 				cm_max_cur = (p + i)->cm_max_exclude_edge;
1034 				if (i < (col_num-1))
1035 					cm_ave_next =
1036 					(p + i+1)->cm_ave_exclude_edge;
1037 				if (i > 0)
1038 					cm_ave_prev =
1039 					(p + i-1)->cm_ave_exclude_edge;
1040 			}
1041 			if (cm_ave_cur == 0)
1042 				cm_ave_cur = 1;
1043 			/*multiple 1000 to increate accuracy*/
1044 			if (i <= 1)
1045 				(p + i)->gradient_val = (cm_max_cur - cm_min_cur
1046 				+ ABS(cm_ave_cur - cm_ave_next)) * 1000 /
1047 				cm_ave_cur;
1048 			else
1049 				(p + i)->gradient_val = (cm_max_cur - cm_min_cur
1050 				+ ABS(cm_ave_cur - cm_ave_prev)) * 1000 /
1051 				cm_ave_cur;
1052 		}
1053 	} else if (exclude_col_edge) {
1054 		for (i = 0; i < col_num; i++) {
1055 			if (!exclude_row_edge) {
1056 				cm_ave_cur = (p + i)->cm_ave;
1057 				cm_min_cur = (p + i)->cm_min;
1058 				cm_max_cur = (p + i)->cm_max;
1059 				if (i < (col_num-1))
1060 					cm_ave_next = (p + i+1)->cm_ave;
1061 				if (i > 0)
1062 					cm_ave_prev = (p + i-1)->cm_ave;
1063 			} else {
1064 				cm_ave_cur = (p + i)->cm_ave_exclude_edge;
1065 				cm_min_cur = (p + i)->cm_min_exclude_edge;
1066 				cm_max_cur = (p + i)->cm_max_exclude_edge;
1067 				if (i < (col_num-1))
1068 					cm_ave_next =
1069 					(p + i+1)->cm_ave_exclude_edge;
1070 				if (i > 0)
1071 					cm_ave_prev =
1072 					(p + i-1)->cm_ave_exclude_edge;
1073 			}
1074 
1075 			if (cm_ave_cur == 0)
1076 				cm_ave_cur = 1;
1077 			/*multiple 1000 to increate accuracy*/
1078 			if ((i == 0) || (i == (col_num - 1)))
1079 				(p + i)->gradient_val =
1080 					 (cm_max_cur - cm_min_cur) * 1000 /
1081 					 cm_ave_cur;
1082 			else if (i == 1)
1083 				(p + i)->gradient_val =
1084 					(cm_max_cur - cm_min_cur +
1085 					ABS(cm_ave_cur - cm_ave_next))
1086 					 * 1000 / cm_ave_cur;
1087 			else
1088 				(p + i)->gradient_val =
1089 					(cm_max_cur - cm_min_cur +
1090 					ABS(cm_ave_cur - cm_ave_prev))
1091 					* 1000 / cm_ave_cur;
1092 			}
1093 	}
1094 }
1095 
fill_gd_sensor_table(struct gd_sensor * head,int32_t index,int32_t cm_max,int32_t cm_min,int32_t cm_ave,int32_t cm_max_exclude_edge,int32_t cm_min_exclude_edge,int32_t cm_ave_exclude_edge)1096 static void fill_gd_sensor_table(struct gd_sensor *head, int32_t index,
1097 	int32_t cm_max, int32_t cm_min,	int32_t cm_ave,
1098 	int32_t cm_max_exclude_edge, int32_t cm_min_exclude_edge,
1099 	int32_t cm_ave_exclude_edge)
1100 {
1101 	(head + index)->cm_max = cm_max;
1102 	(head + index)->cm_min = cm_min;
1103 	(head + index)->cm_ave = cm_ave;
1104 	(head + index)->cm_ave_exclude_edge = cm_ave_exclude_edge;
1105 	(head + index)->cm_max_exclude_edge = cm_max_exclude_edge;
1106 	(head + index)->cm_min_exclude_edge = cm_min_exclude_edge;
1107 }
1108 
calculate_gd_info(struct gd_sensor * gd_sensor_col,struct gd_sensor * gd_sensor_row,int tx_num,int rx_num,int32_t * cm_sensor_data,int cm_excluding_row_edge,int cm_excluding_col_edge)1109 static void calculate_gd_info(struct gd_sensor *gd_sensor_col,
1110 	struct gd_sensor *gd_sensor_row, int tx_num, int rx_num,
1111 	int32_t *cm_sensor_data, int cm_excluding_row_edge,
1112 	int cm_excluding_col_edge)
1113 {
1114 	int32_t cm_max;
1115 	int32_t cm_min;
1116 	int32_t cm_ave;
1117 	int32_t cm_max_exclude_edge;
1118 	int32_t cm_min_exclude_edge;
1119 	int32_t cm_ave_exclude_edge;
1120 	int32_t cm_data;
1121 	int i;
1122 	int j;
1123 
1124 	if (!cm_sensor_data)
1125 		return;
1126 
1127 	/*calculate all the gradient related info for column*/
1128 	for (i = 0; i < tx_num; i++) {
1129 		/*re-initialize for a new col*/
1130 		cm_max = cm_sensor_data[i * rx_num];
1131 		cm_min = cm_max;
1132 		cm_ave = 0;
1133 		cm_max_exclude_edge = cm_sensor_data[i * rx_num + 1];
1134 		cm_min_exclude_edge = cm_max_exclude_edge;
1135 		cm_ave_exclude_edge = 0;
1136 
1137 		for (j = 0; j < rx_num; j++) {
1138 			cm_data = cm_sensor_data[i * rx_num + j];
1139 			if (cm_data > cm_max)
1140 				cm_max = cm_data;
1141 			if (cm_data < cm_min)
1142 				cm_min = cm_data;
1143 			cm_ave += cm_data;
1144 			/*calculate exclude edge data*/
1145 			if ((j > 0) && (j < (rx_num-1))) {
1146 				if (cm_data > cm_max_exclude_edge)
1147 					cm_max_exclude_edge = cm_data;
1148 				if (cm_data < cm_min_exclude_edge)
1149 					cm_min_exclude_edge = cm_data;
1150 				cm_ave_exclude_edge += cm_data;
1151 			}
1152 		}
1153 		if (rx_num)
1154 			cm_ave /= rx_num;
1155 		if (rx_num - 2)
1156 			cm_ave_exclude_edge /= (rx_num-2);
1157 		fill_gd_sensor_table(gd_sensor_col, i, cm_max, cm_min, cm_ave,
1158 		cm_max_exclude_edge, cm_min_exclude_edge, cm_ave_exclude_edge);
1159 	}
1160 
1161 	calculate_gradient_col(gd_sensor_col, tx_num, cm_excluding_row_edge,
1162 		 cm_excluding_col_edge);
1163 
1164 	/*calculate all the gradient related info for row*/
1165 	for (j = 0; j < rx_num; j++) {
1166 		/*re-initialize for a new row*/
1167 		cm_max = cm_sensor_data[j];
1168 		cm_min = cm_max;
1169 		cm_ave = 0;
1170 		cm_max_exclude_edge = cm_sensor_data[rx_num + j];
1171 		cm_min_exclude_edge = cm_max_exclude_edge;
1172 		cm_ave_exclude_edge = 0;
1173 		for (i = 0; i < tx_num; i++) {
1174 			cm_data = cm_sensor_data[i * rx_num + j];
1175 			if (cm_data > cm_max)
1176 				cm_max = cm_data;
1177 			if (cm_data < cm_min)
1178 				cm_min = cm_data;
1179 			cm_ave += cm_data;
1180 			/*calculate exclude edge data*/
1181 			if ((i >  0) && (i < (tx_num-1))) {
1182 				if (cm_data > cm_max_exclude_edge)
1183 					cm_max_exclude_edge = cm_data;
1184 				if (cm_data < cm_min_exclude_edge)
1185 					cm_min_exclude_edge = cm_data;
1186 				cm_ave_exclude_edge += cm_data;
1187 			}
1188 		}
1189 		if (tx_num)
1190 			cm_ave /= tx_num;
1191 		if (tx_num - 2)
1192 			cm_ave_exclude_edge /= (tx_num-2);
1193 		fill_gd_sensor_table(gd_sensor_row, j, cm_max, cm_min, cm_ave,
1194 		cm_max_exclude_edge, cm_min_exclude_edge, cm_ave_exclude_edge);
1195 	}
1196 	calculate_gradient_row(gd_sensor_row, rx_num, cm_excluding_row_edge,
1197 		 cm_excluding_col_edge);
1198 }
1199 
cyttsp5_get_cmcp_info(struct cyttsp5_device_access_data * dad,struct cmcp_data * cmcp_info)1200 static int  cyttsp5_get_cmcp_info(struct cyttsp5_device_access_data *dad,
1201 	struct cmcp_data *cmcp_info)
1202 {
1203 	struct device *dev;
1204 	int32_t *cm_data_panel = cmcp_info->cm_data_panel;
1205 	int32_t *cp_tx_data_panel = cmcp_info->cp_tx_data_panel;
1206 	int32_t *cp_rx_data_panel = cmcp_info->cp_rx_data_panel;
1207 	int32_t *cp_tx_cal_data_panel = cmcp_info->cp_tx_cal_data_panel;
1208 	int32_t *cp_rx_cal_data_panel = cmcp_info->cp_rx_cal_data_panel;
1209 	int32_t *cm_btn_data = cmcp_info->cm_btn_data;
1210 	int32_t *cp_btn_data = cmcp_info->cp_btn_data;
1211 	struct gd_sensor *gd_sensor_col = cmcp_info->gd_sensor_col;
1212 	struct gd_sensor *gd_sensor_row = cmcp_info->gd_sensor_row;
1213 	struct result *result = dad->result;
1214 	int32_t cp_btn_cal = 0;
1215 	int32_t cm_btn_cal = 0;
1216 	int32_t cp_btn_ave = 0;
1217 	int32_t cm_ave_data_panel = 0;
1218 	int32_t cm_ave_data_btn = 0;
1219 	int32_t cm_delta_data_btn = 0;
1220 	int32_t cp_tx_ave_data_panel = 0;
1221 	int32_t cp_rx_ave_data_panel = 0;
1222 	u8 tmp_buf[3];
1223 	int tx_num;
1224 	int rx_num;
1225 	int btn_num;
1226 	int rc = 0;
1227 	int i;
1228 
1229 	dev = dad->dev;
1230 	cmcp_info->tx_num = dad->si->sensing_conf_data.tx_num;
1231 	cmcp_info->rx_num = dad->si->sensing_conf_data.rx_num;
1232 	cmcp_info->btn_num = dad->si->num_btns;
1233 
1234 	tx_num = cmcp_info->tx_num;
1235 	rx_num = cmcp_info->rx_num;
1236 	btn_num = cmcp_info->btn_num;
1237 	parade_debug(dev, DEBUG_LEVEL_2, "%s tx_num=%d", __func__, tx_num);
1238 	parade_debug(dev, DEBUG_LEVEL_2, "%s rx_num=%d", __func__, rx_num);
1239 	parade_debug(dev, DEBUG_LEVEL_2, "%s btn_num=%d", __func__, btn_num);
1240 
1241 	/*short test*/
1242 	result->short_test_pass = true;
1243 	rc = cyttsp5_run_and_get_selftest_result_noprint(
1244 		dev, tmp_buf, sizeof(tmp_buf),
1245 		CY_ST_ID_AUTOSHORTS, PIP_CMD_MAX_LENGTH, false);
1246 	if (rc) {
1247 		dev_err(dev, "short test not supported");
1248 		goto exit;
1249 	}
1250 	if (dad->ic_buf[1] != 0)
1251 		result->short_test_pass = false;
1252 
1253 	/*Get cm_panel data*/
1254 	rc = cyttsp5_run_and_get_selftest_result_noprint(
1255 		dev, tmp_buf, sizeof(tmp_buf),
1256 		CY_ST_ID_CM_PANEL, PIP_CMD_MAX_LENGTH, true);
1257 	if (rc) {
1258 		dev_err(dev, "Get CM Panel not supported");
1259 		goto exit;
1260 	}
1261 	if (cm_data_panel != NULL) {
1262 		for (i = 0; i < tx_num * rx_num;  i++) {
1263 			cm_data_panel[i] =
1264 			10*(dad->ic_buf[CM_PANEL_DATA_OFFSET+i*2] + 256
1265 			* dad->ic_buf[CM_PANEL_DATA_OFFSET+i*2+1]);
1266 			parade_debug(dev, DEBUG_LEVEL_2,
1267 				"cm_data_panel[%d]=%d\n",
1268 				i, cm_data_panel[i]);
1269 			cm_ave_data_panel += cm_data_panel[i];
1270 		}
1271 		cm_ave_data_panel /= (tx_num * rx_num);
1272 		cmcp_info->cm_ave_data_panel = cm_ave_data_panel;
1273 		cmcp_info->cm_cal_data_panel =
1274 		10*(dad->ic_buf[CM_PANEL_DATA_OFFSET+i*2]
1275 		+256 * dad->ic_buf[CM_PANEL_DATA_OFFSET+i*2+1]);
1276 		/*multiple 1000 to increate accuracy*/
1277 		cmcp_info->cm_sensor_delta = ABS((cmcp_info->cm_ave_data_panel -
1278 			cmcp_info->cm_cal_data_panel) * 1000 /
1279 			cmcp_info->cm_ave_data_panel);
1280 	}
1281 
1282 	/*calculate gradient panel sensor column/row here*/
1283 	calculate_gd_info(gd_sensor_col, gd_sensor_row, tx_num, rx_num,
1284 		 cm_data_panel, 1, 1);
1285 	for (i = 0; i < tx_num; i++) {
1286 		parade_debug(dev, DEBUG_LEVEL_2,
1287 			"i=%d max=%d,min=%d,ave=%d, gradient=%d",
1288 			i, gd_sensor_col[i].cm_max, gd_sensor_col[i].cm_min,
1289 			gd_sensor_col[i].cm_ave, gd_sensor_col[i].gradient_val);
1290 	}
1291 
1292 	for (i = 0; i < rx_num; i++) {
1293 		parade_debug(dev, DEBUG_LEVEL_2,
1294 			"i=%d max=%d,min=%d,ave=%d, gradient=%d",
1295 			i, gd_sensor_row[i].cm_max, gd_sensor_row[i].cm_min,
1296 			gd_sensor_row[i].cm_ave, gd_sensor_row[i].gradient_val);
1297 	}
1298 
1299 	/*Get cp data*/
1300 	rc = cyttsp5_run_and_get_selftest_result_noprint(
1301 		dev, tmp_buf, sizeof(tmp_buf),
1302 		CY_ST_ID_CP_PANEL, PIP_CMD_MAX_LENGTH, true);
1303 	if (rc) {
1304 		dev_err(dev, "Get CP Panel not supported");
1305 		goto exit;
1306 	}
1307 	/*Get cp_tx_data_panel*/
1308 	if (cp_tx_data_panel != NULL) {
1309 		for (i = 0; i < tx_num; i++) {
1310 			cp_tx_data_panel[i] =
1311 			10*(dad->ic_buf[CP_PANEL_DATA_OFFSET+i*2]
1312 			+ 256 * dad->ic_buf[CP_PANEL_DATA_OFFSET+i*2+1]);
1313 			parade_debug(dev, DEBUG_LEVEL_2,
1314 				"cp_tx_data_panel[%d]=%d\n",
1315 				i, cp_tx_data_panel[i]);
1316 			cp_tx_ave_data_panel += cp_tx_data_panel[i];
1317 		}
1318 		if (tx_num)
1319 			cp_tx_ave_data_panel /= tx_num;
1320 		cmcp_info->cp_tx_ave_data_panel = cp_tx_ave_data_panel;
1321 	}
1322 
1323 	/*Get cp_tx_cal_data_panel*/
1324 	if (cp_tx_cal_data_panel != NULL) {
1325 		for (i = 0; i < tx_num; i++) {
1326 			cp_tx_cal_data_panel[i] =
1327 			10*(dad->ic_buf[CP_PANEL_DATA_OFFSET+tx_num*2+i*2]
1328 		+ 256 * dad->ic_buf[CP_PANEL_DATA_OFFSET+tx_num*2+i*2+1]);
1329 			parade_debug(dev, DEBUG_LEVEL_2, " cp_tx_cal_data_panel[%d]=%d\n",
1330 				i, cp_tx_cal_data_panel[i]);
1331 		}
1332 	}
1333 
1334 	/*get cp_sensor_tx_delta,using the first sensor cal value for temp */
1335 	/*multiple 1000 to increase accuracy*/
1336 	if (cp_tx_cal_data_panel != NULL) {
1337 		cmcp_info->cp_sensor_tx_delta = ABS((cp_tx_cal_data_panel[0]
1338 			- cp_tx_ave_data_panel) * 1000 / cp_tx_ave_data_panel);
1339 	}
1340 
1341 	/*Get cp_rx_data_panel*/
1342 	if (cp_rx_data_panel != NULL) {
1343 		for (i = 0; i < rx_num;  i++) {
1344 			cp_rx_data_panel[i] =
1345 			10*(dad->ic_buf[CP_PANEL_DATA_OFFSET+tx_num*4+i*2] +
1346 			256 * dad->ic_buf[CP_PANEL_DATA_OFFSET+tx_num*4+i*2+1]);
1347 			parade_debug(dev, DEBUG_LEVEL_2,
1348 				"cp_rx_data_panel[%d]=%d\n", i,
1349 				cp_rx_data_panel[i]);
1350 			cp_rx_ave_data_panel += cp_rx_data_panel[i];
1351 		}
1352 		if (rx_num)
1353 			cp_rx_ave_data_panel /= rx_num;
1354 		cmcp_info->cp_rx_ave_data_panel = cp_rx_ave_data_panel;
1355 	}
1356 
1357 	/*Get cp_rx_cal_data_panel*/
1358 	if (cp_rx_cal_data_panel != NULL) {
1359 		for (i = 0; i < rx_num; i++) {
1360 			cp_rx_cal_data_panel[i] =
1361 		10 * (dad->ic_buf[CP_PANEL_DATA_OFFSET+tx_num*4+rx_num*2+i*2] +
1362 		256 *
1363 		dad->ic_buf[CP_PANEL_DATA_OFFSET+tx_num*4+rx_num*2+i*2+1]);
1364 			parade_debug(dev, DEBUG_LEVEL_2,
1365 				"cp_rx_cal_data_panel[%d]=%d\n", i,
1366 				cp_rx_cal_data_panel[i]);
1367 		}
1368 	}
1369 
1370 	/*get cp_sensor_rx_delta,using the first sensor cal value for temp */
1371 	/*multiple 1000 to increase accuracy*/
1372 	if (cp_rx_cal_data_panel != NULL) {
1373 		if (cp_rx_ave_data_panel) {
1374 			cmcp_info->cp_sensor_rx_delta = ABS((cp_rx_cal_data_panel[0]
1375 				- cp_rx_ave_data_panel) * 1000 / cp_rx_ave_data_panel);
1376 		}
1377 	}
1378 	if (btn_num == 0)
1379 		goto skip_button_test;
1380 
1381 	/*get cm btn data*/
1382 	rc = cyttsp5_run_and_get_selftest_result_noprint(
1383 		dev, tmp_buf, sizeof(tmp_buf),
1384 		CY_ST_ID_CM_BUTTON, PIP_CMD_MAX_LENGTH, true);
1385 	if (rc) {
1386 		dev_err(dev, "Get CM BTN not supported");
1387 		goto exit;
1388 	}
1389 	if (cm_btn_data != NULL) {
1390 		for (i = 0; i < btn_num; i++) {
1391 			cm_btn_data[i] =
1392 			10 * (dad->ic_buf[CM_BTN_DATA_OFFSET+i*2] +
1393 			256 * dad->ic_buf[CM_BTN_DATA_OFFSET+i*2+1]);
1394 			parade_debug(dev, DEBUG_LEVEL_2,
1395 				" cm_btn_data[%d]=%d\n",
1396 				i, cm_btn_data[i]);
1397 			cm_ave_data_btn += cm_btn_data[i];
1398 		}
1399 		cm_ave_data_btn /= btn_num;
1400 		cm_btn_cal = 10*(dad->ic_buf[CM_BTN_DATA_OFFSET+i*2]
1401 			 + 256 * dad->ic_buf[CM_BTN_DATA_OFFSET+i*2+1]);
1402 		/*multiple 1000 to increase accuracy*/
1403 		cm_delta_data_btn = ABS((cm_ave_data_btn-cm_btn_cal)
1404 			 * 1000 / cm_ave_data_btn);
1405 		parade_debug(dev, DEBUG_LEVEL_2, " cm_btn_cal=%d\n",
1406 			cm_btn_cal);
1407 
1408 		cmcp_info->cm_ave_data_btn = cm_ave_data_btn;
1409 		cmcp_info->cm_cal_data_btn = cm_btn_cal;
1410 		cmcp_info->cm_delta_data_btn = cm_delta_data_btn;
1411 	}
1412 
1413 	/*get cp btn data*/
1414 	rc = cyttsp5_run_and_get_selftest_result_noprint(
1415 		dev, tmp_buf, sizeof(tmp_buf),
1416 		CY_ST_ID_CP_BUTTON, PIP_CMD_MAX_LENGTH, true);
1417 	if (rc) {
1418 		dev_err(dev, "Get CP BTN not supported");
1419 		goto exit;
1420 	}
1421 	if (cp_btn_data != NULL) {
1422 		for (i = 0; i < btn_num; i++) {
1423 			cp_btn_data[i] =
1424 			10 * (dad->ic_buf[CP_BTN_DATA_OFFSET+i*2] +
1425 			256 * dad->ic_buf[CP_BTN_DATA_OFFSET+i*2+1]);
1426 			cp_btn_ave += cp_btn_data[i];
1427 			parade_debug(dev, DEBUG_LEVEL_2,
1428 				"cp_btn_data[%d]=%d\n",
1429 				i, cp_btn_data[i]);
1430 		}
1431 		cp_btn_ave /= btn_num;
1432 		cp_btn_cal = 10*(dad->ic_buf[CP_BTN_DATA_OFFSET+i*2]
1433 			 + 256 * dad->ic_buf[CP_BTN_DATA_OFFSET+i*2+1]);
1434 		cmcp_info->cp_button_ave = cp_btn_ave;
1435 		cmcp_info->cp_btn_cal = cp_btn_cal;
1436 		/*multiple 1000 to increase accuracy*/
1437 		cmcp_info->cp_button_delta = ABS((cp_btn_cal
1438 		- cp_btn_ave) * 1000 / cp_btn_ave);
1439 		parade_debug(dev, DEBUG_LEVEL_2, " cp_btn_cal=%d\n",
1440 			cp_btn_cal);
1441 		parade_debug(dev, DEBUG_LEVEL_2, " cp_btn_ave=%d\n",
1442 			cp_btn_ave);
1443 	}
1444 skip_button_test:
1445 exit:
1446 	return rc;
1447 }
1448 
cyttsp5_free_cmcp_buf(struct cmcp_data * cmcp_info)1449 static void cyttsp5_free_cmcp_buf(struct cmcp_data *cmcp_info)
1450 {
1451 	if (cmcp_info->gd_sensor_col != NULL)
1452 		kfree(cmcp_info->gd_sensor_col);
1453 	if (cmcp_info->gd_sensor_row != NULL)
1454 		kfree(cmcp_info->gd_sensor_row);
1455 	if (cmcp_info->cm_data_panel != NULL)
1456 		kfree(cmcp_info->cm_data_panel);
1457 	if (cmcp_info->cp_tx_data_panel != NULL)
1458 		kfree(cmcp_info->cp_tx_data_panel);
1459 	if (cmcp_info->cp_rx_data_panel != NULL)
1460 		kfree(cmcp_info->cp_rx_data_panel);
1461 	if (cmcp_info->cp_tx_cal_data_panel != NULL)
1462 		kfree(cmcp_info->cp_tx_cal_data_panel);
1463 	if (cmcp_info->cp_rx_cal_data_panel != NULL)
1464 		kfree(cmcp_info->cp_rx_cal_data_panel);
1465 	if (cmcp_info->cm_btn_data != NULL)
1466 		kfree(cmcp_info->cm_btn_data);
1467 	if (cmcp_info->cp_btn_data != NULL)
1468 		kfree(cmcp_info->cp_btn_data);
1469 	if (cmcp_info->cm_sensor_column_delta != NULL)
1470 		kfree(cmcp_info->cm_sensor_column_delta);
1471 	if (cmcp_info->cm_sensor_row_delta != NULL)
1472 		kfree(cmcp_info->cm_sensor_row_delta);
1473 }
1474 
cyttsp5_cmcp_get_test_item(int item_input)1475 static int cyttsp5_cmcp_get_test_item(int item_input)
1476 {
1477 	int test_item = 0;
1478 
1479 	switch (item_input) {
1480 	case CMCP_FULL:
1481 		test_item = CMCP_FULL_CASE;
1482 		break;
1483 	case CMCP_CM_PANEL:
1484 		test_item = CM_PANEL;
1485 		break;
1486 	case CMCP_CP_PANEL:
1487 		test_item = CP_PANEL;
1488 		break;
1489 	case CMCP_CM_BTN:
1490 		test_item = CM_BTN;
1491 		break;
1492 	case CMCP_CP_BTN:
1493 		test_item = CP_BTN;
1494 		break;
1495 	}
1496 	return test_item;
1497 }
1498 
cyttsp5_cmcp_test_show(struct device * dev,struct device_attribute * attr,char * buf)1499 static ssize_t cyttsp5_cmcp_test_show(struct device *dev,
1500 		struct device_attribute *attr, char *buf)
1501 {
1502 	struct cyttsp5_device_access_data *dad
1503 		= cyttsp5_get_device_access_data(dev);
1504 	struct cmcp_data *cmcp_info = dad->cmcp_info;
1505 	struct result *result = dad->result;
1506 	struct configuration *configuration = dad->configs;
1507 	bool final_pass = true;
1508 	static const char * const cmcp_test_case_array[] = {"Full Cm/Cp test",
1509 		"Cm panel test", "Cp panel test",
1510 		"Cm button test", "Cp button test"};
1511 	int index = 0;
1512 	int test_item = 0;
1513 	int no_builtin_file = 0;
1514 	int rc;
1515 	u8 status;
1516 	int self_test_id_supported = 0;
1517 
1518 	dev = dad->dev;
1519 	if ((configuration == NULL) || (cmcp_info == NULL))
1520 		goto exit;
1521 
1522 	mutex_lock(&dad->sysfs_lock);
1523 
1524 	if (dad->cmcp_test_in_progress) {
1525 		mutex_unlock(&dad->sysfs_lock);
1526 		goto cmcp_not_ready;
1527 	}
1528 	dad->cmcp_test_in_progress = 1;
1529 
1530 	dad->test_executed = 0;
1531 	test_item = cyttsp5_cmcp_get_test_item(dad->cmcp_test_items);
1532 
1533 	if (dad->builtin_cmcp_threshold_status < 0) {
1534 		dev_err(dev, "%s: No cmcp threshold file.\n", __func__);
1535 		no_builtin_file = 1;
1536 		mutex_unlock(&dad->sysfs_lock);
1537 		goto start_testing;
1538 	}
1539 
1540 	if (dad->cmcp_test_items < 0) {
1541 		parade_debug(dev, DEBUG_LEVEL_2,
1542 			"%s: Invalid test item! Should be 0~4!\n", __func__);
1543 		mutex_unlock(&dad->sysfs_lock);
1544 		goto invalid_item;
1545 	}
1546 
1547 	parade_debug(dev, DEBUG_LEVEL_2, "%s: Test item is %s, %d\n",
1548 		__func__, cmcp_test_case_array[dad->cmcp_test_items],
1549 		test_item);
1550 
1551 	if ((dad->si->num_btns == 0)
1552 		&& ((dad->cmcp_test_items == CMCP_CM_BTN)
1553 			|| (dad->cmcp_test_items == CMCP_CP_BTN))) {
1554 		parade_debug(dev, DEBUG_LEVEL_2,
1555 			"%s: FW doesn't support button!\n", __func__);
1556 		mutex_unlock(&dad->sysfs_lock);
1557 		goto invalid_item_btn;
1558 	}
1559 
1560 	mutex_unlock(&dad->sysfs_lock);
1561 
1562 	if (cmcp_check_config_fw_match(dev, configuration))
1563 		goto mismatch;
1564 
1565 start_testing:
1566 	parade_debug(dev, DEBUG_LEVEL_2, "%s: Start Cm/Cp test!\n", __func__);
1567 	result->cm_test_pass = true;
1568 	result->cp_test_pass = true;
1569 
1570 #ifdef CYTTSP_WATCHDOG_DELAY_ENBALE
1571 	/*stop watchdog*/
1572 	rc = cmd->request_stop_wd(dev);
1573 	if (rc)
1574 		dev_err(dev, "stop watchdog failed");
1575 #endif
1576 	/*force single tx*/
1577 	rc = cmd->nonhid_cmd->set_param(dev, 0, 0x1F, 1, 1);
1578 	if (rc)
1579 		dev_err(dev, "force single tx failed");
1580 	/*suspend_scanning */
1581 	rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
1582 	if (rc)
1583 		dev_err(dev, "suspend_scanning failed");
1584 	/*do calibration*/
1585 	if (!dad->cmcp_force_calibrate) {
1586 		parade_debug(dev, DEBUG_LEVEL_2, "do calibration in single tx mode");
1587 		rc = _cyttsp5_calibrate_idacs_cmd(dev, 0, &status);
1588 		if (rc < 0) {
1589 			dev_err(dev, "%s: Error on calibrate idacs for mutual r=%d\n",
1590 					__func__, rc);
1591 		}
1592 		rc = _cyttsp5_calibrate_idacs_cmd(dev, 1, &status);
1593 		if (rc < 0) {
1594 			dev_err(dev, "%s: Error on calibrate idacs for buttons r=%d\n",
1595 					__func__, rc);
1596 		}
1597 		rc = _cyttsp5_calibrate_idacs_cmd(dev, 2, &status);
1598 		if (rc < 0) {
1599 			dev_err(dev, "%s: Error on calibrate idacs  for self r=%d\n",
1600 					__func__, rc);
1601 		}
1602 	}
1603 	/*resume_scanning */
1604 	rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
1605 	if (rc)
1606 		dev_err(dev, "resume_scanning failed");
1607 
1608 	/*get all cmcp data from FW*/
1609 	self_test_id_supported =
1610 		cyttsp5_get_cmcp_info(dad, cmcp_info);
1611 	if (self_test_id_supported)
1612 		dev_err(dev, "cyttsp5_get_cmcp_info failed");
1613 
1614 	/*restore to multi tx*/
1615 	rc = cmd->nonhid_cmd->set_param(dev, 0, 0x1F, 0, 1);
1616 	if (rc)
1617 		dev_err(dev, "restore multi tx failed");
1618 
1619 	/*suspend_scanning */
1620 	rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
1621 	if (rc)
1622 		dev_err(dev, "suspend_scanning failed");
1623 	/*do calibration*/
1624 	if (!dad->cmcp_force_calibrate) {
1625 		parade_debug(dev, DEBUG_LEVEL_2, "do calibration in multi tx mode");
1626 		rc = _cyttsp5_calibrate_idacs_cmd(dev, 0, &status);
1627 		if (rc < 0) {
1628 			dev_err(dev, "%s: Error on calibrate idacs for mutual r=%d\n",
1629 					__func__, rc);
1630 		}
1631 		rc = _cyttsp5_calibrate_idacs_cmd(dev, 1, &status);
1632 		if (rc < 0) {
1633 			dev_err(dev, "%s: Error on calibrate idacs for buttons r=%d\n",
1634 					__func__, rc);
1635 		}
1636 		rc = _cyttsp5_calibrate_idacs_cmd(dev, 2, &status);
1637 		if (rc < 0) {
1638 			dev_err(dev, "%s: Error on calibrate idacs  for self r=%d\n",
1639 					__func__, rc);
1640 		}
1641 
1642 	}
1643 	/*resume_scanning */
1644 	rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
1645 	if (rc)
1646 		dev_err(dev, "resume_scanning failed");
1647 
1648 #ifdef CYTTSP_WATCHDOG_DELAY_ENBALE
1649 	/*start  watchdog*/
1650 	rc = cmd->request_start_wd(dev);
1651 	if (rc)
1652 		dev_err(dev, "start watchdog failed");
1653 #endif
1654 	if (self_test_id_supported)
1655 		goto self_test_id_failed;
1656 
1657 	if (no_builtin_file)
1658 		goto no_builtin;
1659 
1660 	if (test_item & CM_ENABLED)
1661 		validate_cm_test_results(dev, configuration, cmcp_info,
1662 		result, &final_pass, test_item);
1663 
1664 	if (test_item & CP_ENABLED)
1665 		validate_cp_test_results(dev, configuration, cmcp_info,
1666 		result, &final_pass, test_item);
1667 no_builtin:
1668 	if ((dad->cmcp_test_items == CMCP_FULL)
1669 	&& (dad->cmcp_range_check == 0)) {
1670 		/*full test and full check*/
1671 		result->test_summary =
1672 			result->cm_test_pass
1673 			&& result->cp_test_pass
1674 			&& result->short_test_pass;
1675 	} else if ((dad->cmcp_test_items == CMCP_FULL)
1676 		&& (dad->cmcp_range_check == 1)) {
1677 		/*full test and basic check*/
1678 		result->test_summary =
1679 			result->cm_sensor_gd_col_pass
1680 			&& result->cm_sensor_gd_row_pass
1681 			&& result->cm_sensor_validation_pass
1682 			&& result->cp_rx_validation_pass
1683 			&& result->cp_tx_validation_pass
1684 			&& result->short_test_pass;
1685 	} else if (dad->cmcp_test_items == CMCP_CM_PANEL) {
1686 		/*cm panel test result only*/
1687 		result->test_summary =
1688 			result->cm_sensor_gd_col_pass
1689 			&& result->cm_sensor_gd_row_pass
1690 			&& result->cm_sensor_validation_pass
1691 			&& result->cm_sensor_row_delta_pass
1692 			&& result->cm_sensor_col_delta_pass
1693 			&& result->cm_sensor_calibration_pass
1694 			&& result->cm_sensor_delta_pass;
1695 	} else if (dad->cmcp_test_items == CMCP_CP_PANEL) {
1696 		/*cp panel test result only*/
1697 		result->test_summary =
1698 			result->cp_sensor_delta_pass
1699 			&& result->cp_rx_validation_pass
1700 			&& result->cp_tx_validation_pass;
1701 	} else if (dad->cmcp_test_items == CMCP_CM_BTN) {
1702 		/*cm button test result only*/
1703 		result->test_summary =
1704 			result->cm_button_validation_pass
1705 			&& result->cm_button_delta_pass;
1706 	} else if (dad->cmcp_test_items == CMCP_CP_BTN) {
1707 		/*cp button test result only*/
1708 		result->test_summary =
1709 			result->cp_button_delta_pass
1710 			&& result->cp_button_average_pass
1711 			&& result->cp_button_validation_pass;
1712 	}
1713 	mutex_lock(&dad->sysfs_lock);
1714 	dad->test_executed = 1;
1715 	mutex_unlock(&dad->sysfs_lock);
1716 
1717 	if (result->test_summary) {
1718 		dev_vdbg(dev, "%s: Finish Cm/Cp test! All Test Passed\n",
1719 				__func__);
1720 		index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1721 				"Status 1\n");
1722 	} else {
1723 		dev_vdbg(dev, "%s: Finish Cm/Cp test! Range Check Failure\n",
1724 				__func__);
1725 		index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1726 				"Status 6\n");
1727 	}
1728 
1729 	goto cmcp_ready;
1730 mismatch:
1731 	index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1732 		 "Status 2\nInput cmcp threshold file mismatches with FW\n");
1733 	goto cmcp_ready;
1734 invalid_item_btn:
1735 	index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1736 		"Status 3\nFW doesn't support button!\n");
1737 	goto cmcp_ready;
1738 invalid_item:
1739 	index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1740 		"Status 4\nWrong test item or range check input!\nOnly support below items:\n0 - Cm/Cp Panel & Button with Gradient (Typical)\n1 - Cm Panel with Gradient\n2 - Cp Panel\n3 - Cm Button\n4 - Cp Button\nOnly support below range check:\n0 - Full Range Checking (default)\n1 - Basic Range Checking(TSG5 style)\n");
1741 	goto cmcp_ready;
1742 self_test_id_failed:
1743 	index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1744 		"Status 5\nget self test ID not supported!");
1745 	goto cmcp_ready;
1746 cmcp_not_ready:
1747 	index = snprintf(buf, CY_MAX_PRBUF_SIZE,
1748 			"Status 0\n");
1749 	goto cmcp_ready;
1750 cmcp_ready:
1751 	mutex_lock(&dad->sysfs_lock);
1752 	dad->cmcp_test_in_progress = 0;
1753 	mutex_unlock(&dad->sysfs_lock);
1754 exit:
1755 	return index;
1756 }
1757 
cyttsp5_cmcp_test_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)1758 static ssize_t cyttsp5_cmcp_test_store(struct device *dev,
1759 		struct device_attribute *attr, const char *buf, size_t size)
1760 {
1761 	struct cyttsp5_device_access_data *dad
1762 		= cyttsp5_get_device_access_data(dev);
1763 	u8 test_item = 0;
1764 	u8 range_check = 0;
1765 	u8 force_calibrate = 0;
1766 	int ret = 0;
1767 	static const char * const cmcp_test_case_array[] = {"Full Cm/Cp test",
1768 		"Cm panel test", "Cp panel test",
1769 		"Cm button test", "Cp button test"};
1770 	static const char * const cmcp_test_range_check_array[] = {
1771 		"Full (default)", "Basic"};
1772 	static const char * const cmcp_test_force_cal_array[] =	{
1773 		"Calibrate When Testing (default)", "No Calibration"};
1774 	ssize_t length = 0;
1775 
1776 	pm_runtime_get_sync(dev);
1777 	mutex_lock(&dad->sysfs_lock);
1778 
1779 	length = cyttsp5_ic_parse_input(dev, buf, size, dad->ic_buf,
1780 			CY_MAX_PRBUF_SIZE);
1781 	if (length <= 0 || length > 3) {
1782 		dev_err(dev, "%s: Input format error!\n", __func__);
1783 		dad->cmcp_test_items = -EINVAL;
1784 		ret = -EINVAL;
1785 		goto error;
1786 	}
1787 
1788 	/* Get test item  */
1789 	test_item = dad->ic_buf[0];
1790 	/* Get range check */
1791 	if (length >= 2)
1792 		range_check = dad->ic_buf[1];
1793 	/* Get force calibration */
1794 	if (length == 3)
1795 		force_calibrate = dad->ic_buf[2];
1796 
1797 	/*
1798 	 * Test item limitation:
1799 	 *	 0: Perform all Tests
1800 	 *	 1: CM Panel with Gradient
1801 	 *	 2: CP Panel
1802 	 *	 3: CM Button
1803 	 *	 4: CP Button
1804 	 * Ranage check limitation:
1805 	 *	 0: full check
1806 	 *	 1: basic check
1807 	 * Force calibrate limitation:
1808 	 *	 0: do calibration
1809 	 *	 1: don't do calibration
1810 	 */
1811 	if ((test_item < 0) || (test_item > 4) || (range_check > 1)
1812 		|| (force_calibrate > 1)) {
1813 		dev_err(dev,
1814 		"%s: Test item should be 0~4; Range check should be 0~1; Force calibrate should be 0~1\n",
1815 		__func__);
1816 		dad->cmcp_test_items = -EINVAL;
1817 		ret = -EINVAL;
1818 		goto error;
1819 	}
1820 	/*
1821 	 * If it is not all Test, then range_check should be 0
1822 	 * because other test does not has concept of basic check
1823 	 */
1824 	if (test_item > 0 && test_item < 5)
1825 		range_check = 0;
1826 	dad->cmcp_test_items = test_item;
1827 	dad->cmcp_range_check = range_check;
1828 	dad->cmcp_force_calibrate = force_calibrate;
1829 	parade_debug(dev, DEBUG_LEVEL_2,
1830 		"%s: Test item is %s; Range check is %s; Force calibrate is %s.\n",
1831 		__func__,
1832 		cmcp_test_case_array[test_item],
1833 		cmcp_test_range_check_array[range_check],
1834 		cmcp_test_force_cal_array[force_calibrate]);
1835 
1836 error:
1837 	mutex_unlock(&dad->sysfs_lock);
1838 	pm_runtime_put(dev);
1839 
1840 	if (ret)
1841 		return ret;
1842 
1843 	return size;
1844 }
1845 
1846 static DEVICE_ATTR(cmcp_test, S_IRUSR | S_IWUSR,
1847 	cyttsp5_cmcp_test_show, cyttsp5_cmcp_test_store);
1848 
prepare_print_string(char * out_buf,char * in_buf,int index)1849 static int prepare_print_string(char *out_buf, char *in_buf, int index)
1850 {
1851 	if ((out_buf == NULL) || (in_buf == NULL))
1852 		return index;
1853 	index += scnprintf(&out_buf[index], MAX_BUF_LEN - index,
1854 			"%s", in_buf);
1855 	return index;
1856 }
1857 
prepare_print_data(char * out_buf,int32_t * in_buf,int index,int data_num)1858 static int prepare_print_data(char *out_buf, int32_t *in_buf, int index, int data_num)
1859 {
1860 	int i;
1861 
1862 	if ((out_buf == NULL) || (in_buf == NULL))
1863 		return index;
1864 	for (i = 0; i < data_num; i++)
1865 		index += scnprintf(&out_buf[index], MAX_BUF_LEN - index,
1866 				"%d,", in_buf[i]);
1867 	return index;
1868 }
1869 
save_header(char * out_buf,int index,struct result * result)1870 static int save_header(char *out_buf, int index, struct result *result)
1871 {
1872 	struct timex txc;
1873 	struct rtc_time tm;
1874 	char time_buf[100] = {0};
1875 
1876 	do_gettimeofday(&(txc.time));
1877 	rtc_time_to_tm(txc.time.tv_sec, &tm);
1878 	scnprintf(time_buf, 100, "%d/%d/%d,TIME,%d:%d:%d,", tm.tm_year+1900,
1879 		 tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
1880 
1881 	index = prepare_print_string(out_buf, ",.header,\n", index);
1882 	index = prepare_print_string(out_buf, ",DATE,", index);
1883 	index = prepare_print_string(out_buf, &time_buf[0], index);
1884 	index = prepare_print_string(out_buf, ",\n", index);
1885 	index = prepare_print_string(out_buf, ",SW_VERSION,", index);
1886 	index = prepare_print_string(out_buf, CY_DRIVER_VERSION, index);
1887 	index = prepare_print_string(out_buf, ",\n", index);
1888 	index = prepare_print_string(out_buf, ",.end,\n", index);
1889 	index = prepare_print_string(out_buf, ",.engineering data,\n", index);
1890 
1891 	return index;
1892 }
1893 
print_silicon_id(char * out_buf,char * in_buf,int index)1894 static int print_silicon_id(char *out_buf, char *in_buf, int index)
1895 {
1896 	index = prepare_print_string(out_buf, ",1,", index);
1897 	index = prepare_print_string(out_buf, &in_buf[0], index);
1898 	return index;
1899 }
1900 
save_engineering_data(struct device * dev,char * out_buf,int index,struct cmcp_data * cmcp_info,struct configuration * configuration,struct result * result,int test_item,int no_builtin_file)1901 static int save_engineering_data(struct device *dev, char *out_buf, int index,
1902 	struct cmcp_data *cmcp_info, struct configuration *configuration,
1903 	struct result *result, int test_item, int no_builtin_file)
1904 {
1905 	int i;
1906 	int j;
1907 	int tx_num = cmcp_info->tx_num;
1908 	int rx_num = cmcp_info->rx_num;
1909 	int btn_num = cmcp_info->btn_num;
1910 	int tmp = 0;
1911 	uint32_t fw_revision_control;
1912 	uint32_t fw_config_ver;
1913 	char device_id[20] = {0};
1914 	struct cyttsp5_device_access_data *dad
1915 		= cyttsp5_get_device_access_data(dev);
1916 
1917 	fw_revision_control = dad->si->cydata.revctrl;
1918 	fw_config_ver = dad->si->cydata.fw_ver_conf;
1919 	/*calculate silicon id*/
1920 	result->device_id_low = 0;
1921 	result->device_id_high = 0;
1922 
1923 	for (i = 0; i < 4; i++)
1924 		result->device_id_low =
1925 		(result->device_id_low << 8) + dad->si->cydata.mfg_id[i];
1926 
1927 	for (i = 4; i < 8; i++)
1928 		result->device_id_high =
1929 		(result->device_id_high << 8) + dad->si->cydata.mfg_id[i];
1930 
1931 	scnprintf(device_id, 20, "%x%x",
1932 		result->device_id_high, result->device_id_low);
1933 
1934 	/*print test summary*/
1935 	index = print_silicon_id(out_buf, &device_id[0], index);
1936 	if (result->test_summary)
1937 		index = prepare_print_string(out_buf, ",PASS,\n", index);
1938 	else
1939 		index = prepare_print_string(out_buf, ",FAIL,\n", index);
1940 
1941 	/*revision ctrl number*/
1942 	index = print_silicon_id(out_buf, &device_id[0], index);
1943 	index = prepare_print_string(out_buf, ",FW revision Control,", index);
1944 	index = prepare_print_data(out_buf, &fw_revision_control, index, 1);
1945 	index = prepare_print_string(out_buf, "\n", index);
1946 
1947 	/*config version*/
1948 	index = print_silicon_id(out_buf, &device_id[0], index);
1949 	index = prepare_print_string(out_buf, ",CONFIG_VER,", index);
1950 	index = prepare_print_data(out_buf, &fw_config_ver, index, 1);
1951 	index = prepare_print_string(out_buf, "\n", index);
1952 
1953 	/*short test*/
1954 	index = print_silicon_id(out_buf, &device_id[0], index);
1955 	if (result->short_test_pass)
1956 		index = prepare_print_string(out_buf, ",Shorts,PASS,\n", index);
1957 	else
1958 		index = prepare_print_string(out_buf, ",Shorts,FAIL,\n", index);
1959 
1960 	if ((test_item & CM_ENABLED) == CM_ENABLED) {
1961 		/*print BUTNS_CM_DATA_ROW00*/
1962 		if (((test_item & CM_BTN) == CM_BTN) && (btn_num > 0)) {
1963 			index = print_silicon_id(out_buf, &device_id[0], index);
1964 			index = prepare_print_string(out_buf,
1965 				",Sensor Cm Validation,BUTNS_CM_DATA_ROW00,",
1966 				index);
1967 			index = prepare_print_data(out_buf,
1968 				&cmcp_info->cm_btn_data[0],
1969 				index,
1970 				btn_num);
1971 			index = prepare_print_string(out_buf, "\n", index);
1972 		}
1973 
1974 		if ((test_item & CM_PANEL) == CM_PANEL) {
1975 			/*print CM_DATA_ROW*/
1976 			for (i = 0; i < rx_num; i++) {
1977 				index = print_silicon_id(out_buf, &device_id[0],
1978 							index);
1979 				index = prepare_print_string(out_buf,
1980 							",Sensor Cm Validation,CM_DATA_ROW",
1981 							index);
1982 				index = prepare_print_data(out_buf, &i,
1983 							index, 1);
1984 				for (j = 0; j < tx_num; j++)
1985 					index = prepare_print_data(out_buf,
1986 					&cmcp_info->cm_data_panel[j*rx_num+i],
1987 					index, 1);
1988 				index = prepare_print_string(out_buf,
1989 					"\n", index);
1990 			}
1991 
1992 			if (!no_builtin_file) {
1993 				/*print CM_MAX_GRADIENT_COLS_PERCENT*/
1994 				index = print_silicon_id(out_buf,
1995 							&device_id[0], index);
1996 				index = prepare_print_string(out_buf,
1997 					 ",Sensor Cm Validation,CM_MAX_GRADIENT_COLS_PERCENT,",
1998 					index);
1999 				for (i = 0; i < tx_num; i++) {
2000 					char tmp_buf[10] = {0};
2001 
2002 					scnprintf(tmp_buf, 10, "%d.%d,",
2003 				cmcp_info->gd_sensor_col[i].gradient_val / 10,
2004 				cmcp_info->gd_sensor_col[i].gradient_val % 10);
2005 					index = prepare_print_string(out_buf,
2006 						&tmp_buf[0], index);
2007 				}
2008 				index = prepare_print_string(out_buf,
2009 								"\n", index);
2010 
2011 				/*print CM_MAX_GRADIENT_ROWS_PERCENT*/
2012 				index = print_silicon_id(out_buf,
2013 							&device_id[0], index);
2014 				index = prepare_print_string(out_buf,
2015 			",Sensor Cm Validation,CM_MAX_GRADIENT_ROWS_PERCENT,",
2016 					index);
2017 				for (i = 0; i < rx_num; i++) {
2018 					char tmp_buf[10] = {0};
2019 
2020 					scnprintf(tmp_buf, 10, "%d.%d,",
2021 				cmcp_info->gd_sensor_row[i].gradient_val / 10,
2022 				cmcp_info->gd_sensor_row[i].gradient_val % 10);
2023 					index = prepare_print_string(out_buf,
2024 						&tmp_buf[0], index);
2025 				}
2026 				index = prepare_print_string(out_buf,
2027 								"\n", index);
2028 
2029 				if (!dad->cmcp_range_check) {
2030 					/*print CM_DELTA_COLUMN*/
2031 					for (i = 0; i < rx_num; i++) {
2032 						index = print_silicon_id(
2033 							out_buf,
2034 							&device_id[0], index);
2035 						index = prepare_print_string(
2036 							out_buf,
2037 							",Sensor Cm Validation,DELTA_COLUMNS_ROW",
2038 							index);
2039 						index = prepare_print_data(
2040 							out_buf,
2041 							&i, index, 1);
2042 						index = prepare_print_data(
2043 							out_buf,
2044 							&tmp, index, 1);
2045 						for (j = 1; j < tx_num; j++)
2046 							index = prepare_print_data(
2047 								out_buf,
2048 								&cmcp_info->cm_sensor_column_delta[(j-1)*rx_num+i],
2049 								index, 1);
2050 						index = prepare_print_string(
2051 							out_buf,
2052 							"\n", index);
2053 					}
2054 
2055 					/*print CM_DELTA_ROW*/
2056 					index = print_silicon_id(out_buf,
2057 								&device_id[0],
2058 								index);
2059 					index = prepare_print_string(out_buf,
2060 						 ",Sensor Cm Validation,DELTA_ROWS_ROW",
2061 								index);
2062 					index = prepare_print_data(out_buf,
2063 								&tmp, index, 1);
2064 					for (j = 0; j < tx_num; j++)
2065 						index = prepare_print_data(
2066 								out_buf,
2067 								&tmp, index, 1);
2068 					index = prepare_print_string(out_buf,
2069 								"\n", index);
2070 
2071 					for (i = 1; i < rx_num; i++) {
2072 						index = print_silicon_id(
2073 								out_buf,
2074 								&device_id[0],
2075 								index);
2076 						index = prepare_print_string(
2077 								out_buf,
2078 						",Sensor Cm Validation,DELTA_ROWS_ROW",
2079 								index);
2080 						index = prepare_print_data(
2081 								out_buf, &i,
2082 								index, 1);
2083 						for (j = 0; j < tx_num; j++)
2084 							index = prepare_print_data(
2085 								out_buf,
2086 							&cmcp_info->cm_sensor_row_delta[j*rx_num+i-1],
2087 							index, 1);
2088 						index = prepare_print_string(
2089 							out_buf,
2090 							"\n", index);
2091 					}
2092 
2093 				/*print pass/fail Sensor Cm Validation*/
2094 				index = print_silicon_id(out_buf, &device_id[0],
2095 							index);
2096 				if (result->cm_test_pass)
2097 					index = prepare_print_string(out_buf,
2098 						",Sensor Cm Validation,PASS,\n",
2099 						index);
2100 				else
2101 					index = prepare_print_string(out_buf,
2102 						",Sensor Cm Validation,FAIL,\n",
2103 						index);
2104 			}
2105 			}
2106 		}
2107 
2108 		if (!no_builtin_file) {
2109 			if (((test_item & CM_BTN) == CM_BTN) && (btn_num > 0)
2110 				&& (!dad->cmcp_range_check)) {
2111 				char tmp_buf[10] = {0};
2112 				/*print Button Element by Element */
2113 				index = print_silicon_id(out_buf, &device_id[0],
2114 					index);
2115 				if (result->cm_button_validation_pass)
2116 					index = prepare_print_string(out_buf,
2117 					",Sensor Cm Validation - Button Element by Element,PASS\n",
2118 					index);
2119 				else
2120 					index = prepare_print_string(out_buf,
2121 					",Sensor Cm Validation - Button Element by Element,FAIL\n",
2122 					index);
2123 
2124 				/*
2125 				*print  Sensor Cm Validation
2126 				*- Buttons Range Buttons Range
2127 				*/
2128 				index = print_silicon_id(out_buf,
2129 					&device_id[0], index);
2130 				index = prepare_print_string(out_buf,
2131 					 ",Sensor Cm Validation - Buttons Range,Buttons Range,",
2132 					 index);
2133 				scnprintf(tmp_buf, 10, "%d.%d,",
2134 					 cmcp_info->cm_delta_data_btn / 10,
2135 					 cmcp_info->cm_delta_data_btn % 10);
2136 				index = prepare_print_string(out_buf,
2137 					&tmp_buf[0], index);
2138 				index = prepare_print_string(out_buf,
2139 					"\n", index);
2140 
2141 				/*print  Sensor Cm Validation
2142 				 *-Buttons Range Cm_button_avg
2143 				 */
2144 				index = print_silicon_id(out_buf,
2145 					&device_id[0], index);
2146 				index = prepare_print_string(out_buf,
2147 					 ",Sensor Cm Validation - Buttons Range,Cm_button_avg,",
2148 					 index);
2149 				index = prepare_print_data(out_buf,
2150 					&cmcp_info->cm_ave_data_btn,
2151 					 index, 1);
2152 				index = prepare_print_string(out_buf,
2153 					"\n", index);
2154 
2155 				/*print  Sensor Cm Validation
2156 				 * -Buttons Range Cm_button_avg
2157 				 */
2158 				index = print_silicon_id(out_buf,
2159 					&device_id[0], index);
2160 				index = prepare_print_string(out_buf,
2161 					",Sensor Cm Validation - Buttons Range,Cm_button_cal,",
2162 					index);
2163 				index = prepare_print_data(out_buf,
2164 					&cmcp_info->cm_cal_data_btn,
2165 					index, 1);
2166 				index = prepare_print_string(out_buf,
2167 					"\n", index);
2168 
2169 				/*print  Sensor Cm Validation
2170 				 *-Buttons Range pass/fail
2171 				 */
2172 				index = print_silicon_id(out_buf,
2173 					&device_id[0], index);
2174 				if (result->cm_button_delta_pass)
2175 					index = prepare_print_string(out_buf,
2176 						",Sensor Cm Validation - Buttons Range,PASS,LIMITS,",
2177 						index);
2178 				else
2179 					index = prepare_print_string(out_buf,
2180 						",Sensor Cm Validation - Buttons Range,FAIL,LIMITS,",
2181 						index);
2182 				index = prepare_print_data(out_buf,
2183 				&configuration->cm_max_delta_button_percent,
2184 				index, 1);
2185 				index = prepare_print_string(out_buf,
2186 				"\n", index);
2187 			}
2188 
2189 			if ((test_item & CM_PANEL) == CM_PANEL &&
2190 				!dad->cmcp_range_check) {
2191 				char tmp_buf[10] = {0};
2192 				/*print Cm_sensor_cal */
2193 				index = print_silicon_id(out_buf,
2194 					&device_id[0], index);
2195 				index = prepare_print_string(out_buf,
2196 					",Sensor Cm Validation - Calibration,Cm_sensor_cal,",
2197 					index);
2198 				index = prepare_print_data(out_buf,
2199 					&cmcp_info->cm_cal_data_panel,
2200 					index, 1);
2201 				index = prepare_print_string(out_buf,
2202 					"\n", index);
2203 
2204 				/*print Cm_sensor_cal limit*/
2205 				index = print_silicon_id(out_buf,
2206 					&device_id[0], index);
2207 				if (result->cm_sensor_calibration_pass)
2208 					index = prepare_print_string(out_buf,
2209 						",Sensor Cm Validation - Calibration,PASS,LIMITS,",
2210 						index);
2211 				else
2212 					index = prepare_print_string(out_buf,
2213 						",Sensor Cm Validation - Calibration,FAIL,LIMITS,",
2214 						index);
2215 				index = prepare_print_data(out_buf,
2216 					&configuration->cm_min_limit_cal,
2217 					index, 1);
2218 				index = prepare_print_data(out_buf,
2219 					&configuration->cm_max_limit_cal,
2220 					index, 1);
2221 				index = prepare_print_string(out_buf,
2222 					"\n", index);
2223 
2224 				/*print Columns Delta Matrix*/
2225 				index = print_silicon_id(out_buf,
2226 					&device_id[0], index);
2227 				if (result->cm_sensor_col_delta_pass)
2228 					index = prepare_print_string(out_buf,
2229 					",Sensor Cm Validation - Columns Delta Matrix,PASS,LIMITS,",
2230 					index);
2231 				else
2232 					index = prepare_print_string(out_buf,
2233 					",Sensor Cm Validation - Columns Delta Matrix,FAIL,LIMITS,",
2234 					index);
2235 				index = prepare_print_data(out_buf,
2236 					&configuration->cm_range_limit_col,
2237 					index, 1);
2238 				index = prepare_print_string(out_buf,
2239 					"\n", index);
2240 
2241 				/*print Cm Validation - Element by Element*/
2242 				index = print_silicon_id(out_buf,
2243 					&device_id[0], index);
2244 				if (result->cm_sensor_validation_pass)
2245 					index = prepare_print_string(out_buf,
2246 						",Sensor Cm Validation - Element by Element,PASS,",
2247 						index);
2248 				else
2249 					index = prepare_print_string(out_buf,
2250 						",Sensor Cm Validation - Element by Element,FAIL,",
2251 						index);
2252 				index = prepare_print_string(out_buf,
2253 					"\n", index);
2254 
2255 				/*print Cm Validation -Gradient Cols*/
2256 				index = print_silicon_id(out_buf,
2257 					&device_id[0], index);
2258 				if (result->cm_sensor_gd_col_pass)
2259 					index = prepare_print_string(out_buf,
2260 						",Sensor Cm Validation - Gradient Cols,PASS,",
2261 						index);
2262 				else
2263 					index = prepare_print_string(out_buf,
2264 						",Sensor Cm Validation - Gradient Cols,FAIL,",
2265 						index);
2266 				index = prepare_print_string(out_buf,
2267 					"\n", index);
2268 
2269 				/*print Cm Validation -Gradient Rows*/
2270 				index = print_silicon_id(out_buf,
2271 					&device_id[0], index);
2272 				if (result->cm_sensor_gd_row_pass)
2273 					index = prepare_print_string(out_buf,
2274 						",Sensor Cm Validation - Gradient Rows,PASS,",
2275 						index);
2276 				else
2277 					index = prepare_print_string(out_buf,
2278 						",Sensor Cm Validation - Gradient Rows,FAIL,",
2279 						index);
2280 				index = prepare_print_string(out_buf,
2281 					"\n", index);
2282 
2283 
2284 				/*
2285 				 * Print Sensor Cm Validation
2286 				 * -Rows Delta Matrix
2287 				 */
2288 				index = print_silicon_id(out_buf,
2289 					&device_id[0], index);
2290 				if (result->cm_sensor_row_delta_pass)
2291 					index = prepare_print_string(out_buf,
2292 					",Sensor Cm Validation - Rows Delta Matrix,PASS,LIMITS,",
2293 					index);
2294 				else
2295 					index = prepare_print_string(out_buf,
2296 					",Sensor Cm Validation - Rows Delta Matrix,FAIL,LIMITS,",
2297 					index);
2298 				index = prepare_print_data(out_buf,
2299 					&configuration->cm_range_limit_row,
2300 					index, 1);
2301 				index = prepare_print_string(out_buf,
2302 					"\n", index);
2303 
2304 				/*print Cm_sensor_avg */
2305 				index = print_silicon_id(out_buf,
2306 					&device_id[0], index);
2307 				index = prepare_print_string(out_buf,
2308 					",Sensor Cm Validation - Sensor Range,Cm_sensor_avg,",
2309 					index);
2310 				index = prepare_print_data(out_buf,
2311 					&cmcp_info->cm_ave_data_panel,
2312 					index, 1);
2313 				index = prepare_print_string(out_buf,
2314 					"\n", index);
2315 
2316 				/*printSensor Cm Validation -
2317 				* Sensor Range,   Sensor Range
2318 				*/
2319 				index = print_silicon_id(out_buf,
2320 					&device_id[0], index);
2321 				index = prepare_print_string(out_buf,
2322 					",Sensor Cm Validation - Sensor Range,Sensor Range,",
2323 					index);
2324 				scnprintf(tmp_buf, 10, "%d.%d,",
2325 					cmcp_info->cm_sensor_delta / 10,
2326 					cmcp_info->cm_sensor_delta % 10);
2327 				index = prepare_print_string(out_buf,
2328 					&tmp_buf[0], index);
2329 				index = prepare_print_string(out_buf,
2330 					"\n", index);
2331 
2332 				/*print Sensor Cm Validation - Sensor Range*/
2333 				index = print_silicon_id(out_buf,
2334 					&device_id[0], index);
2335 				if (result->cm_sensor_delta_pass)
2336 					index = prepare_print_string(out_buf,
2337 						",Sensor Cm Validation - Sensor Range,PASS,LIMITS,",
2338 						index);
2339 				else
2340 					index = prepare_print_string(out_buf,
2341 						",Sensor Cm Validation - Sensor Range,FAIL,LIMITS,",
2342 						index);
2343 				index = prepare_print_data(out_buf,
2344 				&configuration->cm_max_delta_sensor_percent,
2345 						index, 1);
2346 				index = prepare_print_string(out_buf,
2347 					"\n", index);
2348 			}
2349 		}
2350 	}
2351 
2352 	if ((test_item & CP_ENABLED) == CP_ENABLED) {
2353 		if (((test_item & CP_BTN) == CP_BTN) && (btn_num > 0)) {
2354 			/*print   BUTNS_CP_DATA_ROW00  */
2355 			index = print_silicon_id(out_buf, &device_id[0], index);
2356 			index = prepare_print_string(out_buf,
2357 			",Self-cap Calibration Check,BUTNS_CP_DATA_ROW00,",
2358 				index);
2359 			index = prepare_print_data(out_buf,
2360 				&cmcp_info->cp_btn_data[0],
2361 				index, btn_num);
2362 			index = prepare_print_string(out_buf,
2363 				"\n", index);
2364 
2365 			if (!no_builtin_file && !dad->cmcp_range_check) {
2366 				/*print Cp Button Element by Element */
2367 				index = print_silicon_id(out_buf, &device_id[0],
2368 					index);
2369 				if (result->cp_button_validation_pass)
2370 					index = prepare_print_string(out_buf,
2371 					",Self-cap Calibration Check - Button Element by Element,PASS\n",
2372 					index);
2373 				else
2374 					index = prepare_print_string(out_buf,
2375 					",Self-cap Calibration Check - Button Element by Element,FAIL\n",
2376 					index);
2377 
2378 				/*print   cp_button_ave  */
2379 				index = print_silicon_id(out_buf,
2380 					&device_id[0], index);
2381 				index = prepare_print_string(out_buf,
2382 				",Self-cap Calibration Check,Cp_button_avg,",
2383 					index);
2384 				index = prepare_print_data(out_buf,
2385 					&cmcp_info->cp_button_ave,
2386 					index, 1);
2387 				index = prepare_print_string(out_buf,
2388 					"\n", index);
2389 
2390 				/*print   Cp_button_cal  */
2391 				index = print_silicon_id(out_buf,
2392 					&device_id[0], index);
2393 				index = prepare_print_string(out_buf,
2394 				",Self-cap Calibration Check,Cp_button_cal,",
2395 					index);
2396 				index = prepare_print_data(out_buf,
2397 					&cmcp_info->cp_btn_cal,
2398 					index, 1);
2399 				index = prepare_print_string(out_buf,
2400 					"\n", index);
2401 			}
2402 		}
2403 
2404 		if ((test_item & CP_PANEL) == CP_PANEL) {
2405 			/*print CP_DATA_RX */
2406 			index = print_silicon_id(out_buf, &device_id[0], index);
2407 			index = prepare_print_string(out_buf,
2408 			",Self-cap Calibration Check,CP_DATA_RX,", index);
2409 			index = prepare_print_data(out_buf,
2410 				&cmcp_info->cp_rx_data_panel[0], index, rx_num);
2411 			index = prepare_print_string(out_buf, "\n", index);
2412 
2413 			/*print CP_DATA_TX */
2414 			index = print_silicon_id(out_buf, &device_id[0], index);
2415 			index = prepare_print_string(out_buf,
2416 			",Self-cap Calibration Check,CP_DATA_TX,", index);
2417 			index = prepare_print_data(out_buf,
2418 				&cmcp_info->cp_tx_data_panel[0], index, tx_num);
2419 			index = prepare_print_string(out_buf, "\n", index);
2420 		}
2421 		if (((test_item & CP_BTN) == CP_BTN) && (btn_num > 0)
2422 			&& !dad->cmcp_range_check) {
2423 			if (!no_builtin_file) {
2424 				char tmp_buf[10] = {0};
2425 				/*print  Cp_delta_button */
2426 				index = print_silicon_id(out_buf, &device_id[0],
2427 					index);
2428 				index = prepare_print_string(out_buf,
2429 				",Self-cap Calibration Check,Cp_delta_button,",
2430 				index);
2431 				scnprintf(tmp_buf, 10, "%d.%d,",
2432 				cmcp_info->cp_button_delta / 10,
2433 				cmcp_info->cp_button_delta % 10);
2434 				index = prepare_print_string(out_buf,
2435 						&tmp_buf[0], index);
2436 				index = prepare_print_string(out_buf, "\n",
2437 					index);
2438 			}
2439 		}
2440 		if ((test_item & CP_PANEL) == CP_PANEL &&
2441 			!dad->cmcp_range_check) {
2442 			if (!no_builtin_file) {
2443 				char tmp_buf[10] = {0};
2444 				/*print Cp_delta_rx */
2445 				index = print_silicon_id(out_buf, &device_id[0],
2446 					index);
2447 				index = prepare_print_string(out_buf,
2448 				",Self-cap Calibration Check,Cp_delta_rx,",
2449 				index);
2450 				scnprintf(tmp_buf, 10, "%d.%d,",
2451 				cmcp_info->cp_sensor_rx_delta / 10,
2452 				cmcp_info->cp_sensor_rx_delta % 10);
2453 				index = prepare_print_string(out_buf,
2454 						&tmp_buf[0], index);
2455 				index = prepare_print_string(out_buf, "\n",
2456 					index);
2457 
2458 				/*print Cp_delta_tx */
2459 				index = print_silicon_id(out_buf, &device_id[0],
2460 					index);
2461 				index = prepare_print_string(out_buf,
2462 				",Self-cap Calibration Check,Cp_delta_tx,",
2463 					index);
2464 				scnprintf(tmp_buf, 10, "%d.%d,",
2465 				cmcp_info->cp_sensor_tx_delta / 10,
2466 				cmcp_info->cp_sensor_tx_delta % 10);
2467 				index = prepare_print_string(out_buf,
2468 						&tmp_buf[0], index);
2469 				index = prepare_print_string(out_buf, "\n",
2470 					index);
2471 
2472 				/*print Cp_sensor_avg_rx */
2473 				index = print_silicon_id(out_buf, &device_id[0],
2474 					index);
2475 				index = prepare_print_string(out_buf,
2476 				",Self-cap Calibration Check,Cp_sensor_avg_rx,",
2477 					index);
2478 				index = prepare_print_data(out_buf,
2479 					&cmcp_info->cp_rx_ave_data_panel,
2480 					index, 1);
2481 				index = prepare_print_string(out_buf,
2482 					"\n", index);
2483 
2484 				/*print Cp_sensor_avg_tx */
2485 				index = print_silicon_id(out_buf,
2486 					&device_id[0], index);
2487 				index = prepare_print_string(out_buf,
2488 				",Self-cap Calibration Check,Cp_sensor_avg_tx,",
2489 					index);
2490 				index = prepare_print_data(out_buf,
2491 					&cmcp_info->cp_tx_ave_data_panel,
2492 					index, 1);
2493 				index = prepare_print_string(out_buf,
2494 					"\n", index);
2495 
2496 				/*print Cp_sensor_cal_rx */
2497 				index = print_silicon_id(out_buf,
2498 					&device_id[0], index);
2499 				index = prepare_print_string(out_buf,
2500 				",Self-cap Calibration Check,Cp_sensor_cal_rx,",
2501 					index);
2502 				index = prepare_print_data(out_buf,
2503 					&cmcp_info->cp_rx_cal_data_panel[0],
2504 					index, rx_num);
2505 				index = prepare_print_string(out_buf,
2506 					"\n", index);
2507 
2508 				/*print Cp_sensor_cal_tx */
2509 				index = print_silicon_id(out_buf,
2510 					&device_id[0], index);
2511 				index = prepare_print_string(out_buf,
2512 				",Self-cap Calibration Check,Cp_sensor_cal_tx,",
2513 					index);
2514 				index = prepare_print_data(out_buf,
2515 					&cmcp_info->cp_tx_cal_data_panel[0],
2516 					index, tx_num);
2517 				index = prepare_print_string(out_buf,
2518 					"\n", index);
2519 			}
2520 		}
2521 
2522 		if (!no_builtin_file && !dad->cmcp_range_check) {
2523 			/*print  cp test limits  */
2524 			index = print_silicon_id(out_buf, &device_id[0], index);
2525 			if (result->cp_test_pass)
2526 				index = prepare_print_string(out_buf,
2527 				",Self-cap Calibration Check,PASS, LIMITS,",
2528 				index);
2529 			else
2530 				index = prepare_print_string(out_buf,
2531 				",Self-cap Calibration Check,FAIL, LIMITS,",
2532 				index);
2533 
2534 			index = prepare_print_string(out_buf,
2535 				"CP_MAX_DELTA_SENSOR_RX_PERCENT,", index);
2536 			index = prepare_print_data(out_buf,
2537 				&configuration->cp_max_delta_sensor_rx_percent,
2538 				index, 1);
2539 			index = prepare_print_string(out_buf,
2540 				"CP_MAX_DELTA_SENSOR_TX_PERCENT,", index);
2541 			index = prepare_print_data(out_buf,
2542 				&configuration->cp_max_delta_sensor_tx_percent,
2543 				index, 1);
2544 			index = prepare_print_string(out_buf,
2545 				"CP_MAX_DELTA_BUTTON_PERCENT,", index);
2546 			index = prepare_print_data(out_buf,
2547 				&configuration->cp_max_delta_button_percent,
2548 				index, 1);
2549 			index = prepare_print_string(out_buf, "\n", index);
2550 		}
2551 	}
2552 
2553 	if (!no_builtin_file) {
2554 		if ((test_item & CM_ENABLED) == CM_ENABLED) {
2555 			if ((test_item & CM_PANEL) == CM_PANEL) {
2556 				/*print columns gradient limit*/
2557 				index = prepare_print_string(out_buf,
2558 			",Sensor Cm Validation,MAX_LIMITS,CM_MAX_GRADIENT_COLS_PERCENT,",
2559 					index);
2560 				index = prepare_print_data(out_buf,
2561 			&configuration->cm_max_table_gradient_cols_percent[0],
2562 					index,
2563 			configuration->cm_max_table_gradient_cols_percent_size);
2564 				index = prepare_print_string(out_buf,
2565 					"\n", index);
2566 				/*print rows gradient limit*/
2567 				index = prepare_print_string(out_buf,
2568 			",Sensor Cm Validation,MAX_LIMITS,CM_MAX_GRADIENT_ROWS_PERCENT,",
2569 					index);
2570 				index = prepare_print_data(out_buf,
2571 			&configuration->cm_max_table_gradient_rows_percent[0],
2572 					index,
2573 			configuration->cm_max_table_gradient_rows_percent_size);
2574 				index = prepare_print_string(out_buf,
2575 					"\n", index);
2576 
2577 				/*print cm max limit*/
2578 				for (i = 0; i < rx_num; i++) {
2579 					index = prepare_print_string(out_buf,
2580 						",Sensor Cm Validation,MAX_LIMITS,CM_DATA_ROW",
2581 						index);
2582 					index = prepare_print_data(out_buf,
2583 						&i, index, 1);
2584 					for (j = 0; j < tx_num; j++)
2585 						index = prepare_print_data(
2586 							out_buf,
2587 		&configuration->cm_min_max_table_sensor[i*tx_num*2+j*2+1],
2588 							index, 1);
2589 					index = prepare_print_string(out_buf,
2590 						"\n", index);
2591 				}
2592 			}
2593 
2594 			if (((test_item & CM_BTN) == CM_BTN) && (btn_num > 0)) {
2595 				index = prepare_print_string(out_buf,
2596 					",Sensor Cm Validation,MAX LIMITS,M_BUTNS,",
2597 					index);
2598 				for (j = 0; j < btn_num; j++) {
2599 					index = prepare_print_data(out_buf,
2600 				&configuration->cm_min_max_table_button[2*j+1],
2601 						index, 1);
2602 				}
2603 				index = prepare_print_string(out_buf,
2604 					"\n", index);
2605 			}
2606 
2607 			index = prepare_print_string(out_buf,
2608 				 ",Sensor Cm Validation MAX LIMITS\n", index);
2609 
2610 			if ((test_item & CM_PANEL) == CM_PANEL) {
2611 				/*print cm min limit*/
2612 				for (i = 0; i < rx_num; i++) {
2613 					index = prepare_print_string(out_buf,
2614 						",Sensor Cm Validation,MIN_LIMITS,CM_DATA_ROW",
2615 						index);
2616 					index = prepare_print_data(out_buf, &i,
2617 						index, 1);
2618 					for (j = 0; j < tx_num; j++)
2619 						index = prepare_print_data(
2620 							out_buf,
2621 		&configuration->cm_min_max_table_sensor[i*tx_num*2 + j*2],
2622 							index, 1);
2623 					index = prepare_print_string(out_buf,
2624 						"\n", index);
2625 				}
2626 			}
2627 
2628 			if (((test_item & CM_BTN) == CM_BTN) && (btn_num > 0)) {
2629 				index = prepare_print_string(out_buf,
2630 					",Sensor Cm Validation,MIN LIMITS,M_BUTNS,",
2631 					index);
2632 				for (j = 0; j < btn_num; j++) {
2633 					index = prepare_print_data(out_buf,
2634 				&configuration->cm_min_max_table_button[2*j],
2635 						 index, 1);
2636 				}
2637 				index = prepare_print_string(out_buf,
2638 					"\n", index);
2639 			}
2640 			index = prepare_print_string(out_buf,
2641 				",Sensor Cm Validation MIN LIMITS\n", index);
2642 		}
2643 
2644 		if ((test_item & CP_ENABLED) == CP_ENABLED) {
2645 			if ((test_item & CP_PANEL) == CP_PANEL) {
2646 				/*print cp tx max limit*/
2647 				index = prepare_print_string(out_buf,
2648 				",Self-cap Calibration Check,MAX_LIMITS,TX,",
2649 					index);
2650 				for (i = 0; i < tx_num; i++)
2651 					index = prepare_print_data(out_buf,
2652 				&configuration->cp_min_max_table_tx[i*2+1],
2653 						index, 1);
2654 				index = prepare_print_string(out_buf,
2655 					"\n", index);
2656 
2657 				/*print cp rx max limit*/
2658 				index = prepare_print_string(out_buf,
2659 				",Self-cap Calibration Check,MAX_LIMITS,RX,",
2660 					index);
2661 				for (i = 0; i < rx_num; i++)
2662 					index = prepare_print_data(out_buf,
2663 				&configuration->cp_min_max_table_rx[i*2+1],
2664 						index, 1);
2665 				index = prepare_print_string(out_buf,
2666 					"\n", index);
2667 			}
2668 
2669 			/*print cp btn max limit*/
2670 			if (((test_item & CP_BTN) == CP_BTN) && (btn_num > 0)) {
2671 				index = prepare_print_string(out_buf,
2672 			",Self-cap Calibration Check,MAX_LIMITS,S_BUTNS,",
2673 					index);
2674 				for (i = 0; i < btn_num; i++)
2675 					index = prepare_print_data(out_buf,
2676 				&configuration->cp_min_max_table_button[i*2+1],
2677 						index, 1);
2678 				index = prepare_print_string(out_buf,
2679 						"\n", index);
2680 			}
2681 
2682 			if ((test_item & CP_PANEL) == CP_PANEL) {
2683 				/*print cp tx min limit*/
2684 				index = prepare_print_string(out_buf,
2685 				",Self-cap Calibration Check,MIN_LIMITS,TX,",
2686 					index);
2687 				for (i = 0; i < tx_num; i++)
2688 					index = prepare_print_data(out_buf,
2689 				&configuration->cp_min_max_table_tx[i*2],
2690 						index, 1);
2691 				index = prepare_print_string(out_buf,
2692 					"\n", index);
2693 
2694 				/*print cp rx min limit*/
2695 				index = prepare_print_string(out_buf,
2696 				",Self-cap Calibration Check,MIN_LIMITS,RX,",
2697 					index);
2698 				for (i = 0; i < rx_num; i++)
2699 					index = prepare_print_data(out_buf,
2700 				&configuration->cp_min_max_table_rx[i*2],
2701 						index, 1);
2702 				index = prepare_print_string(out_buf,
2703 					"\n", index);
2704 			}
2705 
2706 			/*print cp btn min limit*/
2707 			if (((test_item & CP_BTN) == CP_BTN) && (btn_num > 0)) {
2708 				index = prepare_print_string(out_buf,
2709 			",Self-cap Calibration Check,MIN_LIMITS,S_BUTNS,",
2710 					index);
2711 				for (i = 0; i < btn_num; i++)
2712 					index = prepare_print_data(out_buf,
2713 				&configuration->cp_min_max_table_button[i*2],
2714 						index, 1);
2715 				index = prepare_print_string(out_buf,
2716 						"\n", index);
2717 			}
2718 		}
2719 	}
2720 	return index;
2721 }
2722 
result_save(struct device * dev,char * buf,struct configuration * configuration,struct result * result,struct cmcp_data * cmcp_info,loff_t * ppos,size_t count,int test_item,int no_builtin_file)2723 static int result_save(struct device *dev, char *buf,
2724 	struct configuration *configuration, struct result *result,
2725 	struct cmcp_data *cmcp_info, loff_t *ppos, size_t count, int test_item,
2726 	int no_builtin_file)
2727 {
2728 	u8 *out_buf = NULL;
2729 	int index = 0;
2730 	int byte_left;
2731 
2732 	out_buf = kzalloc(MAX_BUF_LEN, GFP_KERNEL);
2733 	if (configuration == NULL)
2734 		dev_err(dev, "config is NULL");
2735 	if (result == NULL)
2736 		dev_err(dev, "result is NULL");
2737 	if (cmcp_info == NULL)
2738 		dev_err(dev, "cmcp_info is NULL");
2739 
2740 	index = save_header(out_buf, index, result);
2741 	index = save_engineering_data(dev, out_buf, index,
2742 		cmcp_info, configuration, result,
2743 		test_item, no_builtin_file);
2744 	byte_left = simple_read_from_buffer(buf, count, ppos, out_buf, index);
2745 
2746 	kfree(out_buf);
2747 	return byte_left;
2748 }
2749 
cmcp_results_debugfs_open(struct inode * inode,struct file * filp)2750 static int cmcp_results_debugfs_open(struct inode *inode,
2751 		struct file *filp)
2752 {
2753 	filp->private_data = inode->i_private;
2754 	return 0;
2755 }
2756 
cmcp_results_debugfs_close(struct inode * inode,struct file * filp)2757 static int cmcp_results_debugfs_close(struct inode *inode,
2758 		struct file *filp)
2759 {
2760 	filp->private_data = NULL;
2761 	return 0;
2762 }
2763 
cmcp_results_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)2764 static ssize_t cmcp_results_debugfs_read(struct file *filp,
2765 		char __user *buf, size_t count, loff_t *ppos)
2766 {
2767 	struct cyttsp5_device_access_data *dad = filp->private_data;
2768 	struct device *dev;
2769 	struct cmcp_data *cmcp_info = dad->cmcp_info;
2770 	struct result *result = dad->result;
2771 	struct configuration *configuration = dad->configs;
2772 	int ret = 0;
2773 	int test_item;
2774 	int no_builtin_file = 0;
2775 	int test_executed = 0;
2776 
2777 	dev = dad->dev;
2778 
2779 	mutex_lock(&dad->sysfs_lock);
2780 	test_executed = dad->test_executed;
2781 	test_item = cyttsp5_cmcp_get_test_item(dad->cmcp_test_items);
2782 	if (dad->builtin_cmcp_threshold_status < 0) {
2783 		dev_err(dev, "%s: No cmcp threshold file.\n", __func__);
2784 		no_builtin_file = 1;
2785 	}
2786 	mutex_unlock(&dad->sysfs_lock);
2787 
2788 	if (test_executed)
2789 		/*save result to buf*/
2790 		ret = result_save(dev, buf, configuration, result, cmcp_info,
2791 			ppos, count, test_item, no_builtin_file);
2792 	else {
2793 		char warning_info[] =
2794 		"No test result available!\n";
2795 		dev_err(dev, "%s: No test result available!\n", __func__);
2796 
2797 		return simple_read_from_buffer(buf, count, ppos, warning_info,
2798 			strlen(warning_info));
2799 	}
2800 
2801 	return ret;
2802 }
2803 
2804 static const struct file_operations cmcp_results_debugfs_fops = {
2805 	.open = cmcp_results_debugfs_open,
2806 	.release = cmcp_results_debugfs_close,
2807 	.read = cmcp_results_debugfs_read,
2808 	.write = NULL,
2809 };
2810 
cyttsp5_cmcp_threshold_loading_show(struct device * dev,struct device_attribute * attr,char * buf)2811 static ssize_t cyttsp5_cmcp_threshold_loading_show(struct device *dev,
2812 		struct device_attribute *attr, char *buf)
2813 {
2814 	struct cyttsp5_device_access_data *dad
2815 		= cyttsp5_get_device_access_data(dev);
2816 	bool cmcp_threshold_loading;
2817 
2818 	mutex_lock(&dad->cmcp_threshold_lock);
2819 	cmcp_threshold_loading = dad->cmcp_threshold_loading;
2820 	mutex_unlock(&dad->cmcp_threshold_lock);
2821 
2822 	return sprintf(buf, "%d\n", cmcp_threshold_loading);
2823 }
2824 
2825 /* Return the buffer offset of new test case */
cmcp_return_offset_of_new_case(const char * bufPtr,u32 first_time)2826 static u32 cmcp_return_offset_of_new_case(const char *bufPtr, u32 first_time)
2827 {
2828 	static u32 offset, first_search;
2829 
2830 	if (first_time == 0) {
2831 		first_search = 0;
2832 		offset = 0;
2833 	}
2834 
2835 	if (first_search != 0) {
2836 		/* Search one case */
2837 		for (;;) {
2838 			/* Search ASCII_LF */
2839 			while (*bufPtr++ != ASCII_LF)
2840 				offset++;
2841 
2842 			offset++;
2843 			/*
2844 			 * Single line: end loop
2845 			 * Multiple lines: continue loop
2846 			 */
2847 			if (*bufPtr != ASCII_COMMA)
2848 				break;
2849 		}
2850 	} else
2851 		first_search = 1;
2852 
2853 	return offset;
2854 }
2855 
2856 /* Get test case information from cmcp threshold file */
cmcp_get_case_info_from_threshold_file(struct device * dev,const char * buf,struct test_case_search * search_array,u32 file_size)2857 static u32 cmcp_get_case_info_from_threshold_file(struct device *dev, const char *buf,
2858 		struct test_case_search *search_array, u32 file_size)
2859 {
2860 	u32 case_num = 0, buffer_offset = 0, name_count = 0, first_search = 0;
2861 
2862 	parade_debug(dev, DEBUG_LEVEL_2, "%s: Search cmcp threshold file\n",
2863 		__func__);
2864 
2865 	/* Get all the test cases */
2866 	for (case_num = 0; case_num < MAX_CASE_NUM; case_num++) {
2867 		buffer_offset =
2868 			cmcp_return_offset_of_new_case(&buf[buffer_offset],
2869 			first_search);
2870 		first_search = 1;
2871 
2872 		if (buf[buffer_offset] == 0)
2873 			break;
2874 
2875 		for (name_count = 0; name_count < NAME_SIZE_MAX; name_count++) {
2876 			/* File end */
2877 			if (buf[buffer_offset + name_count] == ASCII_COMMA)
2878 				break;
2879 
2880 			search_array[case_num].name[name_count] =
2881 					buf[buffer_offset + name_count];
2882 		}
2883 
2884 		/* Exit when buffer offset is larger than file size */
2885 		if (buffer_offset >= file_size)
2886 			break;
2887 
2888 		search_array[case_num].name_size = name_count;
2889 		search_array[case_num].offset = buffer_offset;
2890 		/*
2891 		 *  parade_debug(dev, DEBUG_LEVEL_2, "Find case %d: Name is %s;
2892 		 *  Name size is %d; Case offset is %d\n",
2893 		 *	case_num,
2894 		 *	search_array[case_num].name,
2895 		 *	search_array[case_num].name_size,
2896 		 *	search_array[case_num].offset);
2897 		 */
2898 	}
2899 
2900 	return case_num;
2901 }
2902 
2903 /* Compose one value based on data of each bit */
cmcp_compose_data(char * buf,u32 count)2904 static int cmcp_compose_data(char *buf, u32 count)
2905 {
2906 	u32 base_array[] = {1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9};
2907 	int value = 0;
2908 	u32 index = 0;
2909 
2910 	for (index = 0; index < count; index++)
2911 		value += buf[index] * base_array[count - 1 - index];
2912 
2913 	return value;
2914 }
2915 
2916 /* Return one value */
cmcp_return_one_value(struct device * dev,const char * buf,u32 * offset,u32 * line_num)2917 static int cmcp_return_one_value(struct device *dev,
2918 		const char *buf, u32 *offset, u32 *line_num)
2919 {
2920 	int value = -1;
2921 	char tmp_buffer[10];
2922 	u32 count = 0;
2923 	u32 tmp_offset = *offset;
2924 	static u32 line_count = 1;
2925 
2926 	/* Bypass extra commas */
2927 	while (buf[tmp_offset] == ASCII_COMMA
2928 			&& buf[tmp_offset + 1] == ASCII_COMMA)
2929 		tmp_offset++;
2930 
2931 	/* Windows and Linux difference at the end of one line */
2932 	if (buf[tmp_offset] == ASCII_COMMA
2933 			&& buf[tmp_offset + 1] == ASCII_CR
2934 			&& buf[tmp_offset + 2] == ASCII_LF)
2935 		tmp_offset += 2;
2936 	else if (buf[tmp_offset] == ASCII_COMMA
2937 			&& buf[tmp_offset + 1] == ASCII_LF)
2938 		tmp_offset += 1;
2939 	else if (buf[tmp_offset] == ASCII_COMMA
2940 			&& buf[tmp_offset + 1] == ASCII_CR)
2941 		tmp_offset += 1;
2942 
2943 	/* New line for multiple lines */
2944 	if (buf[tmp_offset] == ASCII_LF && buf[tmp_offset + 1] == ASCII_COMMA) {
2945 		tmp_offset++;
2946 		line_count++;
2947 		/*parade_debug(dev, DEBUG_LEVEL_2, "\n");*/
2948 	}
2949 
2950 	/* Beginning */
2951 	if (buf[tmp_offset] == ASCII_COMMA) {
2952 		tmp_offset++;
2953 		for (;;) {
2954 			if ((buf[tmp_offset] >= ASCII_ZERO)
2955 			&& (buf[tmp_offset] <= ASCII_NINE)) {
2956 				tmp_buffer[count++] =
2957 				buf[tmp_offset] - ASCII_ZERO;
2958 				tmp_offset++;
2959 			} else {
2960 				if (count != 0) {
2961 					value = cmcp_compose_data(tmp_buffer,
2962 					count);
2963 					/*parade_debug(dev, DEBUG_LEVEL_2, */
2964 					/* ",%d", value);*/
2965 				} else {
2966 					/* 0 indicates no data available */
2967 					value = -1;
2968 				}
2969 				break;
2970 			}
2971 		}
2972 	} else {
2973 		/* Multiple line: line count */
2974 		*line_num = line_count;
2975 		/* Reset for next case */
2976 		line_count = 1;
2977 	}
2978 
2979 	*offset = tmp_offset;
2980 
2981 	return value;
2982 }
2983 
2984 /* Get configuration information */
cmcp_get_configuration_info(struct device * dev,const char * buf,struct test_case_search * search_array,u32 case_count,struct test_case_field * field_array,struct configuration * config)2985 static void cmcp_get_configuration_info(struct device *dev,
2986 		const char *buf, struct test_case_search *search_array,
2987 		u32 case_count, struct test_case_field *field_array,
2988 		struct configuration *config)
2989 {
2990 	u32 count = 0, sub_count = 0;
2991 	u32 exist_or_not = 0;
2992 	u32 value_offset = 0;
2993 	int retval = 0;
2994 	u32 data_num = 0;
2995 	u32 line_num = 1;
2996 
2997 	parade_debug(dev, DEBUG_LEVEL_2,
2998 		"%s: Fill configuration struct per cmcp threshold file\n",
2999 		__func__);
3000 
3001 	/* Search cases */
3002 	for (count = 0; count < MAX_CASE_NUM; count++) {
3003 		exist_or_not = 0;
3004 		for (sub_count = 0; sub_count < case_count; sub_count++) {
3005 			if (!strncmp(field_array[count].name,
3006 					search_array[sub_count].name,
3007 					field_array[count].name_size)) {
3008 				exist_or_not = 1;
3009 				break;
3010 			}
3011 		}
3012 
3013 		field_array[count].exist_or_not = exist_or_not;
3014 
3015 		/* Clear data number */
3016 		data_num = 0;
3017 
3018 		if (exist_or_not == 1) {
3019 			switch (field_array[count].type) {
3020 			case TEST_CASE_TYPE_NO:
3021 				field_array[count].data_num = 0;
3022 				field_array[count].line_num = 1;
3023 				break;
3024 			case TEST_CASE_TYPE_ONE:
3025 				value_offset = search_array[sub_count].offset
3026 					+ search_array[sub_count].name_size;
3027 				*field_array[count].bufptr =
3028 						cmcp_return_one_value(dev, buf,
3029 						&value_offset, 0);
3030 				field_array[count].data_num = 1;
3031 				field_array[count].line_num = 1;
3032 				break;
3033 			case TEST_CASE_TYPE_MUL:
3034 			case TEST_CASE_TYPE_MUL_LINES:
3035 				line_num = 1;
3036 				value_offset = search_array[sub_count].offset
3037 					+ search_array[sub_count].name_size;
3038 				for (;;) {
3039 					retval = cmcp_return_one_value(dev,
3040 						buf, &value_offset, &line_num);
3041 					if (retval >= 0) {
3042 						*field_array[count].bufptr++ =
3043 						retval;
3044 						data_num++;
3045 					} else
3046 						break;
3047 				}
3048 
3049 				field_array[count].data_num = data_num;
3050 				field_array[count].line_num = line_num;
3051 				break;
3052 			default:
3053 				break;
3054 			}
3055 			parade_debug(dev, DEBUG_LEVEL_2,
3056 				"%s: %s: Data number is %d, line number is %d\n",
3057 				__func__,
3058 				field_array[count].name,
3059 				field_array[count].data_num,
3060 				field_array[count].line_num);
3061 		} else
3062 			parade_debug(dev, DEBUG_LEVEL_2, "%s: !!! %s doesn't exist\n",
3063 				__func__, field_array[count].name);
3064 	}
3065 }
3066 
3067 /* Get basic information, like tx, rx, button number */
cmcp_get_basic_info(struct device * dev,struct test_case_field * field_array,struct configuration * config)3068 static void cmcp_get_basic_info(struct device *dev,
3069 	struct test_case_field *field_array, struct configuration *config)
3070 {
3071 #define CMCP_DEBUG 0
3072 	u32 tx_num = 0;
3073 #if CMCP_DEBUG
3074 	u32 index = 0;
3075 #endif
3076 
3077 	config->is_valid_or_not = 1; /* Set to valid by default */
3078 	config->cm_enabled = 0;
3079 	config->cp_enabled = 0;
3080 
3081 	if (field_array[CM_TEST_INPUTS].exist_or_not)
3082 		config->cm_enabled = 1;
3083 	if (field_array[CP_TEST_INPUTS].exist_or_not)
3084 		config->cp_enabled = 1;
3085 
3086 	/* Get basic information only when CM and CP are enabled */
3087 	if (config->cm_enabled && config->cp_enabled) {
3088 		parade_debug(dev, DEBUG_LEVEL_2,
3089 			"%s: Find CM and CP thresholds\n", __func__);
3090 
3091 		config->rx_num =
3092 			field_array[PER_ELEMENT_MIN_MAX_TABLE_SENSOR].line_num;
3093 		tx_num =
3094 		(field_array[PER_ELEMENT_MIN_MAX_TABLE_SENSOR].data_num >> 1)
3095 			/field_array[PER_ELEMENT_MIN_MAX_TABLE_SENSOR].line_num;
3096 		config->tx_num = tx_num;
3097 
3098 		config->btn_num =
3099 		field_array[PER_ELEMENT_MIN_MAX_TABLE_BUTTON].data_num >> 1;
3100 
3101 		config->cm_min_max_table_button_size =
3102 			field_array[PER_ELEMENT_MIN_MAX_TABLE_BUTTON].data_num;
3103 		config->cm_min_max_table_sensor_size =
3104 			field_array[PER_ELEMENT_MIN_MAX_TABLE_SENSOR].data_num;
3105 		config->cp_min_max_table_rx_size =
3106 			field_array[PER_ELEMENT_MIN_MAX_RX].data_num;
3107 		config->cp_min_max_table_tx_size =
3108 			field_array[PER_ELEMENT_MIN_MAX_TX].data_num;
3109 		config->cm_max_table_gradient_cols_percent_size =
3110 			field_array[CM_GRADIENT_CHECK_COL].data_num;
3111 		config->cm_max_table_gradient_rows_percent_size =
3112 			field_array[CM_GRADIENT_CHECK_ROW].data_num;
3113 		config->cp_min_max_table_button_size =
3114 			field_array[CP_PER_ELEMENT_MIN_MAX_BUTTON].data_num;
3115 
3116 #if CMCP_DEBUG
3117 		parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3118 					config->cm_excluding_col_edge);
3119 		parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3120 					config->cm_excluding_row_edge);
3121 		for (index = 0;
3122 		index < config->cm_max_table_gradient_cols_percent_size;
3123 		index++)
3124 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3125 			config->cm_max_table_gradient_cols_percent[index]);
3126 		for (index = 0;
3127 		index < config->cm_max_table_gradient_rows_percent_size;
3128 		index++)
3129 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3130 			config->cm_max_table_gradient_rows_percent[index]);
3131 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3132 				config->cm_range_limit_row);
3133 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3134 				config->cm_range_limit_col);
3135 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3136 				config->cm_min_limit_cal);
3137 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3138 				config->cm_max_limit_cal);
3139 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3140 				config->cm_max_delta_sensor_percent);
3141 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3142 				config->cm_max_delta_button_percent);
3143 		for (index = 0;
3144 		index < config->cm_min_max_table_button_size; index++)
3145 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3146 				config->cm_min_max_table_button[index]);
3147 		for (index = 0;
3148 			index < config->cm_min_max_table_sensor_size; index++)
3149 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3150 				config->cm_min_max_table_sensor[index]);
3151 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3152 				config->cp_max_delta_sensor_rx_percent);
3153 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3154 				config->cp_max_delta_sensor_tx_percent);
3155 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3156 				config->cp_max_delta_button_percent);
3157 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3158 				config->min_button);
3159 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3160 				config->max_button);
3161 
3162 		for (index = 0;
3163 		index < config->cp_min_max_table_button_size; index++)
3164 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3165 				config->cp_min_max_table_button[index]);
3166 		for (index = 0;
3167 		index < config->cp_min_max_table_rx_size; index++)
3168 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3169 				config->cp_min_max_table_rx[index]);
3170 		for (index = 0;
3171 		index < config->cp_min_max_table_tx_size; index++)
3172 			parade_debug(dev, DEBUG_LEVEL_2, "%d\n",
3173 				config->cp_min_max_table_tx[index]);
3174 #endif
3175 		/* Invalid mutual data length */
3176 		if ((field_array[PER_ELEMENT_MIN_MAX_TABLE_SENSOR].data_num >>
3177 		1) % field_array[PER_ELEMENT_MIN_MAX_TABLE_SENSOR].line_num) {
3178 			config->is_valid_or_not = 0;
3179 			parade_debug(dev, DEBUG_LEVEL_2, "Invalid mutual data length\n");
3180 		}
3181 	} else {
3182 		if (!config->cm_enabled)
3183 			parade_debug(dev, DEBUG_LEVEL_2,
3184 				"%s: Miss CM thresholds or CM data format is wrong!\n",
3185 				__func__);
3186 
3187 		if (!config->cp_enabled)
3188 			parade_debug(dev, DEBUG_LEVEL_2,
3189 				"%s: Miss CP thresholds or CP data format is wrong!\n",
3190 				__func__);
3191 
3192 		config->rx_num = 0;
3193 		config->tx_num = 0;
3194 		config->btn_num = 0;
3195 		config->is_valid_or_not = 0;
3196 	}
3197 
3198 	parade_debug(dev, DEBUG_LEVEL_2,
3199 		"%s:\n"
3200 		"Input file is %s!\n"
3201 		"CM test: %s\n"
3202 		"CP test: %s\n"
3203 		"rx_num is %d\n"
3204 		"tx_num is %d\n"
3205 		"btn_num is %d\n",
3206 		__func__,
3207 		config->is_valid_or_not == 1 ? "VALID" : "!!! INVALID !!!",
3208 		config->cm_enabled == 1 ? "Found" : "Not found",
3209 		config->cp_enabled == 1 ? "Found" : "Not found",
3210 		config->rx_num,
3211 		config->tx_num,
3212 		config->btn_num);
3213 }
3214 
cmcp_test_case_field_init(struct test_case_field * test_field_array,struct configuration * configs)3215 static void cmcp_test_case_field_init(struct test_case_field *test_field_array,
3216 	struct configuration *configs)
3217 {
3218 	struct test_case_field test_case_field_array[MAX_CASE_NUM] = {
3219 		{"CM TEST INPUTS", 14, TEST_CASE_TYPE_NO,
3220 				NULL, 0, 0, 0},
3221 		{"CM_EXCLUDING_COL_EDGE", 21, TEST_CASE_TYPE_ONE,
3222 				&configs->cm_excluding_col_edge, 0, 0, 0},
3223 		{"CM_EXCLUDING_ROW_EDGE", 21, TEST_CASE_TYPE_ONE,
3224 				&configs->cm_excluding_row_edge, 0, 0, 0},
3225 		{"CM_GRADIENT_CHECK_COL", 21, TEST_CASE_TYPE_MUL,
3226 				&configs->cm_max_table_gradient_cols_percent[0],
3227 				0, 0, 0},
3228 		{"CM_GRADIENT_CHECK_ROW", 21, TEST_CASE_TYPE_MUL,
3229 				&configs->cm_max_table_gradient_rows_percent[0],
3230 				0, 0, 0},
3231 		{"CM_RANGE_LIMIT_ROW", 18, TEST_CASE_TYPE_ONE,
3232 				&configs->cm_range_limit_row, 0, 0, 0},
3233 		{"CM_RANGE_LIMIT_COL", 18, TEST_CASE_TYPE_ONE,
3234 				&configs->cm_range_limit_col, 0, 0, 0},
3235 		{"CM_MIN_LIMIT_CAL", 16, TEST_CASE_TYPE_ONE,
3236 				&configs->cm_min_limit_cal, 0, 0, 0},
3237 		{"CM_MAX_LIMIT_CAL", 16, TEST_CASE_TYPE_ONE,
3238 				&configs->cm_max_limit_cal, 0, 0, 0},
3239 		{"CM_MAX_DELTA_SENSOR_PERCENT", 27, TEST_CASE_TYPE_ONE,
3240 				&configs->cm_max_delta_sensor_percent, 0, 0, 0},
3241 		{"CM_MAX_DELTA_BUTTON_PERCENT", 27, TEST_CASE_TYPE_ONE,
3242 				&configs->cm_max_delta_button_percent, 0, 0, 0},
3243 		{"PER_ELEMENT_MIN_MAX_TABLE_BUTTON", 32, TEST_CASE_TYPE_MUL,
3244 				&configs->cm_min_max_table_button[0], 0, 0, 0},
3245 		{"PER_ELEMENT_MIN_MAX_TABLE_SENSOR", 32,
3246 				TEST_CASE_TYPE_MUL_LINES,
3247 				&configs->cm_min_max_table_sensor[0], 0, 0, 0},
3248 		{"CP TEST INPUTS", 14, TEST_CASE_TYPE_NO,
3249 				NULL, 0, 0, 0},
3250 		{"CP_PER_ELEMENT_MIN_MAX_BUTTON", 29, TEST_CASE_TYPE_MUL,
3251 				&configs->cp_min_max_table_button[0], 0, 0, 0},
3252 		{"CP_MAX_DELTA_SENSOR_RX_PERCENT", 30, TEST_CASE_TYPE_ONE,
3253 				&configs->cp_max_delta_sensor_rx_percent,
3254 				0, 0, 0},
3255 		{"CP_MAX_DELTA_SENSOR_TX_PERCENT", 30, TEST_CASE_TYPE_ONE,
3256 				&configs->cp_max_delta_sensor_tx_percent,
3257 				0, 0, 0},
3258 		{"CP_MAX_DELTA_BUTTON_PERCENT", 27, TEST_CASE_TYPE_ONE,
3259 				&configs->cp_max_delta_button_percent, 0, 0, 0},
3260 		{"MIN_BUTTON", 10, TEST_CASE_TYPE_ONE,
3261 				&configs->min_button, 0, 0, 0},
3262 		{"MAX_BUTTON", 10, TEST_CASE_TYPE_ONE,
3263 				&configs->max_button, 0, 0, 0},
3264 		{"PER_ELEMENT_MIN_MAX_RX", 22, TEST_CASE_TYPE_MUL,
3265 				&configs->cp_min_max_table_rx[0], 0, 0, 0},
3266 		{"PER_ELEMENT_MIN_MAX_TX", 22, TEST_CASE_TYPE_MUL,
3267 				&configs->cp_min_max_table_tx[0], 0, 0, 0},
3268 	};
3269 
3270 	memcpy(test_field_array, test_case_field_array,
3271 		sizeof(struct test_case_field) * MAX_CASE_NUM);
3272 }
3273 
cyttsp5_parse_cmcp_threshold_file_common(struct device * dev,const char * buf,u32 file_size)3274 static ssize_t cyttsp5_parse_cmcp_threshold_file_common(
3275 	struct device *dev, const char *buf, u32 file_size)
3276 {
3277 	struct cyttsp5_device_access_data *dad
3278 		= cyttsp5_get_device_access_data(dev);
3279 	ssize_t rc = 0;
3280 	u32 case_count = 0;
3281 
3282 	parade_debug(dev, DEBUG_LEVEL_2,
3283 		"%s: Start parsing cmcp threshold file. File size is %d\n",
3284 		__func__, file_size);
3285 
3286 	cmcp_test_case_field_init(dad->test_field_array, dad->configs);
3287 
3288 	/* Get all the cases from .csv file */
3289 	case_count = cmcp_get_case_info_from_threshold_file(dev,
3290 		buf, dad->test_search_array, file_size);
3291 
3292 	/* Search cases */
3293 	cmcp_get_configuration_info(dev,
3294 		buf,
3295 		dad->test_search_array, case_count, dad->test_field_array,
3296 		dad->configs);
3297 
3298 	/* Get basic information */
3299 	cmcp_get_basic_info(dev, dad->test_field_array, dad->configs);
3300 
3301 	return rc;
3302 }
3303 
cyttsp5_cmcp_threshold_loading_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)3304 static ssize_t cyttsp5_cmcp_threshold_loading_store(struct device *dev,
3305 	struct device_attribute *attr, const char *buf, size_t size)
3306 {
3307 	struct cyttsp5_device_access_data *dad
3308 		= cyttsp5_get_device_access_data(dev);
3309 	long value;
3310 	int rc;
3311 
3312 	rc = kstrtol(buf, 10, &value);
3313 	if (rc < 0 || value < -1 || value > 1) {
3314 		dev_err(dev, "%s: Invalid value\n", __func__);
3315 		return size;
3316 	}
3317 
3318 	mutex_lock(&dad->cmcp_threshold_lock);
3319 
3320 	if (value == 1)
3321 		dad->cmcp_threshold_loading = true;
3322 	else if (value == -1)
3323 		dad->cmcp_threshold_loading = false;
3324 	else if (value == 0 && dad->cmcp_threshold_loading) {
3325 		dad->cmcp_threshold_loading = false;
3326 
3327 		if (dad->cmcp_threshold_size == 0) {
3328 			dev_err(dev, "%s: No cmcp threshold data\n", __func__);
3329 			goto exit_free;
3330 		}
3331 
3332 		/* Clear test executed flag */
3333 		dad->test_executed = 0;
3334 
3335 		cyttsp5_parse_cmcp_threshold_file_common(dev,
3336 			&dad->cmcp_threshold_data[0], dad->cmcp_threshold_size);
3337 
3338 		/* Mark valid */
3339 		dad->builtin_cmcp_threshold_status = 0;
3340 		/* Restore test item to default value when new file input */
3341 		dad->cmcp_test_items = 0;
3342 	}
3343 
3344 exit_free:
3345 	kfree(dad->cmcp_threshold_data);
3346 	dad->cmcp_threshold_data = NULL;
3347 	dad->cmcp_threshold_size = 0;
3348 
3349 	mutex_unlock(&dad->cmcp_threshold_lock);
3350 
3351 	if (rc)
3352 		return rc;
3353 
3354 	return size;
3355 }
3356 
3357 static DEVICE_ATTR(cmcp_threshold_loading, S_IRUSR | S_IWUSR,
3358 	cyttsp5_cmcp_threshold_loading_show,
3359 	cyttsp5_cmcp_threshold_loading_store);
3360 
3361 /*
3362 * cmcp threshold data write
3363 */
cyttsp5_cmcp_threshold_data_write(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t offset,size_t count)3364 static ssize_t cyttsp5_cmcp_threshold_data_write(struct file *filp,
3365 		struct kobject *kobj, struct bin_attribute *bin_attr,
3366 		char *buf, loff_t offset, size_t count)
3367 {
3368 	struct device *dev = container_of(kobj, struct device, kobj);
3369 	struct cyttsp5_device_access_data *dad
3370 		= cyttsp5_get_device_access_data(dev);
3371 	u8 *p;
3372 
3373 	parade_debug(dev, DEBUG_LEVEL_2, "%s: offset:%lld count:%zu\n",
3374 		__func__, offset, count);
3375 
3376 	mutex_lock(&dad->cmcp_threshold_lock);
3377 
3378 	if (!dad->cmcp_threshold_loading) {
3379 		mutex_unlock(&dad->cmcp_threshold_lock);
3380 		return -ENODEV;
3381 	}
3382 
3383 	p = krealloc(dad->cmcp_threshold_data, offset + count, GFP_KERNEL);
3384 	if (!p) {
3385 		kfree(dad->cmcp_threshold_data);
3386 		dad->cmcp_threshold_data = NULL;
3387 		mutex_unlock(&dad->cmcp_threshold_lock);
3388 		return -ENOMEM;
3389 	}
3390 	dad->cmcp_threshold_data = p;
3391 
3392 	memcpy(&dad->cmcp_threshold_data[offset], buf, count);
3393 	dad->cmcp_threshold_size += count;
3394 
3395 	mutex_unlock(&dad->cmcp_threshold_lock);
3396 
3397 	return count;
3398 }
3399 
3400 static struct bin_attribute bin_attr_cmcp_threshold_data = {
3401 	.attr = {
3402 		.name = "cmcp_threshold_data",
3403 		.mode = S_IWUSR,
3404 	},
3405 	.size = 0,
3406 	.write = cyttsp5_cmcp_threshold_data_write,
3407 };
3408 
3409 /*
3410  * Suspend scan command
3411  */
cyttsp5_suspend_scan_cmd_(struct device * dev)3412 static int cyttsp5_suspend_scan_cmd_(struct device *dev)
3413 {
3414 	int rc;
3415 
3416 	rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
3417 	if (rc < 0)
3418 		dev_err(dev, "%s: Suspend scan failed r=%d\n",
3419 			__func__, rc);
3420 	return rc;
3421 }
3422 
3423 /*
3424  * Resume scan command
3425  */
cyttsp5_resume_scan_cmd_(struct device * dev)3426 static int cyttsp5_resume_scan_cmd_(struct device *dev)
3427 {
3428 	int rc;
3429 
3430 	rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
3431 	if (rc < 0)
3432 		dev_err(dev, "%s: Resume scan failed r=%d\n",
3433 			__func__, rc);
3434 	return rc;
3435 }
3436 
3437 /*
3438  * Execute scan command
3439  */
cyttsp5_exec_scan_cmd_(struct device * dev)3440 static int cyttsp5_exec_scan_cmd_(struct device *dev)
3441 {
3442 	int rc;
3443 
3444 	rc = cmd->nonhid_cmd->exec_panel_scan(dev, 0);
3445 	if (rc < 0)
3446 		dev_err(dev, "%s: Heatmap start scan failed r=%d\n",
3447 			__func__, rc);
3448 	return rc;
3449 }
3450 
3451 /*
3452  * Retrieve panel data command
3453  */
cyttsp5_ret_scan_data_cmd_(struct device * dev,u16 read_offset,u16 read_count,u8 data_id,u8 * response,u8 * config,u16 * actual_read_len,u8 * return_buf)3454 static int cyttsp5_ret_scan_data_cmd_(struct device *dev, u16 read_offset,
3455 		u16 read_count, u8 data_id, u8 *response, u8 *config,
3456 		u16 *actual_read_len, u8 *return_buf)
3457 {
3458 	int rc;
3459 
3460 	rc = cmd->nonhid_cmd->retrieve_panel_scan(dev, 0, read_offset,
3461 			read_count, data_id, response, config, actual_read_len,
3462 			return_buf);
3463 	if (rc < 0)
3464 		dev_err(dev, "%s: Retrieve scan data failed r=%d\n",
3465 				__func__, rc);
3466 	return rc;
3467 }
3468 
3469 /*
3470  * Get data structure command
3471  */
cyttsp5_get_data_structure_cmd_(struct device * dev,u16 read_offset,u16 read_length,u8 data_id,u8 * status,u8 * data_format,u16 * actual_read_len,u8 * data)3472 static int cyttsp5_get_data_structure_cmd_(struct device *dev, u16 read_offset,
3473 		u16 read_length, u8 data_id, u8 *status, u8 *data_format,
3474 		u16 *actual_read_len, u8 *data)
3475 {
3476 	int rc;
3477 
3478 	rc = cmd->nonhid_cmd->get_data_structure(dev, 0, read_offset,
3479 			read_length, data_id, status, data_format,
3480 			actual_read_len, data);
3481 	if (rc < 0)
3482 		dev_err(dev, "%s: Get data structure failed r=%d\n",
3483 				__func__, rc);
3484 	return rc;
3485 }
3486 
3487 /*
3488  * Run self test command
3489  */
cyttsp5_run_selftest_cmd_(struct device * dev,u8 test_id,u8 write_idacs_to_flash,u8 * status,u8 * summary_result,u8 * results_available)3490 static int cyttsp5_run_selftest_cmd_(struct device *dev, u8 test_id,
3491 		u8 write_idacs_to_flash, u8 *status, u8 *summary_result,
3492 		u8 *results_available)
3493 {
3494 	int rc;
3495 
3496 	rc = cmd->nonhid_cmd->run_selftest(dev, 0, test_id,
3497 			write_idacs_to_flash, status, summary_result,
3498 			results_available);
3499 	if (rc < 0)
3500 		dev_err(dev, "%s: Run self test failed r=%d\n",
3501 				__func__, rc);
3502 	return rc;
3503 }
3504 
3505 /*
3506  * Get self test result command
3507  */
cyttsp5_get_selftest_result_cmd_(struct device * dev,u16 read_offset,u16 read_length,u8 test_id,u8 * status,u16 * actual_read_len,u8 * data)3508 static int cyttsp5_get_selftest_result_cmd_(struct device *dev,
3509 		u16 read_offset, u16 read_length, u8 test_id, u8 *status,
3510 		u16 *actual_read_len, u8 *data)
3511 {
3512 	int rc;
3513 
3514 	rc = cmd->nonhid_cmd->get_selftest_result(dev, 0, read_offset,
3515 			read_length, test_id, status, actual_read_len, data);
3516 	if (rc < 0)
3517 		dev_err(dev, "%s: Get self test result failed r=%d\n",
3518 				__func__, rc);
3519 	return rc;
3520 }
3521 
3522 /*
3523  * Calibrate IDACs command
3524  */
_cyttsp5_calibrate_idacs_cmd(struct device * dev,u8 sensing_mode,u8 * status)3525 static int _cyttsp5_calibrate_idacs_cmd(struct device *dev,
3526 		u8 sensing_mode, u8 *status)
3527 {
3528 	int rc;
3529 
3530 	rc = cmd->nonhid_cmd->calibrate_idacs(dev, 0, sensing_mode, status);
3531 	return rc;
3532 }
3533 
3534 /*
3535  * Initialize Baselines command
3536  */
_cyttsp5_initialize_baselines_cmd(struct device * dev,u8 sensing_mode,u8 * status)3537 static int _cyttsp5_initialize_baselines_cmd(struct device *dev,
3538 		u8 sensing_mode, u8 *status)
3539 {
3540 	int rc;
3541 
3542 	rc = cmd->nonhid_cmd->initialize_baselines(dev, 0, sensing_mode,
3543 			status);
3544 	return rc;
3545 }
3546 
prepare_print_buffer(int status,u8 * in_buf,int length,u8 * out_buf,size_t out_buf_size)3547 static int prepare_print_buffer(int status, u8 *in_buf, int length,
3548 		u8 *out_buf, size_t out_buf_size)
3549 {
3550 	int index = 0;
3551 	int i;
3552 
3553 	index += scnprintf(out_buf, out_buf_size, "status %d\n", status);
3554 
3555 	for (i = 0; i < length; i++) {
3556 		index += scnprintf(&out_buf[index], out_buf_size - index,
3557 				"%02X\n", in_buf[i]);
3558 	}
3559 
3560 	return index;
3561 }
cyttsp5_run_and_get_selftest_result_noprint(struct device * dev,char * buf,size_t buf_len,u8 test_id,u16 read_length,bool get_result_on_pass)3562 static ssize_t cyttsp5_run_and_get_selftest_result_noprint(struct device *dev,
3563 		char *buf, size_t buf_len, u8 test_id, u16 read_length,
3564 		bool get_result_on_pass)
3565 {
3566 	struct cyttsp5_device_access_data *dad
3567 		= cyttsp5_get_device_access_data(dev);
3568 	int status = STATUS_FAIL;
3569 	u8 cmd_status = 0;
3570 	u8 summary_result = 0;
3571 	u16 act_length = 0;
3572 	int length = 0;
3573 	int rc;
3574 
3575 	mutex_lock(&dad->sysfs_lock);
3576 
3577 	pm_runtime_get_sync(dev);
3578 
3579 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
3580 	if (rc < 0) {
3581 		dev_err(dev, "%s: Error on request exclusive r=%d\n",
3582 				__func__, rc);
3583 		goto put_pm_runtime;
3584 	}
3585 
3586 	rc = cyttsp5_suspend_scan_cmd_(dev);
3587 	if (rc < 0) {
3588 		dev_err(dev, "%s: Error on suspend scan r=%d\n",
3589 				__func__, rc);
3590 		goto release_exclusive;
3591 	}
3592 
3593 	rc = cyttsp5_run_selftest_cmd_(dev, test_id, 0,
3594 			&cmd_status, &summary_result, NULL);
3595 	if (rc < 0) {
3596 		dev_err(dev, "%s: Error on run self test for test_id:%d r=%d\n",
3597 				__func__, test_id, rc);
3598 		goto resume_scan;
3599 	}
3600 
3601 	/* Form response buffer */
3602 	dad->ic_buf[0] = cmd_status;
3603 	dad->ic_buf[1] = summary_result;
3604 
3605 	length = 2;
3606 
3607 	/* Get data if command status is success */
3608 	if (cmd_status != CY_CMD_STATUS_SUCCESS)
3609 		goto status_success;
3610 
3611 	/* Get data unless test result is pass */
3612 	if (summary_result == CY_ST_RESULT_PASS && !get_result_on_pass)
3613 		goto status_success;
3614 
3615 	rc = cyttsp5_get_selftest_result_cmd_(dev, 0, read_length,
3616 			test_id, &cmd_status, &act_length, &dad->ic_buf[6]);
3617 	if (rc < 0) {
3618 		dev_err(dev, "%s: Error on get self test result r=%d\n",
3619 				__func__, rc);
3620 		goto resume_scan;
3621 	}
3622 
3623 	dad->ic_buf[2] = cmd_status;
3624 	dad->ic_buf[3] = test_id;
3625 	dad->ic_buf[4] = LOW_BYTE(act_length);
3626 	dad->ic_buf[5] = HI_BYTE(act_length);
3627 
3628 	length = 6 + act_length;
3629 
3630 status_success:
3631 	status = STATUS_SUCCESS;
3632 
3633 resume_scan:
3634 	cyttsp5_resume_scan_cmd_(dev);
3635 
3636 release_exclusive:
3637 	cmd->release_exclusive(dev);
3638 
3639 put_pm_runtime:
3640 	pm_runtime_put(dev);
3641 	mutex_unlock(&dad->sysfs_lock);
3642 
3643 	return status;
3644 }
3645 
cyttsp5_run_and_get_selftest_result(struct device * dev,char * buf,size_t buf_len,u8 test_id,u16 read_length,bool get_result_on_pass)3646 static ssize_t cyttsp5_run_and_get_selftest_result(struct device *dev,
3647 		char *buf, size_t buf_len, u8 test_id, u16 read_length,
3648 		bool get_result_on_pass)
3649 {
3650 	struct cyttsp5_device_access_data *dad
3651 		= cyttsp5_get_device_access_data(dev);
3652 	int status = STATUS_FAIL;
3653 	u8 cmd_status = 0;
3654 	u8 summary_result = 0;
3655 	u16 act_length = 0;
3656 	int length = 0;
3657 	int size;
3658 	int rc;
3659 
3660 	mutex_lock(&dad->sysfs_lock);
3661 
3662 	pm_runtime_get_sync(dev);
3663 
3664 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
3665 	if (rc < 0) {
3666 		dev_err(dev, "%s: Error on request exclusive r=%d\n",
3667 				__func__, rc);
3668 		goto put_pm_runtime;
3669 	}
3670 
3671 	rc = cyttsp5_suspend_scan_cmd_(dev);
3672 	if (rc < 0) {
3673 		dev_err(dev, "%s: Error on suspend scan r=%d\n",
3674 				__func__, rc);
3675 		goto release_exclusive;
3676 	}
3677 
3678 	rc = cyttsp5_run_selftest_cmd_(dev, test_id, 0,
3679 			&cmd_status, &summary_result, NULL);
3680 	if (rc < 0) {
3681 		dev_err(dev, "%s: Error on run self test for test_id:%d r=%d\n",
3682 				__func__, test_id, rc);
3683 		goto resume_scan;
3684 	}
3685 
3686 	/* Form response buffer */
3687 	dad->ic_buf[0] = cmd_status;
3688 	dad->ic_buf[1] = summary_result;
3689 
3690 	length = 2;
3691 
3692 	/* Get data if command status is success */
3693 	if (cmd_status != CY_CMD_STATUS_SUCCESS)
3694 		goto status_success;
3695 
3696 	/* Get data unless test result is pass */
3697 	if (summary_result == CY_ST_RESULT_PASS && !get_result_on_pass)
3698 		goto status_success;
3699 
3700 	rc = cyttsp5_get_selftest_result_cmd_(dev, 0, read_length,
3701 			test_id, &cmd_status, &act_length, &dad->ic_buf[6]);
3702 	if (rc < 0) {
3703 		dev_err(dev, "%s: Error on get self test result r=%d\n",
3704 				__func__, rc);
3705 		goto resume_scan;
3706 	}
3707 
3708 	dad->ic_buf[2] = cmd_status;
3709 	dad->ic_buf[3] = test_id;
3710 	dad->ic_buf[4] = LOW_BYTE(act_length);
3711 	dad->ic_buf[5] = HI_BYTE(act_length);
3712 
3713 	length = 6 + act_length;
3714 
3715 status_success:
3716 	status = STATUS_SUCCESS;
3717 
3718 resume_scan:
3719 	cyttsp5_resume_scan_cmd_(dev);
3720 
3721 release_exclusive:
3722 	cmd->release_exclusive(dev);
3723 
3724 put_pm_runtime:
3725 	pm_runtime_put(dev);
3726 
3727 	if (status == STATUS_FAIL)
3728 		length = 0;
3729 
3730 	size = prepare_print_buffer(status, dad->ic_buf, length, buf, buf_len);
3731 
3732 	mutex_unlock(&dad->sysfs_lock);
3733 
3734 	return size;
3735 }
3736 
3737 struct cyttsp5_device_access_debugfs_data {
3738 	struct cyttsp5_device_access_data *dad;
3739 	ssize_t pr_buf_len;
3740 	u8 pr_buf[3 * CY_MAX_PRBUF_SIZE];
3741 };
3742 
cyttsp5_device_access_debugfs_open(struct inode * inode,struct file * filp)3743 static int cyttsp5_device_access_debugfs_open(struct inode *inode,
3744 		struct file *filp)
3745 {
3746 	struct cyttsp5_device_access_data *dad = inode->i_private;
3747 	struct cyttsp5_device_access_debugfs_data *data;
3748 
3749 	data = kzalloc(sizeof(*data), GFP_KERNEL);
3750 	if (!data)
3751 		return -ENOMEM;
3752 
3753 	data->dad = dad;
3754 
3755 	filp->private_data = data;
3756 
3757 	return nonseekable_open(inode, filp);
3758 }
3759 
cyttsp5_device_access_debugfs_release(struct inode * inode,struct file * filp)3760 static int cyttsp5_device_access_debugfs_release(struct inode *inode,
3761 		struct file *filp)
3762 {
3763 	kfree(filp->private_data);
3764 
3765 	return 0;
3766 }
3767 
3768 #define CY_DEBUGFS_FOPS(_name, _read, _write) \
3769 static const struct file_operations _name##_debugfs_fops = { \
3770 	.open = cyttsp5_device_access_debugfs_open, \
3771 	.release = cyttsp5_device_access_debugfs_release, \
3772 	.read = _read, \
3773 	.write = _write, \
3774 }
3775 
panel_scan_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)3776 static ssize_t panel_scan_debugfs_read(struct file *filp, char __user *buf,
3777 		size_t count, loff_t *ppos)
3778 {
3779 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
3780 	struct cyttsp5_device_access_data *dad = data->dad;
3781 	struct device *dev = dad->dev;
3782 	struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
3783 	int status = STATUS_FAIL;
3784 	u8 config;
3785 	u16 actual_read_len;
3786 	int length = 0;
3787 	u8 element_size = 0;
3788 	u8 *buf_offset;
3789 	int elem_offset = 0;
3790 	int rc;
3791 
3792 	if (*ppos)
3793 		goto exit;
3794 
3795 
3796 	mutex_lock(&dad->sysfs_lock);
3797 
3798 	pm_runtime_get_sync(dev);
3799 
3800 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
3801 	if (rc < 0) {
3802 		dev_err(dev, "%s: Error on request exclusive r=%d\n",
3803 				__func__, rc);
3804 		goto put_pm_runtime;
3805 	}
3806 
3807 	rc = cyttsp5_suspend_scan_cmd_(dev);
3808 	if (rc < 0) {
3809 		dev_err(dev, "%s: Error on suspend scan r=%d\n",
3810 				__func__, rc);
3811 		goto release_exclusive;
3812 	}
3813 
3814 	rc = cyttsp5_exec_scan_cmd_(dev);
3815 	if (rc < 0) {
3816 		dev_err(dev, "%s: Error on execute panel scan r=%d\n",
3817 				__func__, rc);
3818 		goto resume_scan;
3819 	}
3820 
3821 	/* Set length to max to read all */
3822 	rc = cyttsp5_ret_scan_data_cmd_(dev, 0, 0xFFFF,
3823 			dad->panel_scan_data_id, dad->ic_buf, &config,
3824 			&actual_read_len, NULL);
3825 	if (rc < 0) {
3826 		dev_err(dev, "%s: Error on retrieve panel scan r=%d\n",
3827 				__func__, rc);
3828 		goto resume_scan;
3829 	}
3830 
3831 	length = get_unaligned_le16(&dad->ic_buf[0]);
3832 	buf_offset = dad->ic_buf + length;
3833 	element_size = config & 0x07;
3834 	elem_offset = actual_read_len;
3835 	while (actual_read_len > 0) {
3836 		rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset, 0xFFFF,
3837 				dad->panel_scan_data_id, NULL, &config,
3838 				&actual_read_len, buf_offset);
3839 		if (rc < 0)
3840 			goto resume_scan;
3841 
3842 		length += actual_read_len * element_size;
3843 		buf_offset = dad->ic_buf + length;
3844 		elem_offset += actual_read_len;
3845 	}
3846 	/* Reconstruct cmd header */
3847 	put_unaligned_le16(length, &dad->ic_buf[0]);
3848 	put_unaligned_le16(elem_offset, &dad->ic_buf[7]);
3849 
3850 	/* Do not print command header */
3851 	length -= 5;
3852 
3853 	status = STATUS_SUCCESS;
3854 
3855 resume_scan:
3856 	cyttsp5_resume_scan_cmd_(dev);
3857 
3858 release_exclusive:
3859 	cmd->release_exclusive(dev);
3860 
3861 put_pm_runtime:
3862 	pm_runtime_put(dev);
3863 
3864 	if (status == STATUS_FAIL)
3865 		length = 0;
3866 	if (cd->show_timestamp) {
3867 		int index = 0;
3868 
3869 		index += scnprintf(data->pr_buf, sizeof(data->pr_buf),
3870 			"[%u] ", jiffies_to_msecs(jiffies));
3871 		data->pr_buf_len = prepare_print_buffer(status,
3872 			&dad->ic_buf[5], length, &data->pr_buf[index],
3873 			sizeof(data->pr_buf)-index);
3874 	} else {
3875 		data->pr_buf_len = prepare_print_buffer(status,
3876 			&dad->ic_buf[5], length, data->pr_buf,
3877 			sizeof(data->pr_buf));
3878 	}
3879 
3880 	mutex_unlock(&dad->sysfs_lock);
3881 
3882 exit:
3883 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
3884 			data->pr_buf_len);
3885 }
3886 
panel_scan_debugfs_write(struct file * filp,const char __user * buf,size_t count,loff_t * ppos)3887 static ssize_t panel_scan_debugfs_write(struct file *filp,
3888 		const char __user *buf, size_t count, loff_t *ppos)
3889 {
3890 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
3891 	struct cyttsp5_device_access_data *dad = data->dad;
3892 	ssize_t length;
3893 	int rc = 0;
3894 
3895 	rc = simple_write_to_buffer(data->pr_buf, sizeof(data->pr_buf), ppos,
3896 			buf, count);
3897 	if (rc < 0)
3898 		return rc;
3899 
3900 	count = rc;
3901 
3902 	mutex_lock(&dad->sysfs_lock);
3903 
3904 	length = cyttsp5_ic_parse_input(dad->dev, data->pr_buf, count,
3905 			dad->ic_buf, CY_MAX_PRBUF_SIZE);
3906 
3907 	if (length != 1) {
3908 		dev_err(dad->dev, "%s: Malformed input\n", __func__);
3909 		rc = -EINVAL;
3910 		goto exit_unlock;
3911 	}
3912 
3913 	dad->panel_scan_data_id = dad->ic_buf[0];
3914 
3915 exit_unlock:
3916 	mutex_unlock(&dad->sysfs_lock);
3917 
3918 	if (rc)
3919 		return rc;
3920 
3921 	return count;
3922 }
3923 
3924 CY_DEBUGFS_FOPS(panel_scan, panel_scan_debugfs_read, panel_scan_debugfs_write);
3925 
get_idac_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)3926 static ssize_t get_idac_debugfs_read(struct file *filp, char __user *buf,
3927 		size_t count, loff_t *ppos)
3928 {
3929 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
3930 	struct cyttsp5_device_access_data *dad = data->dad;
3931 	struct device *dev = dad->dev;
3932 	int status = STATUS_FAIL;
3933 	u8 cmd_status = 0;
3934 	u8 data_format = 0;
3935 	u16 act_length = 0;
3936 	int length = 0;
3937 	int rc;
3938 
3939 	if (*ppos)
3940 		goto exit;
3941 
3942 	mutex_lock(&dad->sysfs_lock);
3943 
3944 	pm_runtime_get_sync(dev);
3945 
3946 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
3947 	if (rc < 0) {
3948 		dev_err(dev, "%s: Error on request exclusive r=%d\n",
3949 				__func__, rc);
3950 		goto put_pm_runtime;
3951 	}
3952 
3953 	rc = cyttsp5_suspend_scan_cmd_(dev);
3954 	if (rc < 0) {
3955 		dev_err(dev, "%s: Error on suspend scan r=%d\n",
3956 				__func__, rc);
3957 		goto release_exclusive;
3958 	}
3959 
3960 	rc = cyttsp5_get_data_structure_cmd_(dev, 0, PIP_CMD_MAX_LENGTH,
3961 			dad->get_idac_data_id, &cmd_status, &data_format,
3962 			&act_length, &dad->ic_buf[5]);
3963 	if (rc < 0) {
3964 		dev_err(dev, "%s: Error on get data structure r=%d\n",
3965 				__func__, rc);
3966 		goto resume_scan;
3967 	}
3968 
3969 	dad->ic_buf[0] = cmd_status;
3970 	dad->ic_buf[1] = dad->get_idac_data_id;
3971 	dad->ic_buf[2] = LOW_BYTE(act_length);
3972 	dad->ic_buf[3] = HI_BYTE(act_length);
3973 	dad->ic_buf[4] = data_format;
3974 
3975 	length = 5 + act_length;
3976 
3977 	status = STATUS_SUCCESS;
3978 
3979 resume_scan:
3980 	cyttsp5_resume_scan_cmd_(dev);
3981 
3982 release_exclusive:
3983 	cmd->release_exclusive(dev);
3984 
3985 put_pm_runtime:
3986 	pm_runtime_put(dev);
3987 
3988 	if (status == STATUS_FAIL)
3989 		length = 0;
3990 
3991 	data->pr_buf_len = prepare_print_buffer(status, dad->ic_buf, length,
3992 			data->pr_buf, sizeof(data->pr_buf));
3993 
3994 	mutex_unlock(&dad->sysfs_lock);
3995 
3996 exit:
3997 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
3998 			data->pr_buf_len);
3999 }
4000 
get_idac_debugfs_write(struct file * filp,const char __user * buf,size_t count,loff_t * ppos)4001 static ssize_t get_idac_debugfs_write(struct file *filp,
4002 		const char __user *buf, size_t count, loff_t *ppos)
4003 {
4004 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4005 	struct cyttsp5_device_access_data *dad = data->dad;
4006 	ssize_t length;
4007 	int rc = 0;
4008 
4009 	rc = simple_write_to_buffer(data->pr_buf, sizeof(data->pr_buf), ppos,
4010 			buf, count);
4011 	if (rc < 0)
4012 		return rc;
4013 
4014 	count = rc;
4015 
4016 	mutex_lock(&dad->sysfs_lock);
4017 
4018 	length = cyttsp5_ic_parse_input(dad->dev, data->pr_buf, count,
4019 			dad->ic_buf, CY_MAX_PRBUF_SIZE);
4020 	if (length != 1) {
4021 		dev_err(dad->dev, "%s: Malformed input\n", __func__);
4022 		rc = -EINVAL;
4023 		goto exit_unlock;
4024 	}
4025 
4026 	dad->get_idac_data_id = dad->ic_buf[0];
4027 
4028 exit_unlock:
4029 	mutex_unlock(&dad->sysfs_lock);
4030 
4031 	if (rc)
4032 		return rc;
4033 
4034 	return count;
4035 }
4036 
4037 CY_DEBUGFS_FOPS(get_idac, get_idac_debugfs_read, get_idac_debugfs_write);
4038 
calibrate_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4039 static ssize_t calibrate_debugfs_read(struct file *filp, char __user *buf,
4040 		size_t count, loff_t *ppos)
4041 {
4042 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4043 	struct cyttsp5_device_access_data *dad = data->dad;
4044 	struct device *dev = dad->dev;
4045 	int status = STATUS_FAIL;
4046 	int length = 0;
4047 	int rc;
4048 
4049 	if (*ppos)
4050 		goto exit;
4051 
4052 	mutex_lock(&dad->sysfs_lock);
4053 
4054 	pm_runtime_get_sync(dev);
4055 
4056 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
4057 	if (rc < 0) {
4058 		dev_err(dev, "%s: Error on request exclusive r=%d\n",
4059 				__func__, rc);
4060 		goto put_pm_runtime;
4061 	}
4062 
4063 	rc = cyttsp5_suspend_scan_cmd_(dev);
4064 	if (rc < 0) {
4065 		dev_err(dev, "%s: Error on suspend scan r=%d\n",
4066 				__func__, rc);
4067 		goto release_exclusive;
4068 	}
4069 
4070 	rc = _cyttsp5_calibrate_idacs_cmd(dev, dad->calibrate_sensing_mode,
4071 			&dad->ic_buf[0]);
4072 	if (rc < 0) {
4073 		dev_err(dev, "%s: Error on calibrate idacs r=%d\n",
4074 				__func__, rc);
4075 		goto resume_scan;
4076 	}
4077 
4078 	length = 1;
4079 
4080 	/* Check if baseline initialization is requested */
4081 	if (dad->calibrate_initialize_baselines) {
4082 		/* Perform baseline initialization for all modes */
4083 		rc = _cyttsp5_initialize_baselines_cmd(dev, CY_IB_SM_MUTCAP |
4084 				CY_IB_SM_SELFCAP | CY_IB_SM_BUTTON,
4085 				&dad->ic_buf[length]);
4086 		if (rc < 0) {
4087 			dev_err(dev, "%s: Error on initialize baselines r=%d\n",
4088 					__func__, rc);
4089 			goto resume_scan;
4090 		}
4091 
4092 		length++;
4093 	}
4094 
4095 	status = STATUS_SUCCESS;
4096 
4097 resume_scan:
4098 	cyttsp5_resume_scan_cmd_(dev);
4099 
4100 release_exclusive:
4101 	cmd->release_exclusive(dev);
4102 
4103 put_pm_runtime:
4104 	pm_runtime_put(dev);
4105 
4106 	if (status == STATUS_FAIL)
4107 		length = 0;
4108 
4109 	data->pr_buf_len = prepare_print_buffer(status, dad->ic_buf, length,
4110 			data->pr_buf, sizeof(data->pr_buf));
4111 
4112 	mutex_unlock(&dad->sysfs_lock);
4113 
4114 exit:
4115 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4116 			data->pr_buf_len);
4117 }
4118 
calibrate_debugfs_write(struct file * filp,const char __user * buf,size_t count,loff_t * ppos)4119 static ssize_t calibrate_debugfs_write(struct file *filp,
4120 		const char __user *buf, size_t count, loff_t *ppos)
4121 {
4122 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4123 	struct cyttsp5_device_access_data *dad = data->dad;
4124 	ssize_t length;
4125 	int rc = 0;
4126 
4127 	rc = simple_write_to_buffer(data->pr_buf, sizeof(data->pr_buf), ppos,
4128 			buf, count);
4129 	if (rc < 0)
4130 		return rc;
4131 
4132 	count = rc;
4133 
4134 	mutex_lock(&dad->sysfs_lock);
4135 
4136 	length = cyttsp5_ic_parse_input(dad->dev, data->pr_buf, count,
4137 			dad->ic_buf, CY_MAX_PRBUF_SIZE);
4138 	if (length != 2) {
4139 		dev_err(dad->dev, "%s: Malformed input\n", __func__);
4140 		rc = -EINVAL;
4141 		goto exit_unlock;
4142 	}
4143 
4144 	dad->calibrate_sensing_mode = dad->ic_buf[0];
4145 	dad->calibrate_initialize_baselines = dad->ic_buf[1];
4146 
4147 exit_unlock:
4148 	mutex_unlock(&dad->sysfs_lock);
4149 
4150 	if (rc)
4151 		return rc;
4152 
4153 	return count;
4154 }
4155 
4156 CY_DEBUGFS_FOPS(calibrate, calibrate_debugfs_read, calibrate_debugfs_write);
4157 
baseline_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4158 static ssize_t baseline_debugfs_read(struct file *filp, char __user *buf,
4159 		size_t count, loff_t *ppos)
4160 {
4161 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4162 	struct cyttsp5_device_access_data *dad = data->dad;
4163 	struct device *dev = dad->dev;
4164 	int status = STATUS_FAIL;
4165 	int length = 0;
4166 	int rc;
4167 
4168 	if (*ppos)
4169 		goto exit;
4170 
4171 	mutex_lock(&dad->sysfs_lock);
4172 
4173 	pm_runtime_get_sync(dev);
4174 
4175 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
4176 	if (rc < 0) {
4177 		dev_err(dev, "%s: Error on request exclusive r=%d\n",
4178 				__func__, rc);
4179 		goto put_pm_runtime;
4180 	}
4181 
4182 	rc = cyttsp5_suspend_scan_cmd_(dev);
4183 	if (rc < 0) {
4184 		dev_err(dev, "%s: Error on suspend scan r=%d\n",
4185 				__func__, rc);
4186 		goto release_exclusive;
4187 	}
4188 
4189 	rc = _cyttsp5_initialize_baselines_cmd(dev, dad->baseline_sensing_mode,
4190 			&dad->ic_buf[0]);
4191 	if (rc < 0) {
4192 		dev_err(dev, "%s: Error on initialize baselines r=%d\n",
4193 				__func__, rc);
4194 		goto resume_scan;
4195 	}
4196 
4197 	length = 1;
4198 
4199 	status = STATUS_SUCCESS;
4200 
4201 resume_scan:
4202 	cyttsp5_resume_scan_cmd_(dev);
4203 
4204 release_exclusive:
4205 	cmd->release_exclusive(dev);
4206 
4207 put_pm_runtime:
4208 	pm_runtime_put(dev);
4209 
4210 	if (status == STATUS_FAIL)
4211 		length = 0;
4212 
4213 	data->pr_buf_len = prepare_print_buffer(status, dad->ic_buf, length,
4214 			data->pr_buf, sizeof(data->pr_buf));
4215 
4216 	mutex_unlock(&dad->sysfs_lock);
4217 
4218 exit:
4219 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4220 			data->pr_buf_len);
4221 }
4222 
baseline_debugfs_write(struct file * filp,const char __user * buf,size_t count,loff_t * ppos)4223 static ssize_t baseline_debugfs_write(struct file *filp,
4224 		const char __user *buf, size_t count, loff_t *ppos)
4225 {
4226 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4227 	struct cyttsp5_device_access_data *dad = data->dad;
4228 	ssize_t length;
4229 	int rc = 0;
4230 
4231 	rc = simple_write_to_buffer(data->pr_buf, sizeof(data->pr_buf), ppos,
4232 			buf, count);
4233 	if (rc < 0)
4234 		return rc;
4235 
4236 	count = rc;
4237 
4238 	mutex_lock(&dad->sysfs_lock);
4239 
4240 	length = cyttsp5_ic_parse_input(dad->dev, buf, count, dad->ic_buf,
4241 			CY_MAX_PRBUF_SIZE);
4242 	if (length != 1) {
4243 		dev_err(dad->dev, "%s: Malformed input\n", __func__);
4244 		rc = -EINVAL;
4245 		goto exit_unlock;
4246 	}
4247 
4248 	dad->baseline_sensing_mode = dad->ic_buf[0];
4249 
4250 exit_unlock:
4251 	mutex_unlock(&dad->sysfs_lock);
4252 
4253 	if (rc)
4254 		return rc;
4255 
4256 	return count;
4257 }
4258 
4259 CY_DEBUGFS_FOPS(baseline, baseline_debugfs_read, baseline_debugfs_write);
4260 
auto_shorts_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4261 static ssize_t auto_shorts_debugfs_read(struct file *filp, char __user *buf,
4262 		size_t count, loff_t *ppos)
4263 {
4264 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4265 
4266 	if (!*ppos)
4267 		/* Set length to PIP_CMD_MAX_LENGTH to read all */
4268 		data->pr_buf_len = cyttsp5_run_and_get_selftest_result(
4269 			data->dad->dev, data->pr_buf, sizeof(data->pr_buf),
4270 			CY_ST_ID_AUTOSHORTS, PIP_CMD_MAX_LENGTH, false);
4271 
4272 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4273 			data->pr_buf_len);
4274 }
4275 
4276 CY_DEBUGFS_FOPS(auto_shorts, auto_shorts_debugfs_read, NULL);
4277 
opens_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4278 static ssize_t opens_debugfs_read(struct file *filp, char __user *buf,
4279 		size_t count, loff_t *ppos)
4280 {
4281 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4282 
4283 	if (!*ppos)
4284 		/* Set length to PIP_CMD_MAX_LENGTH to read all */
4285 		data->pr_buf_len = cyttsp5_run_and_get_selftest_result(
4286 			data->dad->dev, data->pr_buf, sizeof(data->pr_buf),
4287 			CY_ST_ID_OPENS, PIP_CMD_MAX_LENGTH, false);
4288 
4289 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4290 			data->pr_buf_len);
4291 }
4292 
4293 CY_DEBUGFS_FOPS(opens, opens_debugfs_read, NULL);
4294 
cm_panel_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4295 static ssize_t cm_panel_debugfs_read(struct file *filp, char __user *buf,
4296 		size_t count, loff_t *ppos)
4297 {
4298 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4299 
4300 	if (!*ppos)
4301 		/* Set length to PIP_CMD_MAX_LENGTH to read all */
4302 		data->pr_buf_len = cyttsp5_run_and_get_selftest_result(
4303 			data->dad->dev, data->pr_buf, sizeof(data->pr_buf),
4304 			CY_ST_ID_CM_PANEL, PIP_CMD_MAX_LENGTH, true);
4305 
4306 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4307 			data->pr_buf_len);
4308 }
4309 
4310 CY_DEBUGFS_FOPS(cm_panel, cm_panel_debugfs_read, NULL);
4311 
cp_panel_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4312 static ssize_t cp_panel_debugfs_read(struct file *filp, char __user *buf,
4313 		size_t count, loff_t *ppos)
4314 {
4315 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4316 
4317 	if (!*ppos)
4318 		/* Set length to PIP_CMD_MAX_LENGTH to read all */
4319 		data->pr_buf_len = cyttsp5_run_and_get_selftest_result(
4320 			data->dad->dev, data->pr_buf, sizeof(data->pr_buf),
4321 			CY_ST_ID_CP_PANEL, PIP_CMD_MAX_LENGTH, true);
4322 
4323 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4324 			data->pr_buf_len);
4325 }
4326 
4327 CY_DEBUGFS_FOPS(cp_panel, cp_panel_debugfs_read, NULL);
4328 
cm_button_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4329 static ssize_t cm_button_debugfs_read(struct file *filp, char __user *buf,
4330 		size_t count, loff_t *ppos)
4331 {
4332 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4333 
4334 	if (!*ppos)
4335 		/* Set length to PIP_CMD_MAX_LENGTH to read all */
4336 		data->pr_buf_len = cyttsp5_run_and_get_selftest_result(
4337 			data->dad->dev, data->pr_buf, sizeof(data->pr_buf),
4338 			CY_ST_ID_CM_BUTTON, PIP_CMD_MAX_LENGTH, true);
4339 
4340 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4341 			data->pr_buf_len);
4342 }
4343 
4344 CY_DEBUGFS_FOPS(cm_button, cm_button_debugfs_read, NULL);
4345 
cp_button_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4346 static ssize_t cp_button_debugfs_read(struct file *filp, char __user *buf,
4347 		size_t count, loff_t *ppos)
4348 {
4349 	struct cyttsp5_device_access_debugfs_data *data = filp->private_data;
4350 
4351 	if (!*ppos)
4352 		/* Set length to PIP_CMD_MAX_LENGTH to read all */
4353 		data->pr_buf_len = cyttsp5_run_and_get_selftest_result(
4354 			data->dad->dev, data->pr_buf, sizeof(data->pr_buf),
4355 			CY_ST_ID_CP_BUTTON, PIP_CMD_MAX_LENGTH, true);
4356 
4357 	return simple_read_from_buffer(buf, count, ppos, data->pr_buf,
4358 			data->pr_buf_len);
4359 }
4360 
4361 CY_DEBUGFS_FOPS(cp_button, cp_button_debugfs_read, NULL);
4362 
4363 #ifdef TTHE_TUNER_SUPPORT
tthe_get_panel_data_debugfs_read(struct file * filp,char __user * buf,size_t count,loff_t * ppos)4364 static ssize_t tthe_get_panel_data_debugfs_read(struct file *filp,
4365 		char __user *buf, size_t count, loff_t *ppos)
4366 {
4367 	struct cyttsp5_device_access_data *dad = filp->private_data;
4368 	struct device *dev;
4369 	struct cyttsp5_core_data *cd;
4370 	u8 config;
4371 	u16 actual_read_len;
4372 	u16 length = 0;
4373 	u8 element_size = 0;
4374 	u8 *buf_offset;
4375 	u8 *buf_out;
4376 	int elem;
4377 	int elem_offset = 0;
4378 	int print_idx = 0;
4379 	int rc;
4380 	int rc1;
4381 	int i;
4382 
4383 	mutex_lock(&dad->debugfs_lock);
4384 	dev = dad->dev;
4385 	cd = dev_get_drvdata(dev);
4386 	buf_out = dad->tthe_get_panel_data_buf;
4387 	if (!buf_out)
4388 		goto release_mutex;
4389 
4390 	pm_runtime_get_sync(dev);
4391 
4392 	rc = cmd->request_exclusive(dev, CY_REQUEST_EXCLUSIVE_TIMEOUT);
4393 	if (rc < 0)
4394 		goto put_runtime;
4395 
4396 	if (dad->heatmap.scan_start) {
4397 		/*
4398 		 * To fix CDT206291: avoid multiple scans when
4399 		 * return data is larger than 4096 bytes in one cycle
4400 		 */
4401 		dad->heatmap.scan_start = 0;
4402 
4403 		/* Start scan */
4404 		rc = cyttsp5_exec_scan_cmd_(dev);
4405 		if (rc < 0)
4406 			goto release_exclusive;
4407 	}
4408 
4409 	elem = dad->heatmap.num_element;
4410 
4411 #if defined(CY_ENABLE_MAX_ELEN)
4412 	if (elem > CY_MAX_ELEN) {
4413 		rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset,
4414 		CY_MAX_ELEN, dad->heatmap.data_type, dad->ic_buf,
4415 		&config, &actual_read_len, NULL);
4416 	} else{
4417 		rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset, elem,
4418 			dad->heatmap.data_type, dad->ic_buf, &config,
4419 			&actual_read_len, NULL);
4420 	}
4421 #else
4422 	rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset, elem,
4423 			dad->heatmap.data_type, dad->ic_buf, &config,
4424 			&actual_read_len, NULL);
4425 #endif
4426 	if (rc < 0)
4427 		goto release_exclusive;
4428 
4429 	length = get_unaligned_le16(&dad->ic_buf[0]);
4430 	buf_offset = dad->ic_buf + length;
4431 
4432 	element_size = config & CY_CMD_RET_PANEL_ELMNT_SZ_MASK;
4433 
4434 	elem -= actual_read_len;
4435 	elem_offset = actual_read_len;
4436 	while (elem > 0) {
4437 #ifdef CY_ENABLE_MAX_ELEN
4438 		if (elem > CY_MAX_ELEN) {
4439 			rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset,
4440 			CY_MAX_ELEN, dad->heatmap.data_type, NULL, &config,
4441 			&actual_read_len, buf_offset);
4442 		} else{
4443 			rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset, elem,
4444 				dad->heatmap.data_type, NULL, &config,
4445 				&actual_read_len, buf_offset);
4446 		}
4447 #else
4448 
4449 		rc = cyttsp5_ret_scan_data_cmd_(dev, elem_offset, elem,
4450 				dad->heatmap.data_type, NULL, &config,
4451 				&actual_read_len, buf_offset);
4452 #endif
4453 		if (rc < 0)
4454 			goto release_exclusive;
4455 
4456 		if (!actual_read_len)
4457 			break;
4458 
4459 		length += actual_read_len * element_size;
4460 		buf_offset = dad->ic_buf + length;
4461 		elem -= actual_read_len;
4462 		elem_offset += actual_read_len;
4463 	}
4464 
4465 	/* Reconstruct cmd header */
4466 	put_unaligned_le16(length, &dad->ic_buf[0]);
4467 	put_unaligned_le16(elem_offset, &dad->ic_buf[7]);
4468 
4469 release_exclusive:
4470 	rc1 = cmd->release_exclusive(dev);
4471 put_runtime:
4472 	pm_runtime_put(dev);
4473 
4474 	if (rc < 0)
4475 		goto release_mutex;
4476 	if (cd->show_timestamp)
4477 		print_idx += scnprintf(buf_out, TTHE_TUNER_MAX_BUF,
4478 			"[%u] CY_DATA:", jiffies_to_msecs(jiffies));
4479 	else
4480 		print_idx += scnprintf(buf_out, TTHE_TUNER_MAX_BUF,
4481 			"CY_DATA:");
4482 	for (i = 0; i < length; i++)
4483 		print_idx += scnprintf(buf_out + print_idx,
4484 				TTHE_TUNER_MAX_BUF - print_idx,
4485 				"%02X ", dad->ic_buf[i]);
4486 	print_idx += scnprintf(buf_out + print_idx,
4487 			TTHE_TUNER_MAX_BUF - print_idx,
4488 			":(%d bytes)\n", length);
4489 	rc = simple_read_from_buffer(buf, count, ppos, buf_out, print_idx);
4490 	print_idx = rc;
4491 
4492 release_mutex:
4493 	mutex_unlock(&dad->debugfs_lock);
4494 	return print_idx;
4495 }
4496 
tthe_get_panel_data_debugfs_write(struct file * filp,const char __user * buf,size_t count,loff_t * ppos)4497 static ssize_t tthe_get_panel_data_debugfs_write(struct file *filp,
4498 		const char __user *buf, size_t count, loff_t *ppos)
4499 {
4500 	struct cyttsp5_device_access_data *dad = filp->private_data;
4501 	struct device *dev = dad->dev;
4502 	ssize_t length;
4503 	int max_read;
4504 	u8 *buf_in = dad->tthe_get_panel_data_buf;
4505 	int ret;
4506 
4507 	mutex_lock(&dad->debugfs_lock);
4508 	ret = copy_from_user(buf_in + (*ppos), buf, count);
4509 	if (ret)
4510 		goto exit;
4511 	buf_in[count] = 0;
4512 
4513 	length = cyttsp5_ic_parse_input(dev, buf_in, count, dad->ic_buf,
4514 			CY_MAX_PRBUF_SIZE);
4515 	if (length <= 0) {
4516 		dev_err(dev, "%s: %s Group Data store\n", __func__,
4517 				"Malformed input for");
4518 		goto exit;
4519 	}
4520 
4521 	/* update parameter value */
4522 	dad->heatmap.num_element = get_unaligned_le16(&dad->ic_buf[3]);
4523 	dad->heatmap.data_type = dad->ic_buf[5];
4524 
4525 	if (dad->ic_buf[6] > 0)
4526 		dad->heatmap.scan_start = true;
4527 	else
4528 		dad->heatmap.scan_start = false;
4529 
4530 	/* elem can not be bigger then buffer size */
4531 	max_read = CY_CMD_RET_PANEL_HDR;
4532 	max_read += dad->heatmap.num_element * CY_CMD_RET_PANEL_ELMNT_SZ_MAX;
4533 
4534 	if (max_read >= CY_MAX_PRBUF_SIZE) {
4535 		dad->heatmap.num_element =
4536 			(CY_MAX_PRBUF_SIZE - CY_CMD_RET_PANEL_HDR)
4537 			/ CY_CMD_RET_PANEL_ELMNT_SZ_MAX;
4538 		parade_debug(dev, DEBUG_LEVEL_2, "%s: Will get %d element\n",
4539 			__func__, dad->heatmap.num_element);
4540 	}
4541 
4542 exit:
4543 	mutex_unlock(&dad->debugfs_lock);
4544 	parade_debug(dev, DEBUG_LEVEL_2, "%s: return count=%zu\n",
4545 		__func__, count);
4546 	return count;
4547 }
4548 
tthe_get_panel_data_debugfs_open(struct inode * inode,struct file * filp)4549 static int tthe_get_panel_data_debugfs_open(struct inode *inode,
4550 		struct file *filp)
4551 {
4552 	struct cyttsp5_device_access_data *dad = inode->i_private;
4553 
4554 	mutex_lock(&dad->debugfs_lock);
4555 
4556 	if (dad->tthe_get_panel_data_is_open) {
4557 		mutex_unlock(&dad->debugfs_lock);
4558 		return -EBUSY;
4559 	}
4560 
4561 	filp->private_data = inode->i_private;
4562 
4563 	dad->tthe_get_panel_data_is_open = 1;
4564 	mutex_unlock(&dad->debugfs_lock);
4565 	return 0;
4566 }
4567 
tthe_get_panel_data_debugfs_close(struct inode * inode,struct file * filp)4568 static int tthe_get_panel_data_debugfs_close(struct inode *inode,
4569 		struct file *filp)
4570 {
4571 	struct cyttsp5_device_access_data *dad = filp->private_data;
4572 
4573 	mutex_lock(&dad->debugfs_lock);
4574 	filp->private_data = NULL;
4575 	dad->tthe_get_panel_data_is_open = 0;
4576 	mutex_unlock(&dad->debugfs_lock);
4577 
4578 	return 0;
4579 }
4580 
4581 static const struct file_operations tthe_get_panel_data_fops = {
4582 	.open = tthe_get_panel_data_debugfs_open,
4583 	.release = tthe_get_panel_data_debugfs_close,
4584 	.read = tthe_get_panel_data_debugfs_read,
4585 	.write = tthe_get_panel_data_debugfs_write,
4586 };
4587 #endif
4588 
cyttsp5_setup_sysfs(struct device * dev)4589 static int cyttsp5_setup_sysfs(struct device *dev)
4590 {
4591 	struct cyttsp5_device_access_data *dad
4592 		= cyttsp5_get_device_access_data(dev);
4593 	int rc;
4594 
4595 	rc = device_create_file(dev, &dev_attr_command);
4596 	if (rc) {
4597 		dev_err(dev, "%s: Error, could not create command\n",
4598 				__func__);
4599 		goto exit;
4600 	}
4601 
4602 	rc = device_create_file(dev, &dev_attr_status);
4603 	if (rc) {
4604 		dev_err(dev, "%s: Error, could not create status\n",
4605 				__func__);
4606 		goto unregister_command;
4607 	}
4608 
4609 	rc = device_create_file(dev, &dev_attr_response);
4610 	if (rc) {
4611 		dev_err(dev, "%s: Error, could not create response\n",
4612 				__func__);
4613 		goto unregister_status;
4614 	}
4615 
4616 	dad->base_dentry = debugfs_create_dir(dev_name(dev), NULL);
4617 	if (IS_ERR_OR_NULL(dad->base_dentry)) {
4618 		dev_err(dev, "%s: Error, could not create base directory\n",
4619 				__func__);
4620 		goto unregister_response;
4621 	}
4622 
4623 	dad->mfg_test_dentry = debugfs_create_dir("mfg_test",
4624 			dad->base_dentry);
4625 	if (IS_ERR_OR_NULL(dad->mfg_test_dentry)) {
4626 		dev_err(dev, "%s: Error, could not create mfg_test directory\n",
4627 				__func__);
4628 		goto unregister_base_dir;
4629 	}
4630 
4631 	if (IS_ERR_OR_NULL(debugfs_create_file("panel_scan", 0600,
4632 			dad->mfg_test_dentry, dad,
4633 			&panel_scan_debugfs_fops))) {
4634 		dev_err(dev, "%s: Error, could not create panel_scan\n",
4635 				__func__);
4636 		goto unregister_base_dir;
4637 	}
4638 
4639 	if (IS_ERR_OR_NULL(debugfs_create_file("get_idac", 0600,
4640 			dad->mfg_test_dentry, dad, &get_idac_debugfs_fops))) {
4641 		dev_err(dev, "%s: Error, could not create get_idac\n",
4642 				__func__);
4643 		goto unregister_base_dir;
4644 	}
4645 
4646 	if (IS_ERR_OR_NULL(debugfs_create_file("auto_shorts", 0400,
4647 			dad->mfg_test_dentry, dad,
4648 			&auto_shorts_debugfs_fops))) {
4649 		dev_err(dev, "%s: Error, could not create auto_shorts\n",
4650 				__func__);
4651 		goto unregister_base_dir;
4652 	}
4653 
4654 	if (IS_ERR_OR_NULL(debugfs_create_file("opens", 0400,
4655 			dad->mfg_test_dentry, dad, &opens_debugfs_fops))) {
4656 		dev_err(dev, "%s: Error, could not create opens\n",
4657 				__func__);
4658 		goto unregister_base_dir;
4659 	}
4660 
4661 	if (IS_ERR_OR_NULL(debugfs_create_file("calibrate", 0600,
4662 			dad->mfg_test_dentry, dad, &calibrate_debugfs_fops))) {
4663 		dev_err(dev, "%s: Error, could not create calibrate\n",
4664 				__func__);
4665 		goto unregister_base_dir;
4666 	}
4667 
4668 	if (IS_ERR_OR_NULL(debugfs_create_file("baseline", 0600,
4669 			dad->mfg_test_dentry, dad, &baseline_debugfs_fops))) {
4670 		dev_err(dev, "%s: Error, could not create baseline\n",
4671 				__func__);
4672 		goto unregister_base_dir;
4673 	}
4674 
4675 	if (IS_ERR_OR_NULL(debugfs_create_file("cm_panel", 0400,
4676 			dad->mfg_test_dentry, dad, &cm_panel_debugfs_fops))) {
4677 		dev_err(dev, "%s: Error, could not create cm_panel\n",
4678 				__func__);
4679 		goto unregister_base_dir;
4680 	}
4681 
4682 	if (IS_ERR_OR_NULL(debugfs_create_file("cp_panel", 0400,
4683 			dad->mfg_test_dentry, dad, &cp_panel_debugfs_fops))) {
4684 		dev_err(dev, "%s: Error, could not create cp_panel\n",
4685 				__func__);
4686 		goto unregister_base_dir;
4687 	}
4688 
4689 	if (IS_ERR_OR_NULL(debugfs_create_file("cm_button", 0400,
4690 			dad->mfg_test_dentry, dad, &cm_button_debugfs_fops))) {
4691 		dev_err(dev, "%s: Error, could not create cm_button\n",
4692 				__func__);
4693 		goto unregister_base_dir;
4694 	}
4695 
4696 	if (IS_ERR_OR_NULL(debugfs_create_file("cp_button", 0400,
4697 			dad->mfg_test_dentry, dad, &cp_button_debugfs_fops))) {
4698 		dev_err(dev, "%s: Error, could not create cp_button\n",
4699 				__func__);
4700 		goto unregister_base_dir;
4701 	}
4702 
4703 	dad->cmcp_results_debugfs = debugfs_create_file("cmcp_results", 0644,
4704 		dad->mfg_test_dentry, dad, &cmcp_results_debugfs_fops);
4705 	if (IS_ERR_OR_NULL(dad->cmcp_results_debugfs)) {
4706 		dev_err(dev, "%s: Error, could not create cmcp_results\n",
4707 				__func__);
4708 		dad->cmcp_results_debugfs = NULL;
4709 		goto unregister_base_dir;
4710 	}
4711 
4712 #ifdef TTHE_TUNER_SUPPORT
4713 	dad->tthe_get_panel_data_debugfs = debugfs_create_file(
4714 			CYTTSP5_TTHE_TUNER_GET_PANEL_DATA_FILE_NAME,
4715 			0644, NULL, dad, &tthe_get_panel_data_fops);
4716 	if (IS_ERR_OR_NULL(dad->tthe_get_panel_data_debugfs)) {
4717 		dev_err(dev, "%s: Error, could not create get_panel_data\n",
4718 				__func__);
4719 		dad->tthe_get_panel_data_debugfs = NULL;
4720 		goto unregister_base_dir;
4721 	}
4722 #endif
4723 
4724 	rc = device_create_file(dev, &dev_attr_cmcp_test);
4725 	if (rc) {
4726 		dev_err(dev, "%s: Error, could not create cmcp_test\n",
4727 				__func__);
4728 		goto unregister_base_dir;
4729 	}
4730 
4731 	rc = device_create_file(dev, &dev_attr_cmcp_threshold_loading);
4732 	if (rc) {
4733 		dev_err(dev, "%s: Error, could not create cmcp_thresold_loading\n",
4734 				__func__);
4735 		goto unregister_cmcp_test;
4736 	}
4737 
4738 	rc = device_create_bin_file(dev, &bin_attr_cmcp_threshold_data);
4739 	if (rc) {
4740 		dev_err(dev, "%s: Error, could not create cmcp_thresold_data\n",
4741 				__func__);
4742 		goto unregister_cmcp_thresold_loading;
4743 	}
4744 
4745 	dad->sysfs_nodes_created = true;
4746 	return rc;
4747 
4748 unregister_cmcp_thresold_loading:
4749 	device_remove_file(dev, &dev_attr_cmcp_threshold_loading);
4750 unregister_cmcp_test:
4751 	device_remove_file(dev, &dev_attr_cmcp_test);
4752 unregister_base_dir:
4753 	debugfs_remove_recursive(dad->base_dentry);
4754 unregister_response:
4755 	device_remove_file(dev, &dev_attr_response);
4756 unregister_status:
4757 	device_remove_file(dev, &dev_attr_status);
4758 unregister_command:
4759 	device_remove_file(dev, &dev_attr_command);
4760 exit:
4761 	return rc;
4762 }
4763 
cyttsp5_setup_sysfs_attention(struct device * dev)4764 static int cyttsp5_setup_sysfs_attention(struct device *dev)
4765 {
4766 	struct cyttsp5_device_access_data *dad
4767 		= cyttsp5_get_device_access_data(dev);
4768 	int rc = 0;
4769 
4770 	dad->si = cmd->request_sysinfo(dev);
4771 	if (!dad->si)
4772 		return -EINVAL;
4773 
4774 	rc = cyttsp5_setup_sysfs(dev);
4775 
4776 	cmd->unsubscribe_attention(dev, CY_ATTEN_STARTUP,
4777 		CYTTSP5_DEVICE_ACCESS_NAME, cyttsp5_setup_sysfs_attention,
4778 		0);
4779 
4780 	return rc;
4781 }
4782 
4783 #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_DEVICE_ACCESS_API
cyttsp5_device_access_user_command(const char * core_name,u16 read_len,u8 * read_buf,u16 write_len,u8 * write_buf,u16 * actual_read_len)4784 int cyttsp5_device_access_user_command(const char *core_name, u16 read_len,
4785 		u8 *read_buf, u16 write_len, u8 *write_buf,
4786 		u16 *actual_read_len)
4787 {
4788 	struct cyttsp5_core_data *cd;
4789 	int rc;
4790 
4791 	might_sleep();
4792 
4793 	/* Check parameters */
4794 	if (!read_buf || !write_buf || !actual_read_len)
4795 		return -EINVAL;
4796 
4797 	if (!core_name)
4798 		core_name = CY_DEFAULT_CORE_ID;
4799 
4800 	/* Find device */
4801 	cd = cyttsp5_get_core_data((char *)core_name);
4802 	if (!cd) {
4803 		pr_err("%s: No device.\n", __func__);
4804 		return -ENODEV;
4805 	}
4806 
4807 	pm_runtime_get_sync(cd->dev);
4808 	rc = cmd->nonhid_cmd->user_cmd(cd->dev, 1, read_len, read_buf,
4809 			write_len, write_buf, actual_read_len);
4810 	pm_runtime_put(cd->dev);
4811 
4812 	return rc;
4813 }
4814 EXPORT_SYMBOL_GPL(cyttsp5_device_access_user_command);
4815 
4816 struct command_work {
4817 	struct work_struct work;
4818 	const char *core_name;
4819 	u16 read_len;
4820 	u8 *read_buf;
4821 	u16 write_len;
4822 	u8 *write_buf;
4823 
4824 	void (*cont)(const char *core_name, u16 read_len, u8 *read_buf,
4825 		u16 write_len, u8 *write_buf, u16 actual_read_length,
4826 		int rc);
4827 };
4828 
cyttsp5_device_access_user_command_work_func(struct work_struct * work)4829 static void cyttsp5_device_access_user_command_work_func(
4830 		struct work_struct *work)
4831 {
4832 	struct command_work *cmd_work =
4833 			container_of(work, struct command_work, work);
4834 	u16 actual_read_length;
4835 	int rc;
4836 
4837 	rc = cyttsp5_device_access_user_command(cmd_work->core_name,
4838 			cmd_work->read_len, cmd_work->read_buf,
4839 			cmd_work->write_len, cmd_work->write_buf,
4840 			&actual_read_length);
4841 
4842 	if (cmd_work->cont)
4843 		cmd_work->cont(cmd_work->core_name,
4844 			cmd_work->read_len, cmd_work->read_buf,
4845 			cmd_work->write_len, cmd_work->write_buf,
4846 			actual_read_length, rc);
4847 
4848 	kfree(cmd_work);
4849 }
4850 
cyttsp5_device_access_user_command_async(const char * core_name,u16 read_len,u8 * read_buf,u16 write_len,u8 * write_buf,void (* cont)(const char * core_name,u16 read_len,u8 * read_buf,u16 write_len,u8 * write_buf,u16 actual_read_length,int rc))4851 int cyttsp5_device_access_user_command_async(const char *core_name,
4852 		u16 read_len, u8 *read_buf, u16 write_len, u8 *write_buf,
4853 		void (*cont)(const char *core_name, u16 read_len, u8 *read_buf,
4854 			u16 write_len, u8 *write_buf, u16 actual_read_length,
4855 			int rc))
4856 {
4857 	struct command_work *cmd_work;
4858 
4859 	cmd_work = kzalloc(sizeof(*cmd_work), GFP_ATOMIC);
4860 	if (!cmd_work)
4861 		return -ENOMEM;
4862 
4863 	cmd_work->core_name = core_name;
4864 	cmd_work->read_len = read_len;
4865 	cmd_work->read_buf = read_buf;
4866 	cmd_work->write_len = write_len;
4867 	cmd_work->write_buf = write_buf;
4868 	cmd_work->cont = cont;
4869 
4870 	INIT_WORK(&cmd_work->work,
4871 			cyttsp5_device_access_user_command_work_func);
4872 	schedule_work(&cmd_work->work);
4873 
4874 	return 0;
4875 }
4876 EXPORT_SYMBOL_GPL(cyttsp5_device_access_user_command_async);
4877 #endif
4878 
cyttsp5_cmcp_parse_threshold_file(const struct firmware * fw,void * context)4879 static void cyttsp5_cmcp_parse_threshold_file(const struct firmware *fw,
4880 		void *context)
4881 {
4882 	struct device *dev = context;
4883 	struct cyttsp5_device_access_data *dad =
4884 		cyttsp5_get_device_access_data(dev);
4885 
4886 	if (!fw) {
4887 		dev_info(dev, "%s: No builtin cmcp threshold file\n", __func__);
4888 		goto exit;
4889 	}
4890 
4891 	if (!fw->data || !fw->size) {
4892 		dev_err(dev, "%s: Invalid builtin cmcp threshold file\n",
4893 		__func__);
4894 		goto exit;
4895 	}
4896 
4897 	parade_debug(dev, DEBUG_LEVEL_1, "%s: Found cmcp threshold file.\n",
4898 		__func__);
4899 
4900 	cyttsp5_parse_cmcp_threshold_file_common(dev, &fw->data[0], fw->size);
4901 
4902 	dad->builtin_cmcp_threshold_status = 0;
4903 	complete(&dad->builtin_cmcp_threshold_complete);
4904 	return;
4905 
4906 exit:
4907 	release_firmware(fw);
4908 
4909 	dad->builtin_cmcp_threshold_status = -EINVAL;
4910 	complete(&dad->builtin_cmcp_threshold_complete);
4911 }
4912 
cyttsp5_parse_cmcp_threshold_builtin(struct work_struct * cmcp_threshold_update)4913 static void cyttsp5_parse_cmcp_threshold_builtin(
4914 	struct work_struct *cmcp_threshold_update)
4915 {
4916 	struct cyttsp5_device_access_data *dad =
4917 		container_of(cmcp_threshold_update,
4918 		struct cyttsp5_device_access_data,
4919 		cmcp_threshold_update);
4920 	struct device *dev = dad->dev;
4921 	int retval;
4922 
4923 	dad->si = cmd->request_sysinfo(dev);
4924 	if (!dad->si) {
4925 		dev_err(dev, "%s: Fail get sysinfo pointer from core\n",
4926 			__func__);
4927 		return;
4928 	}
4929 
4930 	parade_debug(dev, DEBUG_LEVEL_2,
4931 		"%s: Enabling cmcp threshold class loader built-in\n",
4932 		__func__);
4933 
4934 	/* Open threshold file */
4935 	retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
4936 			CMCP_THRESHOLD_FILE_NAME, dev, GFP_KERNEL, dev,
4937 			cyttsp5_cmcp_parse_threshold_file);
4938 	if (retval < 0) {
4939 		dev_err(dev, "%s: Failed loading cmcp threshold file, attempting legacy file\n",
4940 			__func__);
4941 		/* Try legacy file name */
4942 		retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
4943 				CY_CMCP_THRESHOLD_FILE_NAME, dev, GFP_KERNEL,
4944 				dev, cyttsp5_cmcp_parse_threshold_file);
4945 		if (retval < 0) {
4946 			dev_err(dev, "%s: Fail request cmcp threshold class file load\n",
4947 				__func__);
4948 			goto exit;
4949 		}
4950 	}
4951 
4952 	/* wait until cmcp threshold upgrade finishes */
4953 	wait_for_completion(&dad->builtin_cmcp_threshold_complete);
4954 
4955 	retval = dad->builtin_cmcp_threshold_status;
4956 
4957 exit:
4958 	return;
4959 }
4960 
cyttsp5_device_access_probe(struct device * dev,void ** data)4961 static int cyttsp5_device_access_probe(struct device *dev, void **data)
4962 {
4963 	struct cyttsp5_device_access_data *dad;
4964 	struct configuration *configurations;
4965 	struct cmcp_data *cmcp_info;
4966 	struct result *result;
4967 
4968 	int tx_num = MAX_TX_SENSORS;
4969 	int rx_num = MAX_RX_SENSORS;
4970 	int btn_num = MAX_BUTTONS;
4971 
4972 	struct test_case_field *test_case_field_array;
4973 	struct test_case_search *test_case_search_array;
4974 	int rc = 0;
4975 
4976 	dad = kzalloc(sizeof(*dad), GFP_KERNEL);
4977 	if (!dad) {
4978 		rc = -ENOMEM;
4979 		goto cyttsp5_device_access_probe_data_failed;
4980 	}
4981 
4982 	configurations =
4983 		kzalloc(sizeof(*configurations), GFP_KERNEL);
4984 	if (!configurations) {
4985 		rc = -ENOMEM;
4986 		goto cyttsp5_device_access_probe_configs_failed;
4987 	}
4988 	dad->configs = configurations;
4989 
4990 	cmcp_info = kzalloc(sizeof(*cmcp_info), GFP_KERNEL);
4991 	if (!cmcp_info) {
4992 		rc = -ENOMEM;
4993 		goto cyttsp5_device_access_probe_cmcp_info_failed;
4994 	}
4995 	dad->cmcp_info = cmcp_info;
4996 
4997 	cmcp_info->tx_num = tx_num;
4998 	cmcp_info->rx_num = rx_num;
4999 	cmcp_info->btn_num = btn_num;
5000 
5001 	result = kzalloc(sizeof(*result), GFP_KERNEL);
5002 	if (!result) {
5003 		rc = -ENOMEM;
5004 		goto cyttsp5_device_access_probe_result_failed;
5005 	}
5006 	dad->result = result;
5007 
5008 	test_case_field_array =
5009 		kzalloc(sizeof(*test_case_field_array) * MAX_CASE_NUM,
5010 		GFP_KERNEL);
5011 	if (!test_case_field_array) {
5012 		rc = -ENOMEM;
5013 		goto cyttsp5_device_access_probe_field_array_failed;
5014 	}
5015 
5016 	test_case_search_array =
5017 		kzalloc(sizeof(*test_case_search_array) * MAX_CASE_NUM,
5018 		GFP_KERNEL);
5019 	if (!test_case_search_array) {
5020 		rc = -ENOMEM;
5021 		goto cyttsp5_device_access_probe_search_array_failed;
5022 	}
5023 
5024 	cmcp_info->gd_sensor_col = (struct gd_sensor *)
5025 		 kzalloc(tx_num * sizeof(struct gd_sensor), GFP_KERNEL);
5026 	if (cmcp_info->gd_sensor_col == NULL)
5027 		goto cyttsp5_device_access_probe_gd_sensor_col_failed;
5028 
5029 	cmcp_info->gd_sensor_row = (struct gd_sensor *)
5030 		 kzalloc(rx_num * sizeof(struct gd_sensor), GFP_KERNEL);
5031 	if (cmcp_info->gd_sensor_row == NULL)
5032 		goto cyttsp5_device_access_probe_gd_sensor_row_failed;
5033 
5034 	cmcp_info->cm_data_panel =
5035 		 kzalloc((tx_num * rx_num + 1) * sizeof(int32_t), GFP_KERNEL);
5036 	if (cmcp_info->cm_data_panel == NULL)
5037 		goto cyttsp5_device_access_probe_cm_data_panel_failed;
5038 
5039 	cmcp_info->cp_tx_data_panel =
5040 		kzalloc(tx_num * sizeof(int32_t), GFP_KERNEL);
5041 	if (cmcp_info->cp_tx_data_panel == NULL)
5042 		goto cyttsp5_device_access_probe_cp_tx_data_panel_failed;
5043 
5044 	cmcp_info->cp_tx_cal_data_panel =
5045 		kzalloc(tx_num * sizeof(int32_t), GFP_KERNEL);
5046 	if (cmcp_info->cp_tx_cal_data_panel == NULL)
5047 		goto cyttsp5_device_access_probe_cp_tx_cal_data_panel_failed;
5048 
5049 	cmcp_info->cp_rx_data_panel =
5050 		 kzalloc(rx_num * sizeof(int32_t), GFP_KERNEL);
5051 	if (cmcp_info->cp_rx_data_panel == NULL)
5052 		goto cyttsp5_device_access_probe_cp_rx_data_panel_failed;
5053 
5054 	cmcp_info->cp_rx_cal_data_panel =
5055 		 kzalloc(rx_num * sizeof(int32_t), GFP_KERNEL);
5056 	if (cmcp_info->cp_rx_cal_data_panel == NULL)
5057 		goto cyttsp5_device_access_probe_cp_rx_cal_data_panel_failed;
5058 
5059 	cmcp_info->cm_btn_data = kcalloc(btn_num, sizeof(int32_t), GFP_KERNEL);
5060 	if (cmcp_info->cm_btn_data == NULL)
5061 		goto cyttsp5_device_access_probe_cm_btn_data_failed;
5062 
5063 	cmcp_info->cp_btn_data = kcalloc(btn_num, sizeof(int32_t), GFP_KERNEL);
5064 	if (cmcp_info->cp_btn_data == NULL)
5065 		goto cyttsp5_device_access_probe_cp_btn_data_failed;
5066 
5067 	cmcp_info->cm_sensor_column_delta =
5068 		 kzalloc(rx_num * tx_num * sizeof(int32_t), GFP_KERNEL);
5069 	if (cmcp_info->cm_sensor_column_delta == NULL)
5070 		goto cyttsp5_device_access_probe_cm_sensor_column_delta_failed;
5071 
5072 	cmcp_info->cm_sensor_row_delta =
5073 		 kzalloc(tx_num * rx_num  * sizeof(int32_t), GFP_KERNEL);
5074 	if (cmcp_info->cm_sensor_row_delta == NULL)
5075 		goto cyttsp5_device_access_probe_cm_sensor_row_delta_failed;
5076 
5077 	mutex_init(&dad->sysfs_lock);
5078 	mutex_init(&dad->cmcp_threshold_lock);
5079 	dad->dev = dev;
5080 #ifdef TTHE_TUNER_SUPPORT
5081 	mutex_init(&dad->debugfs_lock);
5082 	dad->heatmap.num_element = 200;
5083 #endif
5084 	*data = dad;
5085 
5086 	dad->test_field_array = test_case_field_array;
5087 	dad->test_search_array = test_case_search_array;
5088 	dad->test_executed = 0;
5089 
5090 	init_completion(&dad->builtin_cmcp_threshold_complete);
5091 
5092 	/* get sysinfo */
5093 	dad->si = cmd->request_sysinfo(dev);
5094 	if (dad->si) {
5095 		rc = cyttsp5_setup_sysfs(dev);
5096 		if (rc)
5097 			goto cyttsp5_device_access_setup_sysfs_failed;
5098 	} else {
5099 		dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
5100 				__func__, dad->si);
5101 		cmd->subscribe_attention(dev, CY_ATTEN_STARTUP,
5102 			CYTTSP5_DEVICE_ACCESS_NAME,
5103 			cyttsp5_setup_sysfs_attention, 0);
5104 	}
5105 
5106 	INIT_WORK(&dad->cmcp_threshold_update,
5107 		cyttsp5_parse_cmcp_threshold_builtin);
5108 	schedule_work(&dad->cmcp_threshold_update);
5109 
5110 	return 0;
5111 
5112 cyttsp5_device_access_setup_sysfs_failed:
5113 	kfree(cmcp_info->cm_sensor_row_delta);
5114 cyttsp5_device_access_probe_cm_sensor_row_delta_failed:
5115 	kfree(cmcp_info->cm_sensor_column_delta);
5116 cyttsp5_device_access_probe_cm_sensor_column_delta_failed:
5117 	kfree(cmcp_info->cp_btn_data);
5118 cyttsp5_device_access_probe_cp_btn_data_failed:
5119 	kfree(cmcp_info->cm_btn_data);
5120 cyttsp5_device_access_probe_cm_btn_data_failed:
5121 	kfree(cmcp_info->cp_rx_cal_data_panel);
5122 cyttsp5_device_access_probe_cp_rx_cal_data_panel_failed:
5123 	kfree(cmcp_info->cp_rx_data_panel);
5124 cyttsp5_device_access_probe_cp_rx_data_panel_failed:
5125 	kfree(cmcp_info->cp_tx_cal_data_panel);
5126 cyttsp5_device_access_probe_cp_tx_cal_data_panel_failed:
5127 	kfree(cmcp_info->cp_tx_data_panel);
5128 cyttsp5_device_access_probe_cp_tx_data_panel_failed:
5129 	kfree(cmcp_info->cm_data_panel);
5130 cyttsp5_device_access_probe_cm_data_panel_failed:
5131 	kfree(cmcp_info->gd_sensor_row);
5132 cyttsp5_device_access_probe_gd_sensor_row_failed:
5133 	kfree(cmcp_info->gd_sensor_col);
5134 cyttsp5_device_access_probe_gd_sensor_col_failed:
5135 	kfree(test_case_search_array);
5136 cyttsp5_device_access_probe_search_array_failed:
5137 	kfree(test_case_field_array);
5138 cyttsp5_device_access_probe_field_array_failed:
5139 	kfree(result);
5140 cyttsp5_device_access_probe_result_failed:
5141 	kfree(cmcp_info);
5142 cyttsp5_device_access_probe_cmcp_info_failed:
5143 	kfree(configurations);
5144 cyttsp5_device_access_probe_configs_failed:
5145 	kfree(dad);
5146 cyttsp5_device_access_probe_data_failed:
5147 	dev_err(dev, "%s failed.\n", __func__);
5148 	return rc;
5149 }
5150 
cyttsp5_device_access_release(struct device * dev,void * data)5151 static void cyttsp5_device_access_release(struct device *dev, void *data)
5152 {
5153 	struct cyttsp5_device_access_data *dad = data;
5154 
5155 	if (dad->sysfs_nodes_created) {
5156 		device_remove_file(dev, &dev_attr_command);
5157 		device_remove_file(dev, &dev_attr_status);
5158 		device_remove_file(dev, &dev_attr_response);
5159 		debugfs_remove(dad->cmcp_results_debugfs);
5160 		debugfs_remove_recursive(dad->base_dentry);
5161 #ifdef TTHE_TUNER_SUPPORT
5162 		debugfs_remove(dad->tthe_get_panel_data_debugfs);
5163 #endif
5164 		device_remove_file(dev, &dev_attr_cmcp_test);
5165 		device_remove_file(dev, &dev_attr_cmcp_threshold_loading);
5166 		device_remove_bin_file(dev, &bin_attr_cmcp_threshold_data);
5167 		kfree(dad->cmcp_threshold_data);
5168 	} else {
5169 		cmd->unsubscribe_attention(dev, CY_ATTEN_STARTUP,
5170 			CYTTSP5_DEVICE_ACCESS_NAME,
5171 			cyttsp5_setup_sysfs_attention, 0);
5172 	}
5173 
5174 	kfree(dad->test_search_array);
5175 	kfree(dad->test_field_array);
5176 	kfree(dad->configs);
5177 	cyttsp5_free_cmcp_buf(dad->cmcp_info);
5178 	kfree(dad->cmcp_info);
5179 	kfree(dad->result);
5180 	kfree(dad);
5181 }
5182 
5183 static struct cyttsp5_module device_access_module = {
5184 	.name = CYTTSP5_DEVICE_ACCESS_NAME,
5185 	.probe = cyttsp5_device_access_probe,
5186 	.release = cyttsp5_device_access_release,
5187 };
5188 
cyttsp5_device_access_init(void)5189 static int __init cyttsp5_device_access_init(void)
5190 {
5191 	int rc;
5192 
5193 	cmd = cyttsp5_get_commands();
5194 	if (!cmd)
5195 		return -EINVAL;
5196 
5197 	rc = cyttsp5_register_module(&device_access_module);
5198 	if (rc < 0) {
5199 		pr_err("%s: Error, failed registering module\n",
5200 			__func__);
5201 			return rc;
5202 	}
5203 
5204 	pr_info("%s: Parade TTSP Device Access Driver (Built %s) rc=%d\n",
5205 		 __func__, CY_DRIVER_VERSION, rc);
5206 	return 0;
5207 }
5208 module_init(cyttsp5_device_access_init);
5209 
cyttsp5_device_access_exit(void)5210 static void __exit cyttsp5_device_access_exit(void)
5211 {
5212 	cyttsp5_unregister_module(&device_access_module);
5213 }
5214 module_exit(cyttsp5_device_access_exit);
5215 
5216 MODULE_LICENSE("GPL");
5217 MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Device Access Driver");
5218 MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");
5219 
5220