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