summaryrefslogtreecommitdiff
path: root/goodix_ts_proc.c
diff options
context:
space:
mode:
authorWendly Li <wendlyli@google.com>2022-02-23 16:35:22 +0000
committerWendly Li <wendlyli@google.com>2022-02-23 16:42:51 +0000
commitccb598ed429baf2522cacef90fc27ef6af8ca39f (patch)
tree0f2bca6e44dfcef82a435bc44661f1051799280c /goodix_ts_proc.c
parent1437c5883fe85a5e543371f37d376c5a2c3f7ab7 (diff)
downloadgoodix_touch-ccb598ed429baf2522cacef90fc27ef6af8ca39f.tar.gz
Import v1.0.3 driver
- Improve test APIs - Fix set_scan_mode API - Add continue mode API Bug: 214118804 Test: Check APIs works properly Change-Id: I0610c41fac5bc38758fde1221fe1602bbfa7595c Signed-off-by: Wendly Li <wendlyli@google.com>
Diffstat (limited to 'goodix_ts_proc.c')
-rw-r--r--goodix_ts_proc.c1844
1 files changed, 1756 insertions, 88 deletions
diff --git a/goodix_ts_proc.c b/goodix_ts_proc.c
index 43955cb..d4f58d9 100644
--- a/goodix_ts_proc.c
+++ b/goodix_ts_proc.c
@@ -6,7 +6,10 @@
#define CMD_FW_UPDATE "fw_update"
#define CMD_AUTO_TEST "auto_test"
+#define CMD_OPEN_TEST "open_test"
+#define CMD_SELF_OPEN_TEST "self_open_test"
#define CMD_NOISE_TEST "noise_test"
+#define CMD_SHORT_TEST "short_test"
#define CMD_GET_PACKAGE_ID "get_package_id"
#define CMD_GET_VERSION "get_version"
#define CMD_GET_RAWDATA "get_raw"
@@ -22,19 +25,713 @@
#define CMD_SET_ESD_ENABLE "set_esd_enable"
#define CMD_SET_DEBUG_LOG "set_debug_log"
#define CMD_SET_SCAN_MODE "set_scan_mode"
+#define CMD_SET_CONTINUE_MODE "set_continue_mode"
#define CMD_GET_CHANNEL_NUM "get_channel_num"
#define CMD_GET_TX_FREQ "get_tx_freq"
#define CMD_RESET "reset"
#define CMD_SET_SENSE_ENABLE "set_sense_enable"
+/* test limits keyword */
+#define CSV_TP_SPECIAL_RAW_MIN "special_raw_min"
+#define CSV_TP_SPECIAL_RAW_MAX "special_raw_max"
+#define CSV_TP_SPECIAL_RAW_DELTA "special_raw_delta"
+#define CSV_TP_SHORT_THRESHOLD "shortciurt_threshold"
+#define CSV_TP_SPECIAL_SELFRAW_MAX "special_selfraw_max"
+#define CSV_TP_SPECIAL_SELFRAW_MIN "special_selfraw_min"
+#define CSV_TP_NOISE_LIMIT "noise_data_limit"
+#define CSV_TP_SELFNOISE_LIMIT "noise_selfdata_limit"
+#define CSV_TP_TEST_CONFIG "test_config"
+
#define SHORT_SIZE 100
#define LARGE_SIZE 4096
+#define HUGE_SIZE 100 * 1024
static struct goodix_ts_core *cd;
static char wbuf[SHORT_SIZE];
static char *rbuf;
static uint32_t index;
+/* factory test */
#define ABS(x) ((x >= 0) ? x : -x)
+#define MAX(a, b) ((a > b) ? a : b)
+
+#define GTP_CAP_TEST 1
+#define GTP_DELTA_TEST 2
+#define GTP_NOISE_TEST 3
+#define GTP_SHORT_TEST 5
+#define GTP_SELFCAP_TEST 6
+#define GTP_SELFNOISE_TEST 7
+#define MAX_TEST_ITEMS 10 /* 0P-1P-2P-3P-5P total test items */
+
+#define TEST_OK 1
+#define TEST_NG 0
+
+#define MAX_LINE_LEN (1024 * 6)
+#define MAX_FRAME_CNT 16
+#define MAX_DRV_NUM 17
+#define MAX_SEN_NUM 35
+#define MAX_SHORT_NUM 15
+
+typedef struct __attribute__((packed)) {
+ u8 result;
+ u8 drv_drv_num;
+ u8 sen_sen_num;
+ u8 drv_sen_num;
+ u8 drv_gnd_avdd_num;
+ u8 sen_gnd_avdd_num;
+ u16 checksum;
+} test_result_t;
+
+/* nottingham drv-sen map */
+static u8 not_drv_map[] = { 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51 };
+
+static u8 not_sen_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34 };
+
+struct ts_short_res {
+ u8 short_num;
+ s16 short_msg[4 * MAX_SHORT_NUM];
+};
+
+struct ts_test_rawdata {
+ s16 data[MAX_DRV_NUM * MAX_SEN_NUM];
+ u32 size;
+};
+
+struct ts_test_self_rawdata {
+ s16 data[MAX_DRV_NUM + MAX_SEN_NUM];
+ u32 size;
+};
+
+struct goodix_ts_test {
+ bool item[MAX_TEST_ITEMS];
+ char result[MAX_TEST_ITEMS];
+ s16 min_limits[MAX_DRV_NUM * MAX_SEN_NUM];
+ s16 max_limits[MAX_DRV_NUM * MAX_SEN_NUM];
+ s16 deviation_limits[MAX_DRV_NUM * MAX_SEN_NUM];
+ s16 self_max_limits[MAX_DRV_NUM + MAX_SEN_NUM];
+ s16 self_min_limits[MAX_DRV_NUM + MAX_SEN_NUM];
+ s16 noise_threshold;
+ s16 short_threshold;
+ s16 r_drv_drv_threshold;
+ s16 r_drv_sen_threshold;
+ s16 r_sen_sen_threshold;
+ s16 r_drv_gnd_threshold;
+ s16 r_sen_gnd_threshold;
+ s16 avdd_value;
+
+ int freq;
+ int raw_data_cnt;
+ struct ts_test_rawdata rawdata[MAX_FRAME_CNT];
+ struct ts_test_rawdata deltadata[MAX_FRAME_CNT];
+ int noise_data_cnt;
+ struct ts_test_rawdata noisedata[MAX_FRAME_CNT];
+ struct ts_test_self_rawdata selfrawdata;
+ struct ts_short_res short_res;
+};
+static struct goodix_ts_test *ts_test;
+
+static int malloc_test_resource(void)
+{
+ ts_test = kzalloc(sizeof(*ts_test), GFP_KERNEL);
+ if (!ts_test)
+ return -ENOMEM;
+ return 0;
+}
+
+static void release_test_resource(void)
+{
+ kfree(ts_test);
+ ts_test = NULL;
+}
+
+#define CHN_VDD 0xFF
+#define CHN_GND 0x7F
+#define DRV_CHANNEL_FLAG 0x80
+#define SHORT_TEST_TIME_REG_NOT 0x1479E
+#define SHORT_TEST_STATUS_REG_NOT 0x13400
+#define SHORT_TEST_RESULT_REG_NOT 0x13408
+#define DRV_DRV_SELFCODE_REG_NOT 0x13446
+#define SEN_SEN_SELFCODE_REG_NOT 0x136EE
+#define DRV_SEN_SELFCODE_REG_NOT 0x14152
+#define DIFF_CODE_DATA_REG_NOT 0x14734
+#define CAL_CHAN_TO_CHAN_RES(v1, v2) (v1 / v2 - 1) * 55 + 45
+#define CAL_CHAN_TO_AVDD_RES(v1, v2) 64 * (2 * v2 - 25) * 76 / v1 - 15
+#define CAL_CHAN_TO_GND_RES(v) 120000 / v - 16
+static u32 map_die2pin(u32 chn_num)
+{
+ int i = 0;
+ u32 res = 255;
+
+ if (chn_num & DRV_CHANNEL_FLAG)
+ chn_num = (chn_num & ~DRV_CHANNEL_FLAG) + MAX_SEN_NUM;
+
+ for (i = 0; i < MAX_SEN_NUM; i++) {
+ if (not_sen_map[i] == chn_num) {
+ res = i;
+ break;
+ }
+ }
+ /* res != 255 mean found the corresponding channel num */
+ if (res != 255)
+ return res;
+ /* if cannot find in SenMap try find in DrvMap */
+ for (i = 0; i < MAX_DRV_NUM; i++) {
+ if (not_drv_map[i] == chn_num) {
+ res = i;
+ break;
+ }
+ }
+ if (i >= MAX_DRV_NUM)
+ ts_err("Faild found corrresponding channel num:%d", chn_num);
+ else
+ res |= DRV_CHANNEL_FLAG;
+
+ return res;
+}
+
+static void goodix_save_short_res(u16 chn1, u16 chn2, int r)
+{
+ int i;
+ u8 repeat_cnt = 0;
+ u8 repeat = 0;
+ struct ts_short_res *short_res = &ts_test->short_res;
+
+ if (chn1 == chn2 || short_res->short_num >= MAX_SHORT_NUM)
+ return;
+
+ for (i = 0; i < short_res->short_num; i++) {
+ repeat_cnt = 0;
+ if (short_res->short_msg[4 * i] == chn1)
+ repeat_cnt++;
+ if (short_res->short_msg[4 * i] == chn2)
+ repeat_cnt++;
+ if (short_res->short_msg[4 * i + 1] == chn1)
+ repeat_cnt++;
+ if (short_res->short_msg[4 * i + 1] == chn2)
+ repeat_cnt++;
+ if (repeat_cnt >= 2) {
+ repeat = 1;
+ break;
+ }
+ }
+ if (repeat == 0) {
+ short_res->short_msg[4 * short_res->short_num + 0] = chn1;
+ short_res->short_msg[4 * short_res->short_num + 1] = chn2;
+ short_res->short_msg[4 * short_res->short_num + 2] =
+ (r >> 8) & 0xFF;
+ short_res->short_msg[4 * short_res->short_num + 3] = r & 0xFF;
+ if (short_res->short_num < MAX_SHORT_NUM)
+ short_res->short_num++;
+ }
+}
+
+static int gdix_check_tx_tx_shortcircut(u8 short_ch_num)
+{
+ int ret = 0, err = 0;
+ u32 r_threshold = 0, short_r = 0;
+ int size = 0, i = 0, j = 0;
+ u16 adc_signal = 0;
+ u8 master_pin_num, slave_pin_num;
+ u8 *data_buf;
+ u32 data_reg = DRV_DRV_SELFCODE_REG_NOT;
+ int max_drv_num = MAX_DRV_NUM;
+ int max_sen_num = MAX_SEN_NUM;
+ u16 self_capdata, short_die_num = 0;
+
+ size = 4 + max_drv_num * 2 + 2;
+ data_buf = kzalloc(size, GFP_KERNEL);
+ if (!data_buf) {
+ ts_err("Failed to alloc memory");
+ return -ENOMEM;
+ }
+ /* drv&drv shortcircut check */
+ for (i = 0; i < short_ch_num; i++) {
+ ret = cd->hw_ops->read(cd, data_reg, data_buf, size);
+ if (ret < 0) {
+ ts_err("Failed read Drv-to-Drv short rawdata");
+ err = -EINVAL;
+ break;
+ }
+
+ if (checksum_cmp(data_buf, size, CHECKSUM_MODE_U8_LE)) {
+ ts_err("Drv-to-Drv adc data checksum error");
+ err = -EINVAL;
+ break;
+ }
+
+ r_threshold = ts_test->r_drv_drv_threshold;
+ short_die_num = le16_to_cpup((__le16 *)&data_buf[0]);
+ short_die_num -= max_sen_num;
+ if (short_die_num >= max_drv_num) {
+ ts_info("invalid short pad num:%d",
+ short_die_num + max_sen_num);
+ continue;
+ }
+
+ /* TODO: j start position need recheck */
+ self_capdata = le16_to_cpup((__le16 *)&data_buf[2]);
+ if (self_capdata == 0xffff || self_capdata == 0) {
+ ts_info("invalid self_capdata:0x%x", self_capdata);
+ continue;
+ }
+
+ for (j = short_die_num + 1; j < max_drv_num; j++) {
+ adc_signal =
+ le16_to_cpup((__le16 *)&data_buf[4 + j * 2]);
+
+ if (adc_signal < ts_test->short_threshold)
+ continue;
+
+ short_r =
+ CAL_CHAN_TO_CHAN_RES(self_capdata, adc_signal);
+ if (short_r < r_threshold) {
+ master_pin_num = map_die2pin(
+ short_die_num + max_sen_num);
+ slave_pin_num = map_die2pin(j + max_sen_num);
+ if (master_pin_num == 0xFF ||
+ slave_pin_num == 0xFF) {
+ ts_info("WARNNING invalid pin");
+ continue;
+ }
+ goodix_save_short_res(
+ master_pin_num, slave_pin_num, short_r);
+ ts_err("short circut:R=%dK,R_Threshold=%dK",
+ short_r, r_threshold);
+ ts_err("%s%d--%s%d shortcircut",
+ (master_pin_num & DRV_CHANNEL_FLAG)
+ ? "DRV"
+ : "SEN",
+ (master_pin_num & ~DRV_CHANNEL_FLAG),
+ (slave_pin_num & DRV_CHANNEL_FLAG)
+ ? "DRV"
+ : "SEN",
+ (slave_pin_num & ~DRV_CHANNEL_FLAG));
+ err = -EINVAL;
+ }
+ }
+ data_reg += size;
+ }
+
+ kfree(data_buf);
+ return err;
+}
+
+static int gdix_check_rx_rx_shortcircut(u8 short_ch_num)
+{
+ int ret = 0, err = 0;
+ u32 r_threshold = 0, short_r = 0;
+ int size = 0, i = 0, j = 0;
+ u16 adc_signal = 0;
+ u8 master_pin_num, slave_pin_num;
+ u8 *data_buf;
+ u32 data_reg = SEN_SEN_SELFCODE_REG_NOT;
+ int max_sen_num = MAX_SEN_NUM;
+ u16 self_capdata, short_die_num = 0;
+
+ size = 4 + max_sen_num * 2 + 2;
+ data_buf = kzalloc(size, GFP_KERNEL);
+ if (!data_buf) {
+ ts_err("Failed to alloc memory");
+ return -ENOMEM;
+ }
+ /* drv&drv shortcircut check */
+ for (i = 0; i < short_ch_num; i++) {
+ ret = cd->hw_ops->read(cd, data_reg, data_buf, size);
+ if (ret) {
+ ts_err("Failed read Sen-to-Sen short rawdata");
+ err = -EINVAL;
+ break;
+ }
+
+ if (checksum_cmp(data_buf, size, CHECKSUM_MODE_U8_LE)) {
+ ts_err("Sen-to-Sen adc data checksum error");
+ err = -EINVAL;
+ break;
+ }
+
+ r_threshold = ts_test->r_sen_sen_threshold;
+ short_die_num = le16_to_cpup((__le16 *)&data_buf[0]);
+ if (short_die_num >= max_sen_num) {
+ ts_info("invalid short pad num:%d", short_die_num);
+ continue;
+ }
+
+ /* TODO: j start position need recheck */
+ self_capdata = le16_to_cpup((__le16 *)&data_buf[2]);
+ if (self_capdata == 0xffff || self_capdata == 0) {
+ ts_info("invalid self_capdata:0x%x", self_capdata);
+ continue;
+ }
+
+ for (j = short_die_num + 1; j < max_sen_num; j++) {
+ adc_signal =
+ le16_to_cpup((__le16 *)&data_buf[4 + j * 2]);
+
+ if (adc_signal < ts_test->short_threshold)
+ continue;
+
+ short_r =
+ CAL_CHAN_TO_CHAN_RES(self_capdata, adc_signal);
+ if (short_r < r_threshold) {
+ master_pin_num = map_die2pin(short_die_num);
+ slave_pin_num = map_die2pin(j);
+ if (master_pin_num == 0xFF ||
+ slave_pin_num == 0xFF) {
+ ts_info("WARNNING invalid pin");
+ continue;
+ }
+ goodix_save_short_res(
+ master_pin_num, slave_pin_num, short_r);
+ ts_err("short circut:R=%dK,R_Threshold=%dK",
+ short_r, r_threshold);
+ ts_err("%s%d--%s%d shortcircut",
+ (master_pin_num & DRV_CHANNEL_FLAG)
+ ? "DRV"
+ : "SEN",
+ (master_pin_num & ~DRV_CHANNEL_FLAG),
+ (slave_pin_num & DRV_CHANNEL_FLAG)
+ ? "DRV"
+ : "SEN",
+ (slave_pin_num & ~DRV_CHANNEL_FLAG));
+ err = -EINVAL;
+ }
+ }
+ data_reg += size;
+ }
+
+ kfree(data_buf);
+ return err;
+}
+
+static int gdix_check_tx_rx_shortcircut(u8 short_ch_num)
+{
+ int ret = 0, err = 0;
+ u32 r_threshold = 0, short_r = 0;
+ int size = 0, i = 0, j = 0;
+ u16 adc_signal = 0;
+ u8 master_pin_num, slave_pin_num;
+ u8 *data_buf = NULL;
+ u32 data_reg = DRV_SEN_SELFCODE_REG_NOT;
+ int max_drv_num = MAX_DRV_NUM;
+ int max_sen_num = MAX_SEN_NUM;
+ u16 self_capdata, short_die_num = 0;
+
+ size = 4 + max_drv_num * 2 + 2;
+ data_buf = kzalloc(size, GFP_KERNEL);
+ if (!data_buf) {
+ ts_err("Failed to alloc memory");
+ return -ENOMEM;
+ }
+ /* drv&sen shortcircut check */
+ for (i = 0; i < short_ch_num; i++) {
+ ret = cd->hw_ops->read(cd, data_reg, data_buf, size);
+ if (ret) {
+ ts_err("Failed read Drv-to-Sen short rawdata");
+ err = -EINVAL;
+ break;
+ }
+
+ if (checksum_cmp(data_buf, size, CHECKSUM_MODE_U8_LE)) {
+ ts_err("Drv-to-Sen adc data checksum error");
+ err = -EINVAL;
+ break;
+ }
+
+ r_threshold = ts_test->r_drv_sen_threshold;
+ short_die_num = le16_to_cpup((__le16 *)&data_buf[0]);
+ if (short_die_num >= max_sen_num) {
+ ts_info("invalid short pad num:%d", short_die_num);
+ continue;
+ }
+
+ /* TODO: j start position need recheck */
+ self_capdata = le16_to_cpup((__le16 *)&data_buf[2]);
+ if (self_capdata == 0xffff || self_capdata == 0) {
+ ts_info("invalid self_capdata:0x%x", self_capdata);
+ continue;
+ }
+
+ for (j = 0; j < max_drv_num; j++) {
+ adc_signal =
+ le16_to_cpup((__le16 *)&data_buf[4 + j * 2]);
+
+ if (adc_signal < ts_test->short_threshold)
+ continue;
+
+ short_r =
+ CAL_CHAN_TO_CHAN_RES(self_capdata, adc_signal);
+ if (short_r < r_threshold) {
+ master_pin_num = map_die2pin(short_die_num);
+ slave_pin_num = map_die2pin(j + max_sen_num);
+ if (master_pin_num == 0xFF ||
+ slave_pin_num == 0xFF) {
+ ts_info("WARNNING invalid pin");
+ continue;
+ }
+ goodix_save_short_res(
+ master_pin_num, slave_pin_num, short_r);
+ ts_err("short circut:R=%dK,R_Threshold=%dK",
+ short_r, r_threshold);
+ ts_err("%s%d--%s%d shortcircut",
+ (master_pin_num & DRV_CHANNEL_FLAG)
+ ? "DRV"
+ : "SEN",
+ (master_pin_num & ~DRV_CHANNEL_FLAG),
+ (slave_pin_num & DRV_CHANNEL_FLAG)
+ ? "DRV"
+ : "SEN",
+ (slave_pin_num & ~DRV_CHANNEL_FLAG));
+ err = -EINVAL;
+ }
+ }
+ data_reg += size;
+ }
+
+ kfree(data_buf);
+ return err;
+}
+
+static int gdix_check_resistance_to_gnd(u16 adc_signal, u32 pos)
+{
+ long r = 0;
+ u16 r_th = 0, avdd_value = 0;
+ u16 chn_id_tmp = 0;
+ u8 pin_num = 0;
+ unsigned short short_type;
+ int max_drv_num = MAX_DRV_NUM;
+ int max_sen_num = MAX_SEN_NUM;
+
+ avdd_value = ts_test->avdd_value;
+ short_type = adc_signal & 0x8000;
+ adc_signal &= ~0x8000;
+ if (adc_signal == 0)
+ adc_signal = 1;
+
+ if (short_type == 0) {
+ /* short to GND */
+ r = CAL_CHAN_TO_GND_RES(adc_signal);
+ } else {
+ /* short to VDD */
+ r = CAL_CHAN_TO_AVDD_RES(adc_signal, avdd_value);
+ }
+
+ if (pos < max_drv_num)
+ r_th = ts_test->r_drv_gnd_threshold;
+ else
+ r_th = ts_test->r_sen_gnd_threshold;
+
+ chn_id_tmp = pos;
+ if (chn_id_tmp < max_drv_num)
+ chn_id_tmp += max_sen_num;
+ else
+ chn_id_tmp -= max_drv_num;
+
+ if (r < r_th) {
+ pin_num = map_die2pin(chn_id_tmp);
+ goodix_save_short_res(
+ pin_num, short_type ? CHN_VDD : CHN_GND, r);
+ ts_err("%s%d shortcircut to %s,R=%ldK,R_Threshold=%dK",
+ (pin_num & DRV_CHANNEL_FLAG) ? "DRV" : "SEN",
+ (pin_num & ~DRV_CHANNEL_FLAG),
+ short_type ? "VDD" : "GND", r, r_th);
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int gdix_check_gndvdd_shortcircut(void)
+{
+ int ret = 0, err = 0;
+ int size = 0, i = 0;
+ u16 adc_signal = 0;
+ u32 data_reg = DIFF_CODE_DATA_REG_NOT;
+ u8 *data_buf = NULL;
+ int max_drv_num = MAX_DRV_NUM;
+ int max_sen_num = MAX_SEN_NUM;
+
+ size = (max_drv_num + max_sen_num) * 2 + 2;
+ data_buf = kzalloc(size, GFP_KERNEL);
+ if (!data_buf) {
+ ts_err("Failed to alloc memory");
+ return -ENOMEM;
+ }
+ /* read diff code, diff code will be used to calculate
+ * resistance between channel and GND */
+ ret = cd->hw_ops->read(cd, data_reg, data_buf, size);
+ if (ret < 0) {
+ ts_err("Failed read to-gnd rawdata");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ if (checksum_cmp(data_buf, size, CHECKSUM_MODE_U8_LE)) {
+ ts_err("diff code checksum error");
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ for (i = 0; i < max_drv_num + max_sen_num; i++) {
+ adc_signal = le16_to_cpup((__le16 *)&data_buf[i * 2]);
+ ret = gdix_check_resistance_to_gnd(adc_signal, i);
+ if (ret != 0) {
+ ts_err("Resistance to-gnd/vdd short");
+ err = ret;
+ }
+ }
+
+err_out:
+ kfree(data_buf);
+ return err;
+}
+
+static int goodix_shortcircut_analysis(void)
+{
+ int ret;
+ int err = 0;
+ test_result_t test_result;
+
+ ret = cd->hw_ops->read(cd, SHORT_TEST_RESULT_REG_NOT,
+ (u8 *)&test_result, sizeof(test_result));
+ if (ret < 0) {
+ ts_err("Read TEST_RESULT_REG failed");
+ return ret;
+ }
+
+ if (checksum_cmp((u8 *)&test_result, sizeof(test_result),
+ CHECKSUM_MODE_U8_LE)) {
+ ts_err("shrot result checksum err");
+ return -EINVAL;
+ }
+
+ if (!(test_result.result & 0x0F)) {
+ ts_info(">>>>> No shortcircut");
+ return 0;
+ }
+ ts_info("short flag 0x%02x, drv&drv:%d, sen&sen:%d, drv&sen:%d, drv/GNDVDD:%d, sen/GNDVDD:%d",
+ test_result.result, test_result.drv_drv_num,
+ test_result.sen_sen_num, test_result.drv_sen_num,
+ test_result.drv_gnd_avdd_num, test_result.sen_gnd_avdd_num);
+
+ if (test_result.drv_drv_num)
+ err |= gdix_check_tx_tx_shortcircut(test_result.drv_drv_num);
+ if (test_result.sen_sen_num)
+ err |= gdix_check_rx_rx_shortcircut(test_result.sen_sen_num);
+ if (test_result.drv_sen_num)
+ err |= gdix_check_tx_rx_shortcircut(test_result.drv_sen_num);
+ if (test_result.drv_gnd_avdd_num || test_result.sen_gnd_avdd_num)
+ err |= gdix_check_gndvdd_shortcircut();
+
+ ts_info(">>>>> short check return 0x%x", err);
+
+ return err;
+}
+
+#define INSPECT_FW_SWITCH_CMD 0x85
+#define SHORT_TEST_RUN_FLAG 0xAA
+#define SHORT_TEST_RUN_REG 0x10400
+static int goodix_short_test_prepare(void)
+{
+ struct goodix_ts_cmd tmp_cmd;
+ int ret;
+ int retry;
+ int resend = 3;
+ u8 status;
+
+ ts_info("short test prepare IN");
+ tmp_cmd.len = 4;
+ tmp_cmd.cmd = INSPECT_FW_SWITCH_CMD;
+
+resend_cmd:
+ ret = cd->hw_ops->send_cmd(cd, &tmp_cmd);
+ if (ret < 0) {
+ ts_err("send test mode failed");
+ return ret;
+ }
+
+ retry = 3;
+ while (retry--) {
+ msleep(40);
+ ret = cd->hw_ops->read(cd, SHORT_TEST_RUN_REG, &status, 1);
+ if (!ret && status == SHORT_TEST_RUN_FLAG)
+ return 0;
+ ts_info("short_mode_status=0x%02x ret=%d", status, ret);
+ }
+
+ if (resend--) {
+ cd->hw_ops->reset(cd, 100);
+ goto resend_cmd;
+ }
+
+ return -EINVAL;
+}
+
+#define MAX_TEST_TIME_MS 15000
+#define DEFAULT_TEST_TIME_MS 7000
+#define SHORT_TEST_FINISH_FLAG 0x88
+static int goodix_shortcircut_test(void)
+{
+ int ret = 0;
+ int res;
+ int retry;
+ u16 test_time;
+ u8 status;
+
+ ts_info("---------------------- short_test begin ----------------------");
+ ret = goodix_short_test_prepare();
+ if (ret < 0) {
+ ts_err("Failed enter short test mode");
+ return ret;
+ }
+
+ /* get short test time */
+ ret = cd->hw_ops->read(
+ cd, SHORT_TEST_TIME_REG_NOT, (u8 *)&test_time, 2);
+ if (ret < 0) {
+ ts_err("Failed to get test_time, default %dms",
+ DEFAULT_TEST_TIME_MS);
+ test_time = DEFAULT_TEST_TIME_MS;
+ } else {
+ if (test_time > MAX_TEST_TIME_MS) {
+ ts_info("test time too long %d > %d", test_time,
+ MAX_TEST_TIME_MS);
+ test_time = MAX_TEST_TIME_MS;
+ }
+ ts_info("get test time %dms", test_time);
+ }
+
+ /* start short test */
+ status = 0;
+ cd->hw_ops->write(cd, SHORT_TEST_RUN_REG, &status, 1);
+
+ /* wait short test finish */
+ msleep(test_time);
+ retry = 50;
+ while (retry--) {
+ ret = cd->hw_ops->read(
+ cd, SHORT_TEST_STATUS_REG_NOT, &status, 1);
+ if (!ret && status == SHORT_TEST_FINISH_FLAG)
+ break;
+ msleep(50);
+ }
+ if (retry < 0) {
+ ts_err("short test failed, status:0x%02x", status);
+ return -EINVAL;
+ }
+
+ /* start analysis short result */
+ ts_info("short_test finished, start analysis");
+ res = goodix_shortcircut_analysis();
+ if (res == 0) {
+ ts_test->result[GTP_SHORT_TEST] = TEST_OK;
+ ret = 0;
+ }
+
+ return ret;
+}
typedef struct __attribute__((packed)) {
uint32_t checksum;
@@ -167,6 +864,7 @@ static void seq_stop(struct seq_file *s, void *v)
kfree(rbuf);
rbuf = NULL;
index = 0;
+ release_test_resource();
}
}
@@ -186,78 +884,936 @@ static int driver_test_release(struct inode *inode, struct file *file)
return seq_release(inode, file);
}
-static int goodix_noise_test(uint16_t frame, int threshold)
+static void goodix_save_header(void)
+{
+ int i;
+ bool total_result = true;
+
+ index = sprintf(
+ &rbuf[index], "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ index += sprintf(&rbuf[index], "<TESTLOG>\n");
+ index += sprintf(&rbuf[index], "<Header>\n");
+ /* sava test result */
+ for (i = 0; i < MAX_TEST_ITEMS; i++) {
+ if (ts_test->item[i] && ts_test->result[i] == TEST_NG)
+ total_result = false;
+ }
+ if (total_result == false) {
+ index += sprintf(&rbuf[index], "<Result>NG</Result>\n");
+ } else {
+ index += sprintf(&rbuf[index], "<Result>OK</Result>\n");
+ }
+
+ index += sprintf(&rbuf[index], "<DeviceType>GT%s</DeviceType>\n",
+ cd->fw_version.patch_pid);
+ index += sprintf(&rbuf[index], "<SensorId>%d</SensorId>\n",
+ cd->fw_version.sensor_id);
+ index += sprintf(&rbuf[index], "</Header>\n");
+
+ index += sprintf(&rbuf[index], "<ItemList>\n");
+ if (ts_test->item[GTP_CAP_TEST]) {
+ if (ts_test->result[GTP_CAP_TEST] == TEST_NG) {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Rawdata MAX/MIN Test\" result=\"NG\"/>\n");
+ } else {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Rawdata MAX/MIN Test\" result=\"OK\"/>\n");
+ }
+ if (ts_test->result[GTP_DELTA_TEST] == TEST_NG) {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Rawdata Adjcent Deviation Test\" result=\"NG\"/>\n");
+ } else {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Rawdata Adjcent Deviation Test\" result=\"OK\"/>\n");
+ }
+ }
+
+ if (ts_test->item[GTP_NOISE_TEST]) {
+ if (ts_test->result[GTP_NOISE_TEST] == TEST_NG) {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Diffdata Jitter Test\" result=\"NG\"/>\n");
+ } else {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Diffdata Jitter Test\" result=\"OK\"/>\n");
+ }
+ }
+
+ if (ts_test->item[GTP_SELFCAP_TEST]) {
+ if (ts_test->result[GTP_SELFCAP_TEST] == TEST_NG) {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Self Rawdata Upper Limit Test\" result=\"NG\"/>\n");
+ } else {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Self Rawdata Upper Limit Test\" result=\"OK\"/>\n");
+ }
+ }
+
+ if (ts_test->item[GTP_SHORT_TEST]) {
+ if (ts_test->result[GTP_SHORT_TEST] == TEST_NG) {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Short Test\" result=\"NG\"/>\n");
+ } else {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Short Test\" result=\"OK\"/>\n");
+ }
+ }
+ index += sprintf(&rbuf[index], "</ItemList>\n");
+}
+
+static void goodix_save_limits(void)
+{
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ int i;
+ int chn1;
+ int chn2;
+ int r;
+
+ index += sprintf(&rbuf[index], "<TestItems>\n");
+
+ /* save short result */
+ if (ts_test->item[GTP_SHORT_TEST]) {
+ index += sprintf(&rbuf[index], "<Item name=\"Short Test\">\n");
+ index += sprintf(&rbuf[index], "<ShortNum>%d</ShortNum>\n",
+ ts_test->short_res.short_num);
+ for (i = 0; i < ts_test->short_res.short_num; i++) {
+ chn1 = ts_test->short_res.short_msg[4 * i];
+ chn2 = ts_test->short_res.short_msg[4 * i + 1];
+ r = (ts_test->short_res.short_msg[4 * i + 2] << 8) +
+ ts_test->short_res.short_msg[4 * i + 3];
+ if (chn1 == CHN_VDD)
+ index += sprintf(&rbuf[index],
+ "<ShortMess Chn1=\"VDD\" ");
+ else if (chn1 == CHN_GND)
+ index += sprintf(&rbuf[index],
+ "<ShortMess Chn1=\"GND\" ");
+ else if (chn1 & DRV_CHANNEL_FLAG)
+ index += sprintf(&rbuf[index],
+ "<ShortMess Chn1=\"Tx%d\" ",
+ chn1 & 0x7f);
+ else
+ index += sprintf(&rbuf[index],
+ "<ShortMess Chn1=\"Rx%d\" ",
+ chn1 & 0x7f);
+ if (chn2 == CHN_VDD)
+ index += sprintf(&rbuf[index],
+ "Chn2=\"VDD\" ShortResistor= \"%dKom\"/>\n",
+ r);
+ else if (chn2 == CHN_GND)
+ index += sprintf(&rbuf[index],
+ "Chn2=\"GND\" ShortResistor= \"%dKom\"/>\n",
+ r);
+ else if (chn2 & DRV_CHANNEL_FLAG)
+ index += sprintf(&rbuf[index],
+ "Chn2=\"Tx%d\" ShortResistor= \"%dKom\"/>\n",
+ chn2 & 0x7f, r);
+ else
+ index += sprintf(&rbuf[index],
+ "Chn2=\"Rx%d\" ShortResistor= \"%dKom\"/>\n",
+ chn2 & 0x7f, r);
+ }
+ index += sprintf(&rbuf[index], "</Item>\n");
+ }
+
+ /* save open limits */
+ if (ts_test->item[GTP_CAP_TEST]) {
+ index += sprintf(
+ &rbuf[index], "<Item name=\"Rawdata Test Sets\">\n");
+ index += sprintf(&rbuf[index],
+ "<TotalFrameCnt>%d</TotalFrameCnt>\n",
+ ts_test->raw_data_cnt);
+ /* rawdata max limit */
+ index += sprintf(&rbuf[index], "<MaxRawLimit>\n");
+ for (i = 0; i < tx * rx; i++) {
+ index += sprintf(
+ &rbuf[index], "%d,", ts_test->max_limits[i]);
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ index += sprintf(&rbuf[index], "</MaxRawLimit>\n");
+ /* rawdata min limit */
+ index += sprintf(&rbuf[index], "<MinRawLimit>\n");
+ for (i = 0; i < tx * rx; i++) {
+ index += sprintf(
+ &rbuf[index], "%d,", ts_test->min_limits[i]);
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ index += sprintf(&rbuf[index], "</MinRawLimit>\n");
+ /* Max Accord limit */
+ index += sprintf(&rbuf[index], "<MaxAccordLimit>\n");
+ for (i = 0; i < tx * rx; i++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->deviation_limits[i]);
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ index += sprintf(&rbuf[index], "</MaxAccordLimit>\n");
+ index += sprintf(&rbuf[index], "</Item>\n");
+ }
+
+ /* save noise limit */
+ if (ts_test->item[GTP_NOISE_TEST]) {
+ index += sprintf(
+ &rbuf[index], "<Item name=\"Diffdata Test Sets\">\n");
+ index += sprintf(&rbuf[index],
+ "<TotalFrameCnt>%d</TotalFrameCnt>\n",
+ ts_test->noise_data_cnt);
+ index += sprintf(&rbuf[index],
+ "<MaxJitterLimit>%d</MaxJitterLimit>\n",
+ ts_test->noise_threshold);
+ index += sprintf(&rbuf[index], "</Item>\n");
+ }
+
+ /* save self rawdata limit */
+ if (ts_test->item[GTP_SELFCAP_TEST]) {
+ index += sprintf(&rbuf[index],
+ "<Item name=\"Self Rawdata Test Sets\">\n");
+ index += sprintf(
+ &rbuf[index], "<TotalFrameCnt>1</TotalFrameCnt>\n");
+ index += sprintf(&rbuf[index], "<MaxRawLimit>\n");
+ for (i = 0; i < tx + rx; i++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->self_max_limits[i]);
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ if ((tx + rx) % tx != 0)
+ index += sprintf(&rbuf[index], "\n");
+ index += sprintf(&rbuf[index], "</MaxRawLimit>\n");
+ index += sprintf(&rbuf[index], "<MinRawLimit>\n");
+ for (i = 0; i < tx + rx; i++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->self_min_limits[i]);
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ if ((tx + rx) % tx != 0)
+ index += sprintf(&rbuf[index], "\n");
+ index += sprintf(&rbuf[index], "</MinRawLimit>\n");
+ index += sprintf(&rbuf[index], "</Item>\n");
+ }
+
+ index += sprintf(&rbuf[index], "</TestItems>\n");
+}
+
+static void goodix_data_cal(s16 *data, size_t data_size, s16 *stat_result)
+{
+ int i = 0;
+ s16 avg = 0;
+ s16 min = 0;
+ s16 max = 0;
+ long long sum = 0;
+
+ min = data[0];
+ max = data[0];
+ for (i = 0; i < data_size; i++) {
+ sum += data[i];
+ if (max < data[i])
+ max = data[i];
+ if (min > data[i])
+ min = data[i];
+ }
+ avg = div_s64(sum, data_size);
+ stat_result[0] = avg;
+ stat_result[1] = max;
+ stat_result[2] = min;
+}
+
+static void goodix_save_data(void)
{
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ s16 stat_result[3];
+ int i, j;
+
+ index += sprintf(&rbuf[index], "<DataRecord>\n");
+
+ /* save rawdata */
+ if (ts_test->item[GTP_CAP_TEST]) {
+ index += sprintf(&rbuf[index], "<RawDataRecord>\n");
+ for (i = 0; i < ts_test->raw_data_cnt; i++) {
+ goodix_data_cal(
+ ts_test->rawdata[i].data, tx * rx, stat_result);
+ index += sprintf(&rbuf[index],
+ "<DataContent No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ i, tx * rx, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (j = 0; j < tx * rx; j++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->rawdata[i].data[j]);
+ if ((j + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ index += sprintf(&rbuf[index], "</DataContent>\n");
+ goodix_data_cal(ts_test->deltadata[i].data, tx * rx,
+ stat_result);
+ index += sprintf(&rbuf[index],
+ "<RawAccord No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ i, tx * rx, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (j = 0; j < tx * rx; j++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->deltadata[i].data[j]);
+ if ((j + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ index += sprintf(&rbuf[index], "</RawAccord>\n");
+ }
+ index += sprintf(&rbuf[index], "</RawDataRecord>\n");
+ }
+
+ /* save noisedata */
+ if (ts_test->item[GTP_NOISE_TEST]) {
+ index += sprintf(&rbuf[index], "<DiffDataRecord>\n");
+ for (i = 0; i < ts_test->noise_data_cnt; i++) {
+ goodix_data_cal(ts_test->noisedata[i].data, tx * rx,
+ stat_result);
+ index += sprintf(&rbuf[index],
+ "<DataContent No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ i, tx * rx, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (j = 0; j < tx * rx; j++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->noisedata[i].data[j]);
+ if ((j + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ index += sprintf(&rbuf[index], "</DataContent>\n");
+ }
+ index += sprintf(&rbuf[index], "</DiffDataRecord>\n");
+ }
+
+ /* save self rawdata */
+ if (ts_test->item[GTP_SELFCAP_TEST]) {
+ index += sprintf(&rbuf[index], "<selfDataRecord>\n");
+ goodix_data_cal(
+ ts_test->selfrawdata.data, tx + rx, stat_result);
+ index += sprintf(&rbuf[index],
+ "<DataContent No.=\"0\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ tx + rx, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (i = 0; i < tx + rx; i++) {
+ index += sprintf(&rbuf[index], "%d,",
+ ts_test->selfrawdata.data[i]);
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ if ((tx + rx) % tx != 0)
+ index += sprintf(&rbuf[index], "\n");
+ index += sprintf(&rbuf[index], "</DataContent>\n");
+ index += sprintf(&rbuf[index], "</selfDataRecord>\n");
+ }
+
+ index += sprintf(&rbuf[index], "</DataRecord>\n");
+}
+
+static void goodix_save_tail(void)
+{
+ index += sprintf(&rbuf[index], "</TESTLOG>\n");
+}
+
+static void goodix_save_test_result(void)
+{
+ goodix_save_header();
+ goodix_save_limits();
+ goodix_save_data();
+ goodix_save_tail();
+}
+
+static void goto_next_line(char **ptr)
+{
+ do {
+ *ptr = *ptr + 1;
+ } while (**ptr != '\n' && **ptr != '\0');
+ if (**ptr == '\0') {
+ return;
+ }
+ *ptr = *ptr + 1;
+}
+
+static void copy_this_line(char *dest, char *src)
+{
+ char *copy_from;
+ char *copy_to;
+
+ copy_from = src;
+ copy_to = dest;
+ do {
+ *copy_to = *copy_from;
+ copy_from++;
+ copy_to++;
+ } while ((*copy_from != '\n') && (*copy_from != '\r') &&
+ (*copy_from != '\0'));
+ *copy_to = '\0';
+}
+
+static int getrid_space(s8 *data, s32 len)
+{
+ u8 *buf = NULL;
+ s32 i;
+ u32 count = 0;
+
+ buf = (char *)kzalloc(len + 5, GFP_KERNEL);
+ if (buf == NULL) {
+ ts_err("get space kzalloc error");
+ return -ESRCH;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (data[i] == ' ' || data[i] == '\r' || data[i] == '\n') {
+ continue;
+ }
+ buf[count++] = data[i];
+ }
+
+ buf[count++] = '\0';
+
+ memcpy(data, buf, count);
+ kfree(buf);
+
+ return count;
+}
+
+static int parse_valid_data(
+ char *buf_start, loff_t buf_size, char *ptr, s16 *data, s32 rows)
+{
+ int i = 0;
+ int j = 0;
+ char *token = NULL;
+ char *tok_ptr = NULL;
+ char *row_data = NULL;
+ long temp_val;
+
+ if (!ptr || !data)
+ return -EINVAL;
+
+ row_data = (char *)kzalloc(MAX_LINE_LEN, GFP_KERNEL);
+ if (!row_data) {
+ ts_err("alloc index %d failed.", MAX_LINE_LEN);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < rows; i++) {
+ memset(row_data, 0, MAX_LINE_LEN);
+ copy_this_line(row_data, ptr);
+ getrid_space(row_data, strlen(row_data));
+ tok_ptr = row_data;
+ while ((token = strsep(&tok_ptr, ","))) {
+ if (strlen(token) == 0)
+ continue;
+ if (kstrtol(token, 0, &temp_val)) {
+ kfree(row_data);
+ return -EINVAL;
+ }
+ data[j++] = (s16)temp_val;
+ }
+ if (i == rows - 1)
+ break;
+ goto_next_line(&ptr); // next row
+ if (!ptr || (0 == strlen(ptr)) ||
+ (ptr >= (buf_start + buf_size))) {
+ ts_info("invalid ptr, return");
+ kfree(row_data);
+ row_data = NULL;
+ return -EPERM;
+ }
+ }
+ kfree(row_data);
+ return j;
+}
+
+static int parse_csvfile(
+ char *buf, size_t size, char *target_name, s16 *data, s32 rows, s32 col)
+{
+ char *ptr = NULL;
+
+ if (!data || !buf)
+ return -EIO;
+
+ ptr = buf;
+ ptr = strstr(ptr, target_name);
+ if (!ptr) {
+ ts_info("load %s failed 1, maybe not this item", target_name);
+ return -EINTR;
+ }
+
+ goto_next_line(&ptr);
+ if (!ptr || (0 == strlen(ptr))) {
+ ts_err("load %s failed 2!", target_name);
+ return -EIO;
+ }
+
+ return parse_valid_data(buf, size, ptr, data, rows);
+}
+
+static int goodix_obtain_testlimits(void)
+{
+ const struct firmware *firmware = NULL;
+ struct device *dev = &cd->pdev->dev;
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ char limit_file[100] = { 0 };
+ char *temp_buf = NULL;
+ s16 data_buf[7];
+ int ret;
+
+ sprintf(limit_file, "goodix_test_limits_%d.csv",
+ cd->fw_version.sensor_id);
+ ts_info("limit_file_name:%s", limit_file);
+
+ ret = request_firmware(&firmware, limit_file, dev);
+ if (ret < 0) {
+ ts_err("limits file [%s] not available", limit_file);
+ return -EINVAL;
+ }
+ if (firmware->size <= 0) {
+ ts_err("request_firmware, limits param length error,len:%zu",
+ firmware->size);
+ ret = -EINVAL;
+ goto exit_free;
+ }
+ temp_buf = kzalloc(firmware->size + 1, GFP_KERNEL);
+ if (!temp_buf) {
+ ret = -ENOMEM;
+ goto exit_free;
+ }
+ memcpy(temp_buf, firmware->data, firmware->size);
+
+ if (ts_test->item[GTP_CAP_TEST]) {
+ /* obtain mutual_raw min */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_SPECIAL_RAW_MIN, ts_test->min_limits, rx, tx);
+ if (ret < 0) {
+ ts_err("Failed get min_limits");
+ goto exit_free;
+ }
+ /* obtain mutual_raw max */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_SPECIAL_RAW_MAX, ts_test->max_limits, rx, tx);
+ if (ret < 0) {
+ ts_err("Failed get max_limits");
+ goto exit_free;
+ }
+ /* obtain delta limit */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_SPECIAL_RAW_DELTA, ts_test->deviation_limits, rx,
+ tx);
+ if (ret < 0) {
+ ts_err("Failed get delta limit");
+ goto exit_free;
+ }
+ }
+
+ if (ts_test->item[GTP_SELFCAP_TEST]) {
+ /* obtain self_raw min */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_SPECIAL_SELFRAW_MIN, ts_test->self_min_limits, 1,
+ tx + rx);
+ if (ret < 0) {
+ ts_err("Failed get self_min_limits");
+ goto exit_free;
+ }
+ /* obtain self_raw max */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_SPECIAL_SELFRAW_MAX, ts_test->self_max_limits, 1,
+ tx + rx);
+ if (ret < 0) {
+ ts_err("Failed get self_min_limits");
+ goto exit_free;
+ }
+ }
+
+ if (ts_test->item[GTP_NOISE_TEST]) {
+ /* obtain noise_threshold */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_NOISE_LIMIT, &ts_test->noise_threshold, 1, 1);
+ if (ret < 0) {
+ ts_err("Failed get noise limits");
+ goto exit_free;
+ }
+ }
+
+ if (ts_test->item[GTP_SHORT_TEST]) {
+ /* obtain short_params */
+ ret = parse_csvfile(temp_buf, firmware->size,
+ CSV_TP_SHORT_THRESHOLD, data_buf, 1, 7);
+ if (ret < 0) {
+ ts_err("Failed get short circuit limits");
+ goto exit_free;
+ }
+ ts_test->short_threshold = data_buf[0];
+ ts_test->r_drv_drv_threshold = data_buf[1];
+ ts_test->r_drv_sen_threshold = data_buf[2];
+ ts_test->r_sen_sen_threshold = data_buf[3];
+ ts_test->r_drv_gnd_threshold = data_buf[4];
+ ts_test->r_sen_gnd_threshold = data_buf[5];
+ ts_test->avdd_value = data_buf[6];
+ }
+
+exit_free:
+ kfree(temp_buf);
+ if (firmware)
+ release_firmware(firmware);
+ return ret;
+}
+
+static int goodix_delta_test(void)
+{
+ int i, j;
+ int max_val;
+ int raw;
+ int temp;
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ u32 data_size = tx * rx;
+ int ret = 0;
+
+ for (i = 0; i < ts_test->raw_data_cnt; i++) {
+ for (j = 0; j < data_size; j++) {
+ raw = ts_test->rawdata[i].data[j];
+ max_val = 0;
+ /* calcu delta with above node */
+ if (j - tx >= 0) {
+ temp = ts_test->rawdata[i].data[j - tx];
+ temp = ABS(temp - raw);
+ max_val = MAX(max_val, temp);
+ }
+ /* calcu delta with bellow node */
+ if (j + tx < data_size) {
+ temp = ts_test->rawdata[i].data[j + tx];
+ temp = ABS(temp - raw);
+ max_val = MAX(max_val, temp);
+ }
+ /* calcu delta with left node */
+ if (j % tx) {
+ temp = ts_test->rawdata[i].data[j - 1];
+ temp = ABS(temp - raw);
+ max_val = MAX(max_val, temp);
+ }
+ /* calcu delta with right node */
+ if ((j + 1) % tx) {
+ temp = ts_test->rawdata[i].data[j + 1];
+ temp = ABS(temp - raw);
+ max_val = MAX(max_val, temp);
+ }
+ temp = max_val * 1000 / raw;
+ ts_test->deltadata[i].data[j] = temp;
+ if (temp > ts_test->deviation_limits[j]) {
+ ts_err("delta_data[%d] > limits[%d]", temp,
+ ts_test->deviation_limits[j]);
+ ret = -EINVAL;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int goodix_open_test(void)
+{
+ unsigned char tmp_buf[GOODIX_MAX_FRAMEDATA_LEN];
struct goodix_ts_cmd temp_cmd;
int tx = cd->ic_info.parm.drv_num;
int rx = cd->ic_info.parm.sen_num;
- s16 buf[17 * 35];
+ u32 sync_addr = cd->ic_info.misc.frame_data_addr;
u32 raw_addr;
- int retry = 50;
- u8 status;
int ret;
- int i;
int err_cnt = 0;
+ int i, j;
+ s16 tmp_val;
+ u16 tmp_freq;
+ u8 val;
+ int retry;
raw_addr = cd->ic_info.misc.frame_data_addr +
cd->ic_info.misc.frame_data_head_len +
cd->ic_info.misc.fw_attr_len + cd->ic_info.misc.fw_log_len +
8;
- temp_cmd.len = 0x07;
+ /* open test prepare */
+ temp_cmd.cmd = 0x90;
+ temp_cmd.data[0] = 0x84;
+ temp_cmd.len = 5;
+ ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
+ if (ret < 0) {
+ ts_err("send rawdata cmd failed");
+ return ret;
+ }
+
+ /* switch freq */
+ if (ts_test->freq > 0) {
+ ts_info("set freq %d", ts_test->freq);
+ tmp_freq = ts_test->freq / 61;
+ temp_cmd.len = 6;
+ temp_cmd.cmd = 0xB1;
+ temp_cmd.data[0] = tmp_freq & 0xFF;
+ temp_cmd.data[1] = (tmp_freq >> 8) & 0xFF;
+ ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
+ if (ret < 0) {
+ ts_err("set freq %d failed", ts_test->freq);
+ return ret;
+ }
+ }
+
+ /* discard the first few frames */
+ for (i = 0; i < 3; i++) {
+ val = 0;
+ cd->hw_ops->write(cd, sync_addr, &val, 1);
+ usleep_range(20000, 21000);
+ }
+
+ /* read rawdata */
+ for (i = 0; i < ts_test->raw_data_cnt; i++) {
+ val = 0;
+ cd->hw_ops->write(cd, sync_addr, &val, 1);
+ retry = 20;
+ while (retry--) {
+ usleep_range(5000, 5100);
+ cd->hw_ops->read(cd, sync_addr, &val, 1);
+ if (val & 0x80)
+ break;
+ }
+ if (retry < 0) {
+ ts_err("rawdata is not ready val:0x%02x i:%d, exit",
+ val, i);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ cd->hw_ops->read(cd, raw_addr, tmp_buf, tx * rx * 2);
+ goodix_rotate_abcd2cbad(tx, rx, (s16 *)tmp_buf);
+ memcpy((u8 *)ts_test->rawdata[i].data, tmp_buf, tx * rx * 2);
+ }
+
+ /* analysis results */
+ ts_test->result[GTP_CAP_TEST] = TEST_OK;
+ for (i = 0; i < ts_test->raw_data_cnt; i++) {
+ for (j = 0; j < tx * rx; j++) {
+ tmp_val = ts_test->rawdata[i].data[j];
+ if (tmp_val > ts_test->max_limits[j] ||
+ tmp_val < ts_test->min_limits[j]) {
+ ts_err("rawdata[%d] out of range[%d %d]",
+ tmp_val, ts_test->min_limits[j],
+ ts_test->max_limits[j]);
+ err_cnt++;
+ }
+ }
+ }
+
+ if (err_cnt > 0) {
+ ret = -EINVAL;
+ ts_test->result[GTP_CAP_TEST] = TEST_NG;
+ }
+
+ if (goodix_delta_test() == 0)
+ ts_test->result[GTP_DELTA_TEST] = TEST_OK;
+
+exit:
+ return ret;
+}
+
+static int goodix_self_open_test(void)
+{
+ unsigned char tmp_buf[GOODIX_MAX_FRAMEDATA_LEN];
+ struct goodix_ts_cmd temp_cmd;
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ u32 sync_addr = cd->ic_info.misc.frame_data_addr;
+ u32 raw_addr;
+ int ret;
+ int j;
+ s16 tmp_val;
+ u8 val;
+ int retry;
+
+ raw_addr = cd->ic_info.misc.frame_data_addr +
+ cd->ic_info.misc.frame_data_head_len +
+ cd->ic_info.misc.fw_attr_len + cd->ic_info.misc.fw_log_len +
+ cd->ic_info.misc.mutual_struct_len + 10;
+
+ /* test prepare */
temp_cmd.cmd = 0x90;
- temp_cmd.data[0] = 0x86;
- temp_cmd.data[1] = frame & 0xFF;
- temp_cmd.data[2] = (frame >> 8) & 0xFF;
+ temp_cmd.data[0] = 0x84;
+ temp_cmd.len = 5;
ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
if (ret < 0) {
- ts_err("send noise cmd failed");
- goto fail;
+ ts_err("send rawdata cmd failed");
+ return ret;
}
- msleep(frame * 10);
+ /* discard the first few frames */
+ for (j = 0; j < 3; j++) {
+ val = 0;
+ cd->hw_ops->write(cd, sync_addr, &val, 1);
+ usleep_range(20000, 21000);
+ }
+
+ /* read self rawdata */
+ val = 0;
+ cd->hw_ops->write(cd, sync_addr, &val, 1);
+ retry = 20;
while (retry--) {
- ret = cd->hw_ops->read(
- cd, cd->ic_info.misc.cmd_addr, &status, 1);
- if (ret == 0 && status == 0x80)
+ usleep_range(5000, 5100);
+ cd->hw_ops->read(cd, sync_addr, &val, 1);
+ if (val & 0x80)
break;
- msleep(50);
}
if (retry < 0) {
- ts_err("noise data is not ready");
- goto fail;
+ ts_err("self rawdata is not ready val:0x%02x, exit", val);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ cd->hw_ops->read(cd, raw_addr, tmp_buf, (tx + rx) * 2);
+ memcpy((u8 *)ts_test->selfrawdata.data, tmp_buf, (tx + rx) * 2);
+
+ /* analysis results */
+ ts_test->result[GTP_SELFCAP_TEST] = TEST_OK;
+ for (j = 0; j < tx + rx; j++) {
+ tmp_val = ts_test->selfrawdata.data[j];
+ if (tmp_val > ts_test->self_max_limits[j] ||
+ tmp_val < ts_test->self_min_limits[j]) {
+ ts_err("self_rawdata[%d] out of range[%d %d]", tmp_val,
+ ts_test->self_min_limits[j],
+ ts_test->self_max_limits[j]);
+ ts_test->result[GTP_SELFCAP_TEST] = TEST_NG;
+ ret = -EINVAL;
+ }
}
- msleep(50);
- ret = cd->hw_ops->read(cd, raw_addr, (u8 *)buf, tx * rx * 2);
+exit:
+ return ret;
+}
+
+static int goodix_noise_test(void)
+{
+ unsigned char tmp_buf[GOODIX_MAX_FRAMEDATA_LEN];
+ struct goodix_ts_cmd temp_cmd;
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ u32 sync_addr = cd->ic_info.misc.frame_data_addr;
+ u32 raw_addr;
+ int ret;
+ int i, j;
+ s16 tmp_val;
+ u8 val;
+ int retry;
+
+ raw_addr = cd->ic_info.misc.frame_data_addr +
+ cd->ic_info.misc.frame_data_head_len +
+ cd->ic_info.misc.fw_attr_len + cd->ic_info.misc.fw_log_len +
+ 8;
+
+ /* open test prepare */
+ temp_cmd.cmd = 0x90;
+ temp_cmd.data[0] = 0x82;
+ temp_cmd.len = 5;
+ ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
if (ret < 0) {
- ts_err("read noise data faield");
- goto fail;
+ ts_err("send rawdata cmd failed");
+ return ret;
}
- goodix_rotate_abcd2cbad(tx, rx, buf);
- for (i = 0; i < tx * rx; i++) {
- if (ABS(buf[i]) > threshold)
- err_cnt++;
- index += sprintf(&rbuf[index], "%3d,", buf[i]);
- if ((i + 1) % tx == 0)
- index += sprintf(&rbuf[index], "\n");
+ /* discard the first few frames */
+ for (i = 0; i < 3; i++) {
+ val = 0;
+ cd->hw_ops->write(cd, sync_addr, &val, 1);
+ usleep_range(20000, 21000);
}
- if (err_cnt > 0) {
- ts_err("noise test fail");
- goto fail;
+ /* read noisedata */
+ for (i = 0; i < ts_test->noise_data_cnt; i++) {
+ val = 0;
+ cd->hw_ops->write(cd, sync_addr, &val, 1);
+ retry = 20;
+ while (retry--) {
+ usleep_range(5000, 5100);
+ cd->hw_ops->read(cd, sync_addr, &val, 1);
+ if (val & 0x80)
+ break;
+ }
+ if (retry < 0) {
+ ts_err("noisedata is not ready val:0x%02x i:%d, exit",
+ val, i);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ cd->hw_ops->read(cd, raw_addr, tmp_buf, tx * rx * 2);
+ goodix_rotate_abcd2cbad(tx, rx, (s16 *)tmp_buf);
+ memcpy((u8 *)ts_test->noisedata[i].data, tmp_buf, tx * rx * 2);
}
- ts_info("noise test pass");
- index += sprintf(&rbuf[index], "noise_test-[PASS]\n");
- return 0;
+ /* analysis results */
+ ts_test->result[GTP_NOISE_TEST] = TEST_OK;
+ for (i = 0; i < ts_test->noise_data_cnt; i++) {
+ for (j = 0; j < tx * rx; j++) {
+ tmp_val = ts_test->noisedata[i].data[j];
+ tmp_val = ABS(tmp_val);
+ if (tmp_val > ts_test->noise_threshold) {
+ ts_err("noise data[%d] > noise threshold[%d]",
+ tmp_val, ts_test->noise_threshold);
+ ts_test->result[GTP_NOISE_TEST] = TEST_NG;
+ ret = -EINVAL;
+ }
+ }
+ }
-fail:
- index += sprintf(&rbuf[index], "noise_test-[FAIL]\n");
+exit:
return ret;
}
+static int goodix_auto_test(void)
+{
+ struct goodix_ts_cmd temp_cmd;
+ int ret;
+
+ ret = goodix_obtain_testlimits();
+ if (ret < 0) {
+ ts_err("obtain open test limits failed");
+ return ret;
+ }
+
+ cd->hw_ops->irq_enable(cd, false);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
+
+ temp_cmd.len = 5;
+ temp_cmd.cmd = 0x64;
+ temp_cmd.data[0] = 1;
+
+ if (ts_test->item[GTP_CAP_TEST]) {
+ ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
+ if (ret < 0)
+ ts_err("enter test mode failed");
+ goodix_open_test();
+ cd->hw_ops->reset(cd, 100);
+ }
+
+ if (ts_test->item[GTP_NOISE_TEST]) {
+ ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
+ if (ret < 0)
+ ts_err("enter test mode failed");
+ goodix_noise_test();
+ cd->hw_ops->reset(cd, 100);
+ }
+
+ if (ts_test->item[GTP_SELFCAP_TEST]) {
+ goodix_self_open_test();
+ cd->hw_ops->reset(cd, 100);
+ }
+
+ if (ts_test->item[GTP_SHORT_TEST]) {
+ goodix_shortcircut_test();
+ cd->hw_ops->reset(cd, 100);
+ }
+
+ cd->hw_ops->irq_enable(cd, true);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ goodix_save_test_result();
+ return 0;
+}
+
static int get_cap_data(uint8_t *type)
{
struct goodix_ts_cmd temp_cmd;
@@ -409,24 +1965,51 @@ static void goodix_set_scan_mode(u8 val)
{
struct goodix_ts_cmd temp_cmd;
+ if (val == 0) {
+ ts_info("set scan mode to default");
+ index = sprintf(rbuf, "set scan mode to default\n");
+ } else if (val == 1) {
+ ts_info("set scan mode to idle");
+ index = sprintf(rbuf, "set scan mode to idle\n");
+ } else {
+ ts_info("set scan mode to active");
+ index = sprintf(rbuf, "set scan mode to active\n");
+ }
+
temp_cmd.len = 5;
temp_cmd.cmd = 0x9F;
temp_cmd.data[0] = val;
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
+static void goodix_set_continue_mode(u8 val)
+{
+ struct goodix_ts_cmd temp_cmd;
+
+ if (val == 0) {
+ ts_info("enable continue report");
+ index = sprintf(rbuf, "enable continue report\n");
+ } else {
+ ts_info("disable continue report");
+ index = sprintf(rbuf, "disable continue report\n");
+ }
+
+ temp_cmd.len = 5;
+ temp_cmd.cmd = 0xC3;
+ temp_cmd.data[0] = val;
+ cd->hw_ops->send_cmd(cd, &temp_cmd);
+}
+
static ssize_t driver_test_write(
struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
struct goodix_fw_version fw_ver;
struct goodix_ic_info ic_info;
- struct ts_rawdata_info *info = NULL;
char *p = wbuf;
char *token;
int ret;
- int frames;
- int limit;
int cmd_val;
+ int cmd_val2;
u8 id;
if (count > SHORT_SIZE) {
@@ -442,10 +2025,11 @@ static ssize_t driver_test_write(
kfree(rbuf);
rbuf = NULL;
index = 0;
+ release_test_resource();
ts_info("input cmd[%s]", p);
- if (strstr(p, CMD_FW_UPDATE)) {
+ if (!strncmp(p, CMD_FW_UPDATE, strlen(CMD_FW_UPDATE))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
ret = goodix_do_fw_update(
NULL, UPDATE_MODE_BLOCK | UPDATE_MODE_FORCE |
@@ -458,7 +2042,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_VERSION)) {
+ if (!strncmp(p, CMD_GET_VERSION, strlen(CMD_GET_VERSION))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
cd->hw_ops->read_version(cd, &fw_ver);
cd->hw_ops->get_ic_info(cd, &ic_info);
@@ -469,7 +2053,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_RAWDATA)) {
+ if (!strncmp(p, CMD_GET_RAWDATA, strlen(CMD_GET_RAWDATA))) {
rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_RAWDATA);
if (ret < 0) {
@@ -478,7 +2062,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_BASEDATA)) {
+ if (!strncmp(p, CMD_GET_BASEDATA, strlen(CMD_GET_BASEDATA))) {
rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_BASEDATA);
if (ret < 0) {
@@ -487,7 +2071,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_DIFFDATA)) {
+ if (!strncmp(p, CMD_GET_DIFFDATA, strlen(CMD_GET_DIFFDATA))) {
rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_DIFFDATA);
if (ret < 0) {
@@ -496,7 +2080,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_SELF_RAWDATA)) {
+ if (!strncmp(p, CMD_GET_SELF_RAWDATA, strlen(CMD_GET_SELF_RAWDATA))) {
rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_SELF_RAWDATA);
if (ret < 0) {
@@ -505,7 +2089,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_SELF_DIFFDATA)) {
+ if (!strncmp(p, CMD_GET_SELF_DIFFDATA, strlen(CMD_GET_SELF_DIFFDATA))) {
rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_SELF_DIFFDATA);
if (ret < 0) {
@@ -515,7 +2099,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_GET_SELF_BASEDATA)) {
+ if (!strncmp(p, CMD_GET_SELF_BASEDATA, strlen(CMD_GET_SELF_BASEDATA))) {
rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_SELF_BASEDATA);
if (ret < 0) {
@@ -525,7 +2109,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_SET_DOUBLE_TAP)) {
+ if (!strncmp(p, CMD_SET_DOUBLE_TAP, strlen(CMD_SET_DOUBLE_TAP))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -552,7 +2136,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_SET_SINGLE_TAP)) {
+ if (!strncmp(p, CMD_SET_SINGLE_TAP, strlen(CMD_SET_SINGLE_TAP))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -579,7 +2163,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_SET_IRQ_ENABLE)) {
+ if (!strncmp(p, CMD_SET_IRQ_ENABLE, strlen(CMD_SET_IRQ_ENABLE))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -604,7 +2188,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_SET_ESD_ENABLE)) {
+ if (!strncmp(p, CMD_SET_ESD_ENABLE, strlen(CMD_SET_ESD_ENABLE))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -629,7 +2213,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_SET_DEBUG_LOG)) {
+ if (!strncmp(p, CMD_SET_DEBUG_LOG, strlen(CMD_SET_DEBUG_LOG))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -654,23 +2238,31 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_AUTO_TEST)) {
- rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
- info = vmalloc(sizeof(*info));
- goodix_do_inspect(cd, info);
- index = sprintf(rbuf, "%s", info->result);
- vfree(info);
+ if (!strncmp(p, CMD_AUTO_TEST, strlen(CMD_AUTO_TEST))) {
+ rbuf = kzalloc(HUGE_SIZE, GFP_KERNEL);
+ ret = malloc_test_resource();
+ if (ret < 0) {
+ ts_err("malloc test resource failed");
+ goto exit;
+ }
+ ts_test->item[GTP_CAP_TEST] = true;
+ ts_test->item[GTP_NOISE_TEST] = true;
+ ts_test->item[GTP_SELFCAP_TEST] = true;
+ ts_test->item[GTP_SHORT_TEST] = true;
+ ts_test->raw_data_cnt = 16;
+ ts_test->noise_data_cnt = 1;
+ goodix_auto_test();
goto exit;
}
- if (strstr(p, CMD_GET_CHANNEL_NUM)) {
+ if (!strncmp(p, CMD_GET_CHANNEL_NUM, strlen(CMD_GET_CHANNEL_NUM))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
index = sprintf(rbuf, "TX:%d RX:%d\n", cd->ic_info.parm.drv_num,
cd->ic_info.parm.sen_num);
goto exit;
}
- if (strstr(p, CMD_GET_TX_FREQ)) {
+ if (!strncmp(p, CMD_GET_TX_FREQ, strlen(CMD_GET_TX_FREQ))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
ret = get_cap_data(CMD_GET_TX_FREQ);
if (ret < 0) {
@@ -679,14 +2271,14 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_RESET)) {
+ if (!strncmp(p, CMD_RESET, strlen(CMD_RESET))) {
cd->hw_ops->irq_enable(cd, false);
cd->hw_ops->reset(cd, 100);
cd->hw_ops->irq_enable(cd, true);
goto exit;
}
- if (strstr(p, CMD_SET_SENSE_ENABLE)) {
+ if (!strncmp(p, CMD_SET_SENSE_ENABLE, strlen(CMD_SET_SENSE_ENABLE))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -710,41 +2302,37 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_NOISE_TEST)) {
- rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
+ if (!strncmp(p, CMD_NOISE_TEST, strlen(CMD_NOISE_TEST))) {
+ rbuf = kzalloc(HUGE_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
index = sprintf(rbuf, "%s: invalid cmd param\n",
CMD_NOISE_TEST);
goto exit;
}
- token = strsep(&p, ",");
- if (!token || !p) {
+ if (kstrtos32(p, 10, &cmd_val)) {
index = sprintf(rbuf, "%s: invalid cmd param\n",
CMD_NOISE_TEST);
goto exit;
}
- if (kstrtos32(token, 10, &frames)) {
- index = sprintf(rbuf, "%s: invalid cmd param\n",
- CMD_NOISE_TEST);
+ if (cmd_val > MAX_FRAME_CNT) {
+ index = sprintf(rbuf,
+ "%s: frame cnt:%d > MAX_CNT[%d]\n",
+ CMD_NOISE_TEST, (int)cmd_val, MAX_FRAME_CNT);
goto exit;
}
- if (kstrtos32(p, 10, &limit)) {
- index = sprintf(rbuf, "%s: invalid cmd param\n",
- CMD_NOISE_TEST);
+ ret = malloc_test_resource();
+ if (ret < 0) {
+ ts_err("malloc test resource failed");
goto exit;
}
-
- ts_info("noise test frames:%d limit:%d", frames, limit);
- cd->hw_ops->irq_enable(cd, false);
- goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
- goodix_noise_test(frames, limit);
- cd->hw_ops->irq_enable(cd, true);
- goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ ts_test->item[GTP_NOISE_TEST] = true;
+ ts_test->noise_data_cnt = cmd_val;
+ goodix_auto_test();
goto exit;
}
- if (strstr(p, CMD_GET_PACKAGE_ID)) {
+ if (!strncmp(p, CMD_GET_PACKAGE_ID, strlen(CMD_GET_PACKAGE_ID))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
ret = goodix_flash_read(0x1F301, &id, 1);
if (ret < 0)
@@ -755,7 +2343,7 @@ static ssize_t driver_test_write(
goto exit;
}
- if (strstr(p, CMD_SET_SCAN_MODE)) {
+ if (!strncmp(p, CMD_SET_SCAN_MODE, strlen(CMD_SET_SCAN_MODE))) {
rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
token = strsep(&p, ",");
if (!token || !p) {
@@ -768,15 +2356,95 @@ static ssize_t driver_test_write(
CMD_SET_SCAN_MODE);
goto exit;
}
- if (cmd_val == 0) {
- goodix_set_scan_mode(0);
+ if (cmd_val > 2 || cmd_val < 0) {
+ index = sprintf(rbuf, "%s: invalid cmd param\n",
+ CMD_SET_SCAN_MODE);
+ goto exit;
+ }
+ goodix_set_scan_mode(cmd_val);
+ goto exit;
+ }
+
+ if (!strncmp(p, CMD_SET_CONTINUE_MODE, strlen(CMD_SET_CONTINUE_MODE))) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ token = strsep(&p, ",");
+ if (!token || !p) {
+ index = sprintf(rbuf, "%s: invalid cmd param\n",
+ CMD_SET_CONTINUE_MODE);
+ goto exit;
+ }
+ if (kstrtos32(p, 10, &cmd_val)) {
+ index = sprintf(rbuf, "%s: invalid cmd param\n",
+ CMD_SET_CONTINUE_MODE);
+ goto exit;
+ }
+ if (cmd_val > 1 || cmd_val < 0) {
+ index = sprintf(rbuf, "%s: invalid cmd param\n",
+ CMD_SET_CONTINUE_MODE);
+ goto exit;
+ }
+ goodix_set_continue_mode(cmd_val);
+ goto exit;
+ }
+
+ /* open test */
+ if (!strncmp(p, CMD_OPEN_TEST, strlen(CMD_OPEN_TEST))) {
+ rbuf = kzalloc(HUGE_SIZE, GFP_KERNEL);
+ token = strsep(&p, ",");
+ if (!token || !p) {
index = sprintf(
- rbuf, "%s: exit idle\n", CMD_SET_SCAN_MODE);
- } else {
- goodix_set_scan_mode(1);
+ rbuf, "%s: invalid cmd param\n", CMD_OPEN_TEST);
+ goto exit;
+ }
+ token = strsep(&p, ",");
+ if (!token || !p) {
index = sprintf(
- rbuf, "%s: enter idle\n", CMD_SET_SCAN_MODE);
+ rbuf, "%s: invalid cmd param\n", CMD_OPEN_TEST);
+ goto exit;
+ }
+ if (kstrtos32(token, 10, &cmd_val)) {
+ index = sprintf(
+ rbuf, "%s: invalid cmd param\n", CMD_OPEN_TEST);
+ goto exit;
+ }
+ if (kstrtos32(p, 10, &cmd_val2)) {
+ index = sprintf(
+ rbuf, "%s: invalid cmd param\n", CMD_OPEN_TEST);
+ goto exit;
+ }
+ ret = malloc_test_resource();
+ if (ret < 0) {
+ ts_err("malloc test resource failed");
+ goto exit;
+ }
+ ts_test->item[GTP_CAP_TEST] = true;
+ ts_test->raw_data_cnt = cmd_val;
+ ts_test->freq = cmd_val2;
+ goodix_auto_test();
+ goto exit;
+ }
+
+ if (!strncmp(p, CMD_SELF_OPEN_TEST, strlen(CMD_SELF_OPEN_TEST))) {
+ rbuf = kzalloc(HUGE_SIZE, GFP_KERNEL);
+ ret = malloc_test_resource();
+ if (ret < 0) {
+ ts_err("malloc test resource failed");
+ goto exit;
+ }
+ ts_test->item[GTP_SELFCAP_TEST] = true;
+ goodix_auto_test();
+ goto exit;
+ }
+
+ if (!strncmp(p, CMD_SHORT_TEST, strlen(CMD_SHORT_TEST))) {
+ rbuf = kzalloc(HUGE_SIZE, GFP_KERNEL);
+ ret = malloc_test_resource();
+ if (ret < 0) {
+ ts_err("malloc test resource failed");
+ goto exit;
}
+ ts_test->item[GTP_SHORT_TEST] = true;
+ goodix_auto_test();
goto exit;
}