| /* drivers/input/touchscreen/sec_ts_fn.c |
| * |
| * Copyright (C) 2015 Samsung Electronics Co., Ltd. |
| * http://www.samsungsemi.com/ |
| * |
| * Core file for Samsung TSC driver |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| */ |
| |
| #include "sec_ts.h" |
| #include "sec_ts_fac_spec.h" |
| |
| static void fw_update(void *device_data); |
| static void get_fw_ver_bin(void *device_data); |
| static void get_fw_ver_ic(void *device_data); |
| static void get_config_ver(void *device_data); |
| #ifdef PAT_CONTROL |
| static void get_pat_information(void *device_data); |
| static void set_external_factory(void *device_data); |
| #endif |
| static void get_threshold(void *device_data); |
| static void module_off_master(void *device_data); |
| static void module_on_master(void *device_data); |
| static void get_chip_vendor(void *device_data); |
| static void get_chip_name(void *device_data); |
| static void set_mis_cal_spec(void *device_data); |
| static void get_mis_cal_info(void *device_data); |
| static void get_wet_mode(void *device_data); |
| static void get_x_num(void *device_data); |
| static void get_y_num(void *device_data); |
| static void get_x_cross_routing(void *device_data); |
| static void get_y_cross_routing(void *device_data); |
| static void get_checksum_data(void *device_data); |
| static void run_reference_read(void *device_data); |
| static void run_reference_read_all(void *device_data); |
| static void get_reference(void *device_data); |
| static void run_rawcap_read(void *device_data); |
| static void run_rawcap_read_all(void *device_data); |
| static void run_rawcap_high_freq_read_all(void *device_data); |
| static void get_rawcap(void *device_data); |
| static void run_rawcap_gap_read_all(void *device_data); |
| static void run_delta_read(void *device_data); |
| static void run_delta_read_all(void *device_data); |
| static void get_delta(void *device_data); |
| static void run_rawdata_stdev_read(void *device_data); |
| static void run_rawdata_p2p_read_all(void *device_data); |
| static void run_rawdata_read_type(void *device_data); |
| static void run_rawdata_read_all(void *device_data); |
| static void run_self_reference_read(void *device_data); |
| static void run_self_reference_read_all(void *device_data); |
| static void run_self_rawcap_read(void *device_data); |
| static void run_self_rawcap_read_all(void *device_data); |
| static void run_self_rawcap_gap_read_all(void *device_data); |
| static void run_self_delta_read(void *device_data); |
| static void run_self_delta_read_all(void *device_data); |
| static void run_force_calibration(void *device_data); |
| static void get_force_calibration(void *device_data); |
| #ifdef USE_PRESSURE_SENSOR |
| static void run_force_pressure_calibration(void *device_data); |
| static void set_pressure_test_mode(void *device_data); |
| static void run_pressure_filtered_strength_read_all(void *device_data); |
| static void run_pressure_strength_read_all(void *device_data); |
| static void run_pressure_rawdata_read_all(void *device_data); |
| static void run_pressure_offset_read_all(void *device_data); |
| static void set_pressure_strength(void *device_data); |
| static void set_pressure_rawdata(void *device_data); |
| static void set_pressure_data_index(void *device_data); |
| static void get_pressure_strength(void *device_data); |
| static void get_pressure_rawdata(void *device_data); |
| static void get_pressure_data_index(void *device_data); |
| static void set_pressure_strength_clear(void *device_data); |
| static void get_pressure_threshold(void *device_data); |
| static void set_pressure_user_level(void *device_data); |
| static void get_pressure_user_level(void *device_data); |
| #endif |
| static void run_fs_cal_pre_press(void *device_data); |
| static void run_fs_cal_get_data(void *device_data); |
| static void run_fs_cal_post_press(void *device_data); |
| static void enable_fs_cal_table(void *device_data); |
| static void enable_coordinate_report(void *device_data); |
| static void enable_gain_limit(void *device_data); |
| static void run_trx_short_test(void *device_data); |
| static void set_tsp_test_result(void *device_data); |
| static void get_tsp_test_result(void *device_data); |
| static void increase_disassemble_count(void *device_data); |
| static void get_disassemble_count(void *device_data); |
| static void glove_mode(void *device_data); |
| static void clear_cover_mode(void *device_data); |
| static void dead_zone_enable(void *device_data); |
| static void drawing_test_enable(void *device_data); |
| static void set_lowpower_mode(void *device_data); |
| static void set_wirelesscharger_mode(void *device_data); |
| static void spay_enable(void *device_data); |
| static void set_aod_rect(void *device_data); |
| static void get_aod_rect(void *device_data); |
| static void aod_enable(void *device_data); |
| static void set_grip_data(void *device_data); |
| static void dex_enable(void *device_data); |
| static void brush_enable(void *device_data); |
| static void force_touch_active(void *device_data); |
| static void set_touchable_area(void *device_data); |
| static void set_log_level(void *device_data); |
| static void debug(void *device_data); |
| static void set_touch_mode(void *device_data); |
| static void not_support_cmd(void *device_data); |
| static void set_palm_detection_enable(void *device_data); |
| static void set_grip_detection_enable(void *device_data); |
| static void set_wet_mode_enable(void *device_data); |
| static void set_noise_mode_enable(void *device_data); |
| static void set_continuous_report_enable(void *device_data); |
| static void set_charger_nb_enable(void *device_data); |
| static void set_print_format(void *device_data); |
| static void run_cal_check(void *device_data); |
| |
| static struct sec_cmd sec_cmds[] = { |
| {SEC_CMD("fw_update", fw_update),}, |
| {SEC_CMD("get_fw_ver_bin", get_fw_ver_bin),}, |
| {SEC_CMD("get_fw_ver_ic", get_fw_ver_ic),}, |
| {SEC_CMD("get_config_ver", get_config_ver),}, |
| #ifdef PAT_CONTROL |
| {SEC_CMD("get_pat_information", get_pat_information),}, |
| {SEC_CMD("set_external_factory", set_external_factory),}, |
| #endif |
| {SEC_CMD("get_threshold", get_threshold),}, |
| {SEC_CMD("module_off_master", module_off_master),}, |
| {SEC_CMD("module_on_master", module_on_master),}, |
| {SEC_CMD("get_chip_vendor", get_chip_vendor),}, |
| {SEC_CMD("get_chip_name", get_chip_name),}, |
| {SEC_CMD("set_mis_cal_spec", set_mis_cal_spec),}, |
| {SEC_CMD("get_mis_cal_info", get_mis_cal_info),}, |
| {SEC_CMD("get_wet_mode", get_wet_mode),}, |
| {SEC_CMD("get_x_num", get_x_num),}, |
| {SEC_CMD("get_y_num", get_y_num),}, |
| {SEC_CMD("get_x_cross_routing", get_x_cross_routing),}, |
| {SEC_CMD("get_y_cross_routing", get_y_cross_routing),}, |
| {SEC_CMD("get_checksum_data", get_checksum_data),}, |
| {SEC_CMD("run_reference_read", run_reference_read),}, |
| {SEC_CMD("run_reference_read_all", run_reference_read_all),}, |
| {SEC_CMD("get_reference", get_reference),}, |
| {SEC_CMD("run_rawcap_read", run_rawcap_read),}, |
| {SEC_CMD("run_rawcap_read_all", run_rawcap_read_all),}, |
| {SEC_CMD("get_rawcap", get_rawcap),}, |
| {SEC_CMD("run_rawcap_gap_read_all", run_rawcap_gap_read_all),}, |
| {SEC_CMD("run_delta_read", run_delta_read),}, |
| {SEC_CMD("run_delta_read_all", run_delta_read_all),}, |
| {SEC_CMD("get_delta", get_delta),}, |
| {SEC_CMD("run_rawdata_stdev_read", run_rawdata_stdev_read),}, |
| {SEC_CMD("run_rawdata_p2p_read_all", run_rawdata_p2p_read_all),}, |
| {SEC_CMD("run_rawdata_read_type", run_rawdata_read_type),}, |
| {SEC_CMD("run_rawdata_read_all", run_rawdata_read_all),}, |
| {SEC_CMD("run_self_reference_read", run_self_reference_read),}, |
| {SEC_CMD("run_self_reference_read_all", run_self_reference_read_all),}, |
| {SEC_CMD("run_self_rawcap_read", run_self_rawcap_read),}, |
| {SEC_CMD("run_self_rawcap_read_all", run_self_rawcap_read_all),}, |
| {SEC_CMD("run_self_rawcap_gap_read_all", |
| run_self_rawcap_gap_read_all),}, |
| {SEC_CMD("run_rawcap_high_freq_read_all", |
| run_rawcap_high_freq_read_all),}, |
| {SEC_CMD("run_self_delta_read", run_self_delta_read),}, |
| {SEC_CMD("run_self_delta_read_all", run_self_delta_read_all),}, |
| {SEC_CMD("run_force_calibration", run_force_calibration),}, |
| {SEC_CMD("get_force_calibration", get_force_calibration),}, |
| #ifdef USE_PRESSURE_SENSOR |
| {SEC_CMD("run_force_pressure_calibration", |
| run_force_pressure_calibration),}, |
| {SEC_CMD("set_pressure_test_mode", set_pressure_test_mode),}, |
| {SEC_CMD("run_pressure_filtered_strength_read_all", |
| run_pressure_filtered_strength_read_all),}, |
| {SEC_CMD("run_pressure_strength_read_all", |
| run_pressure_strength_read_all),}, |
| {SEC_CMD("run_pressure_rawdata_read_all", |
| run_pressure_rawdata_read_all),}, |
| {SEC_CMD("run_pressure_offset_read_all", |
| run_pressure_offset_read_all),}, |
| {SEC_CMD("set_pressure_strength", set_pressure_strength),}, |
| {SEC_CMD("set_pressure_rawdata", set_pressure_rawdata),}, |
| {SEC_CMD("set_pressure_data_index", set_pressure_data_index),}, |
| {SEC_CMD("get_pressure_strength", get_pressure_strength),}, |
| {SEC_CMD("get_pressure_rawdata", get_pressure_rawdata),}, |
| {SEC_CMD("get_pressure_data_index", get_pressure_data_index),}, |
| {SEC_CMD("set_pressure_strength_clear", set_pressure_strength_clear),}, |
| {SEC_CMD("get_pressure_threshold", get_pressure_threshold),}, |
| {SEC_CMD("set_pressure_user_level", set_pressure_user_level),}, |
| {SEC_CMD("get_pressure_user_level", get_pressure_user_level),}, |
| #endif |
| {SEC_CMD("run_fs_cal_pre_press", run_fs_cal_pre_press),}, |
| {SEC_CMD("run_fs_cal_get_data", run_fs_cal_get_data),}, |
| {SEC_CMD("run_fs_cal_post_press", run_fs_cal_post_press),}, |
| {SEC_CMD("enable_fs_cal_table", enable_fs_cal_table),}, |
| {SEC_CMD("enable_coordinate_report", enable_coordinate_report),}, |
| {SEC_CMD("enable_gain_limit", enable_gain_limit),}, |
| {SEC_CMD("run_trx_short_test", run_trx_short_test),}, |
| {SEC_CMD("set_tsp_test_result", set_tsp_test_result),}, |
| {SEC_CMD("get_tsp_test_result", get_tsp_test_result),}, |
| {SEC_CMD("increase_disassemble_count", increase_disassemble_count),}, |
| {SEC_CMD("get_disassemble_count", get_disassemble_count),}, |
| {SEC_CMD("glove_mode", glove_mode),}, |
| {SEC_CMD("clear_cover_mode", clear_cover_mode),}, |
| {SEC_CMD("dead_zone_enable", dead_zone_enable),}, |
| {SEC_CMD("drawing_test_enable", drawing_test_enable),}, |
| {SEC_CMD("set_lowpower_mode", set_lowpower_mode),}, |
| {SEC_CMD("set_wirelesscharger_mode", set_wirelesscharger_mode),}, |
| {SEC_CMD("spay_enable", spay_enable),}, |
| {SEC_CMD("set_aod_rect", set_aod_rect),}, |
| {SEC_CMD("get_aod_rect", get_aod_rect),}, |
| {SEC_CMD("aod_enable", aod_enable),}, |
| {SEC_CMD("set_grip_data", set_grip_data),}, |
| {SEC_CMD("dex_enable", dex_enable),}, |
| {SEC_CMD("brush_enable", brush_enable),}, |
| {SEC_CMD("force_touch_active", force_touch_active),}, |
| {SEC_CMD("set_touchable_area", set_touchable_area),}, |
| {SEC_CMD("set_log_level", set_log_level),}, |
| {SEC_CMD("debug", debug),}, |
| {SEC_CMD("set_touch_mode", set_touch_mode),}, |
| {SEC_CMD("set_palm_detection_enable", set_palm_detection_enable),}, |
| {SEC_CMD("set_grip_detection_enable", set_grip_detection_enable),}, |
| {SEC_CMD("set_wet_mode_enable", set_wet_mode_enable),}, |
| {SEC_CMD("set_noise_mode_enable", set_noise_mode_enable),}, |
| {SEC_CMD("set_continuous_report_enable", |
| set_continuous_report_enable),}, |
| {SEC_CMD("set_charger_nb_enable", set_charger_nb_enable),}, |
| {SEC_CMD("set_print_format", set_print_format),}, |
| {SEC_CMD("run_cal_check", run_cal_check),}, |
| {SEC_CMD("not_support_cmd", not_support_cmd),}, |
| }; |
| |
| static void set_palm_detection_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[4] = { 0 }; |
| u8 para = 0x0; |
| u8 ret = 0; |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d\n", __func__, sec->cmd_param[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] == 1) |
| para = 0x1; |
| else if (sec->cmd_param[0] == 0) |
| para = 0x0; |
| else { |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_PALM_DETEC, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x para %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_SET_PALM_DETEC, para, ret); |
| goto err_out; |
| } |
| |
| scnprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_out: |
| scnprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_grip_detection_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[4] = { 0 }; |
| u8 para = 0x0; |
| u8 ret = 0; |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d\n", __func__, sec->cmd_param[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] == 1) |
| para = 0x1F; |
| else if (sec->cmd_param[0] == 0) |
| para = 0x0; |
| else { |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GRIP_DETEC, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x para %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_SET_GRIP_DETEC, para, ret); |
| goto err_out; |
| } |
| |
| scnprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_out: |
| scnprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_wet_mode_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[4] = { 0 }; |
| u8 para = 0x0; |
| u8 ret = 0; |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d\n", __func__, sec->cmd_param[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] == 1) |
| para = 0x0; |
| else if (sec->cmd_param[0] == 0) |
| para = 0x1; |
| else { |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_WET_MODE, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x para %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_SET_WET_MODE, para, ret); |
| goto err_out; |
| } |
| |
| scnprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_out: |
| scnprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_noise_mode_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[4] = { 0 }; |
| u8 para = 0x0; |
| u8 ret = 0; |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d\n", __func__, sec->cmd_param[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] == 1) |
| para = NOISE_MODE_DEFALUT; |
| else if (sec->cmd_param[0] == 0) |
| para = NOISE_MODE_OFF; |
| else { |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_NOISE_MODE, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x para %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_SET_NOISE_MODE, para, ret); |
| goto err_out; |
| } |
| |
| scnprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_out: |
| scnprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_continuous_report_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[4] = { 0 }; |
| u8 para = 0x0; |
| u8 ret = 0; |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d\n", __func__, sec->cmd_param[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] == 1) |
| para = 0x1; |
| else if (sec->cmd_param[0] == 0) |
| para = 0x0; |
| else { |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_CONT_REPORT, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x para %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_SET_CONT_REPORT, para, ret); |
| goto err_out; |
| } |
| |
| ts->use_default_mf = para; |
| scnprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_out: |
| scnprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_charger_nb_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[4] = { 0 }; |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d\n", __func__, sec->cmd_param[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] == 1) |
| ts->ignore_charger_nb = 0; |
| else if (sec->cmd_param[0] == 0) |
| ts->ignore_charger_nb = 1; |
| else { |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| scnprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_out: |
| scnprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static ssize_t scrub_pos_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[256] = { 0 }; |
| |
| #ifdef CONFIG_SAMSUNG_PRODUCT_SHIP |
| input_info(true, &ts->client->dev, |
| "%s: scrub_id: %d\n", __func__, ts->scrub_id); |
| #else |
| input_info(true, &ts->client->dev, |
| "%s: scrub_id: %d, X:%d, Y:%d\n", __func__, |
| ts->scrub_id, ts->scrub_x, ts->scrub_y); |
| #endif |
| snprintf(buff, sizeof(buff), "%d %d %d", |
| ts->scrub_id, ts->scrub_x, ts->scrub_y); |
| |
| ts->scrub_x = 0; |
| ts->scrub_y = 0; |
| |
| return snprintf(buf, PAGE_SIZE, "%s", buff); |
| } |
| |
| static DEVICE_ATTR_RO(scrub_pos); |
| |
| static ssize_t ito_check_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[256] = { 0 }; |
| |
| input_info(true, &ts->client->dev, "%s: %02X%02X%02X%02X\n", __func__, |
| ts->ito_test[0], ts->ito_test[1], |
| ts->ito_test[2], ts->ito_test[3]); |
| |
| snprintf(buff, sizeof(buff), "%02X%02X%02X%02X", |
| ts->ito_test[0], ts->ito_test[1], |
| ts->ito_test[2], ts->ito_test[3]); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%s", buff); |
| } |
| |
| static ssize_t raw_check_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int ii, ret = 0; |
| char *buffer = NULL; |
| char temp[CMD_RESULT_WORD_LEN] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| buffer = vzalloc(ts->rx_count * ts->tx_count * 6); |
| if (!buffer) { |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return -ENOMEM; |
| } |
| |
| memset(buffer, 0x00, ts->rx_count * ts->tx_count * 6); |
| |
| for (ii = 0; ii < (ts->rx_count * ts->tx_count - 1); ii++) { |
| snprintf(temp, CMD_RESULT_WORD_LEN, "%d ", ts->pFrame[ii]); |
| strncat(buffer, temp, CMD_RESULT_WORD_LEN); |
| |
| memset(temp, 0x00, CMD_RESULT_WORD_LEN); |
| } |
| |
| snprintf(temp, CMD_RESULT_WORD_LEN, "%d", ts->pFrame[ii]); |
| strncat(buffer, temp, CMD_RESULT_WORD_LEN); |
| |
| ret = snprintf(buf, ts->rx_count * ts->tx_count * 6, buffer); |
| vfree(buffer); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return ret; |
| } |
| |
| static ssize_t multi_count_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, "%s: %d\n", __func__, |
| ts->multi_count); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", ts->multi_count); |
| } |
| |
| static ssize_t multi_count_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->multi_count = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t wet_mode_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, "%s: %d, %d\n", __func__, |
| ts->wet_count, ts->dive_count); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", ts->wet_count); |
| } |
| |
| static ssize_t wet_mode_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->wet_count = 0; |
| ts->dive_count = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t comm_err_count_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, "%s: %d\n", __func__, |
| ts->multi_count); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", ts->comm_err_count); |
| } |
| |
| static ssize_t comm_err_count_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->comm_err_count = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t module_id_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[256] = { 0 }; |
| |
| input_info(true, &ts->client->dev, "%s: %d\n", __func__, |
| ts->multi_count); |
| |
| snprintf(buff, sizeof(buff), "SE%02X%02X%02X%02X%02X%02X%02X", |
| ts->plat_data->panel_revision, |
| ts->plat_data->img_version_of_bin[2], |
| ts->plat_data->img_version_of_bin[3], ts->nv, ts->cal_count, |
| ts->pressure_cal_base, ts->pressure_cal_delta); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%s", buff); |
| } |
| |
| static ssize_t vendor_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| unsigned char buffer[10] = { 0 }; |
| |
| snprintf(buffer, 5, ts->plat_data->firmware_name + 8); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "LSI_%s", buffer); |
| } |
| |
| static ssize_t checksum_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->checksum_result = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t checksum_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, "%s: %d\n", __func__, |
| ts->checksum_result); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", ts->checksum_result); |
| } |
| |
| static ssize_t holding_time_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->time_longest = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t holding_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, "%s: %ld\n", __func__, |
| ts->time_longest); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%ld", ts->time_longest); |
| } |
| |
| static ssize_t all_touch_count_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, |
| "%s: touch:%d, force:%d, aod:%d, spay:%d\n", __func__, |
| ts->all_finger_count, ts->all_force_count, |
| ts->all_aod_tap_count, ts->all_spay_count); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, |
| "\"TTCN\":\"%d\",\"TFCN\":\"%d\",\"TACN\":\"%d\",\"TSCN\":\"%d\"", |
| ts->all_finger_count, ts->all_force_count, |
| ts->all_aod_tap_count, ts->all_spay_count); |
| } |
| |
| static ssize_t all_touch_count_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->all_force_count = 0; |
| ts->all_aod_tap_count = 0; |
| ts->all_spay_count = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t z_value_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| input_info(true, &ts->client->dev, "%s: max:%d, min:%d, avg:%d\n", |
| __func__, ts->max_z_value, ts->min_z_value, ts->sum_z_value); |
| |
| if (ts->all_finger_count) |
| return snprintf(buf, SEC_CMD_BUF_SIZE, |
| "\"TMXZ\":\"%d\",\"TMNZ\":\"%d\",\"TAVZ\":\"%d\"", |
| ts->max_z_value, ts->min_z_value, |
| ts->sum_z_value / ts->all_finger_count); |
| else |
| return snprintf(buf, SEC_CMD_BUF_SIZE, |
| "\"TMXZ\":\"%d\",\"TMNZ\":\"%d\"", |
| ts->max_z_value, ts->min_z_value); |
| |
| } |
| |
| static ssize_t z_value_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| |
| ts->max_z_value = 0; |
| ts->min_z_value = 0xFFFFFFFF; |
| ts->sum_z_value = 0; |
| ts->all_finger_count = 0; |
| |
| input_info(true, &ts->client->dev, "%s: clear\n", __func__); |
| |
| return count; |
| } |
| |
| static ssize_t pressure_enable_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[256] = { 0 }; |
| |
| if (ts->lowpower_mode & SEC_TS_MODE_CUSTOMLIB_FORCE_KEY) |
| snprintf(buff, sizeof(buff), "1"); |
| else |
| snprintf(buff, sizeof(buff), "0"); |
| |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buff); |
| } |
| |
| static ssize_t pressure_enable_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int ret; |
| unsigned long value = 0; |
| |
| if (count > 2) |
| return -EINVAL; |
| |
| ret = kstrtoul(buf, 10, &value); |
| if (ret != 0) |
| return ret; |
| |
| if (!ts->use_customlib) |
| return -EINVAL; |
| |
| if (value == 1) |
| ts->lowpower_mode |= SEC_TS_MODE_CUSTOMLIB_FORCE_KEY; |
| else |
| ts->lowpower_mode &= ~SEC_TS_MODE_CUSTOMLIB_FORCE_KEY; |
| |
| #ifdef SEC_TS_SUPPORT_CUSTOMLIB |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_ts_set_custom_library(ts); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| #endif |
| |
| return count; |
| } |
| |
| static ssize_t get_lp_dump_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| u8 string_data[8] = {0, }; |
| u16 current_index; |
| int i, ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "TSP turned off"); |
| } |
| |
| string_data[0] = SEC_TS_CMD_CUSTOMLIB_LP_DUMP & 0xFF; |
| string_data[1] = (SEC_TS_CMD_CUSTOMLIB_LP_DUMP & 0xFF00) >> 8; |
| |
| disable_irq(ts->client->irq); |
| |
| ret = ts->sec_ts_read_customlib(ts, string_data, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: Failed to read rect\n", |
| __func__); |
| snprintf(buf, SEC_CMD_BUF_SIZE, "NG, Failed to read rect"); |
| goto out; |
| } |
| |
| current_index = (string_data[1] & 0xFF) << 8 | (string_data[0] & 0xFF); |
| if (current_index > 1000 || current_index < 500) { |
| input_err(true, &ts->client->dev, |
| "Failed to Custom Library LP log %d\n", current_index); |
| snprintf(buf, SEC_CMD_BUF_SIZE, |
| "NG, Failed to Custom Library LP log, current_index=%d", |
| current_index); |
| goto out; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: DEBUG current_index = %d\n", __func__, current_index); |
| |
| /* Custom Library has 62 stacks for LP dump */ |
| for (i = 61; i >= 0; i--) { |
| u16 data0, data1, data2, data3; |
| char buff[30] = {0, }; |
| u16 string_addr; |
| |
| string_addr = current_index - (8 * i); |
| if (string_addr < 500) |
| string_addr += SEC_TS_CMD_CUSTOMLIB_LP_DUMP; |
| string_data[0] = string_addr & 0xFF; |
| string_data[1] = (string_addr & 0xFF00) >> 8; |
| |
| ret = ts->sec_ts_read_customlib(ts, string_data, 8); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to read rect\n", __func__); |
| snprintf(buf, SEC_CMD_BUF_SIZE, |
| "NG, Failed to read rect, addr=%d", |
| string_addr); |
| goto out; |
| } |
| |
| data0 = (string_data[1] & 0xFF) << 8 | (string_data[0] & 0xFF); |
| data1 = (string_data[3] & 0xFF) << 8 | (string_data[2] & 0xFF); |
| data2 = (string_data[5] & 0xFF) << 8 | (string_data[4] & 0xFF); |
| data3 = (string_data[7] & 0xFF) << 8 | (string_data[6] & 0xFF); |
| if (data0 || data1 || data2 || data3) { |
| snprintf(buff, sizeof(buff), |
| "%d: %04x%04x%04x%04x\n", |
| string_addr, data0, data1, data2, data3); |
| strncat(buf, buff, SEC_CMD_BUF_SIZE); |
| } |
| } |
| |
| out: |
| enable_irq(ts->client->irq); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return strlen(buf); |
| } |
| |
| static ssize_t force_recal_count_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| u8 rbuf[4] = {0, }; |
| u32 recal_count; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: Touch is stopped!\n", __func__); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", -ENODEV); |
| } |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_FORCE_RECAL_COUNT, rbuf, 4); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to read\n", __func__); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", -EIO); |
| } |
| |
| recal_count = (rbuf[0] & 0xFF) << 24 | (rbuf[1] & 0xFF) << 16 | |
| (rbuf[2] & 0xFF) << 8 | (rbuf[3] & 0xFF); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", recal_count); |
| } |
| |
| |
| /* sysfs file node to store heatmap mode |
| * "echo cmd > heatmap_mode" to change |
| * Possible commands: |
| * 0 = HEATMAP_OFF |
| * 1 = HEATMAP_PARTIAL |
| * 2 = HEATMAP_FULL |
| */ |
| static ssize_t heatmap_mode_store(struct device *dev, |
| struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| #if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP) |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_plat_data *pdata = ts->plat_data; |
| int result; |
| int val; |
| u8 config; |
| |
| result = kstrtoint(buf, 10, &val); |
| if (result < 0 || val < HEATMAP_OFF || val > HEATMAP_FULL) { |
| input_err(true, &ts->client->dev, |
| "%s: Invalid input.\n", __func__); |
| return -EINVAL; |
| } |
| |
| pdata->heatmap_mode = val; |
| |
| /* reset all heatmap settings when any change */ |
| config = 0; |
| result = ts->sec_ts_write(ts, |
| SEC_TS_CMD_HEATMAP_ENABLE, &config, 1); |
| if (result < 0) |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_HEATMAP_ENABLE, result); |
| config = TYPE_INVALID_DATA; |
| result = ts->sec_ts_write(ts, |
| SEC_TS_CMD_MUTU_RAW_TYPE, &config, 1); |
| if (result < 0) |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x failed, returned %i\n", |
| __func__, SEC_TS_CMD_MUTU_RAW_TYPE, result); |
| |
| return count; |
| #else |
| return 0; |
| #endif |
| } |
| |
| static ssize_t heatmap_mode_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| #if IS_ENABLED(CONFIG_TOUCHSCREEN_HEATMAP) |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| const struct sec_ts_plat_data *pdata = ts->plat_data; |
| |
| return scnprintf(buf, PAGE_SIZE, "%d\n", |
| pdata->heatmap_mode); |
| #else |
| return scnprintf(buf, PAGE_SIZE, "N/A\n"); |
| #endif |
| } |
| |
| static ssize_t fw_version_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int ret, written = 0; |
| u8 data[3]; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| /* If there is no FW file avaiable, |
| * sec_ts_save_version_of_ic() and sec_ts_save_version_of_bin() will |
| * no be called. Need to get through SEC_TS_READ_IMG_VERSION cmd. |
| */ |
| if (ts->plat_data->panel_revision == 0 && |
| ts->plat_data->img_version_of_bin[2] == 0 && |
| ts->plat_data->img_version_of_bin[3] == 0) { |
| u8 fw_ver[4]; |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_IMG_VERSION, fw_ver, 4); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: firmware version read error\n", __func__); |
| goto out; |
| } |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "SE-V%02X.%02X.%02X\n", |
| ts->plat_data->panel_revision, |
| fw_ver[2], |
| fw_ver[3]); |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "FW file: N/A\n"); |
| } else { |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "SE-V%02X.%02X.%02X\n", |
| ts->plat_data->panel_revision, |
| ts->plat_data->img_version_of_ic[2], |
| ts->plat_data->img_version_of_ic[3]); |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "FW file: %s\n", |
| ts->plat_data->firmware_name); |
| } |
| |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "Cal: %02X %02X %02X %02X %02X %02X %02X %02X\n", |
| ts->cali_report[0], ts->cali_report[1], ts->cali_report[2], |
| ts->cali_report[3], ts->cali_report[4], ts->cali_report[5], |
| ts->cali_report[6], ts->cali_report[7]); |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_ID, data, sizeof(data)); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to read device id(%d)\n", |
| __func__, ret); |
| goto out; |
| } |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "ID: %02X %02X %02X\n", |
| data[0], data[1], data[2]); |
| out: |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| |
| return written; |
| } |
| |
| static ssize_t status_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct sec_cmd_data *sec = dev_get_drvdata(dev); |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int written = 0; |
| unsigned char data[4] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| data[0] = 0; |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_BOOT_STATUS, data, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to read boot status(%d)\n", |
| __func__, ret); |
| goto out; |
| } |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "BOOT STATUS: 0x%02X\n", data[0]); |
| |
| memset(data, 0x0, 4); |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_TS_STATUS, data, 4); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to touch status(%d)\n", |
| __func__, ret); |
| goto out; |
| } |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "TOUCH STATUS: 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", |
| data[0], data[1], data[2], data[3]); |
| |
| memset(data, 0x0, 2); |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_SET_TOUCHFUNCTION, data, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to read touch functions(%d)\n", |
| __func__, ret); |
| goto out; |
| } |
| written += scnprintf(buf + written, PAGE_SIZE - written, |
| "Functions: 0x%02X, 0x%02X\n", data[0], data[1]); |
| |
| out: |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return written; |
| } |
| |
| static DEVICE_ATTR_RO(ito_check); |
| static DEVICE_ATTR_RO(raw_check); |
| static DEVICE_ATTR_RW(multi_count); |
| static DEVICE_ATTR_RW(wet_mode); |
| static DEVICE_ATTR_RW(comm_err_count); |
| static DEVICE_ATTR_RW(checksum); |
| static DEVICE_ATTR_RW(holding_time); |
| static DEVICE_ATTR_RW(all_touch_count); |
| static DEVICE_ATTR_RW(z_value); |
| static DEVICE_ATTR_RO(module_id); |
| static DEVICE_ATTR_RO(vendor); |
| static DEVICE_ATTR_RW(pressure_enable); |
| static DEVICE_ATTR_RO(get_lp_dump); |
| static DEVICE_ATTR_RO(force_recal_count); |
| static DEVICE_ATTR_RW(heatmap_mode); |
| static DEVICE_ATTR_RO(fw_version); |
| static DEVICE_ATTR_RO(status); |
| |
| |
| static struct attribute *cmd_attributes[] = { |
| &dev_attr_scrub_pos.attr, |
| &dev_attr_ito_check.attr, |
| &dev_attr_raw_check.attr, |
| &dev_attr_multi_count.attr, |
| &dev_attr_wet_mode.attr, |
| &dev_attr_comm_err_count.attr, |
| &dev_attr_checksum.attr, |
| &dev_attr_holding_time.attr, |
| &dev_attr_all_touch_count.attr, |
| &dev_attr_z_value.attr, |
| &dev_attr_module_id.attr, |
| &dev_attr_vendor.attr, |
| &dev_attr_pressure_enable.attr, |
| &dev_attr_get_lp_dump.attr, |
| &dev_attr_force_recal_count.attr, |
| &dev_attr_heatmap_mode.attr, |
| &dev_attr_fw_version.attr, |
| &dev_attr_status.attr, |
| NULL, |
| }; |
| |
| static struct attribute_group cmd_attr_group = { |
| .attrs = cmd_attributes, |
| }; |
| |
| static int sec_ts_check_index(struct sec_ts_data *ts) |
| { |
| struct sec_cmd_data *sec = &ts->sec; |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int node; |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > ts->tx_count |
| || sec->cmd_param[1] < 0 || sec->cmd_param[1] > ts->rx_count) { |
| |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| input_info(true, &ts->client->dev, |
| "%s: parameter error: %u, %u\n", |
| __func__, sec->cmd_param[0], sec->cmd_param[0]); |
| node = -1; |
| return node; |
| } |
| node = sec->cmd_param[1] * ts->tx_count + sec->cmd_param[0]; |
| input_info(true, &ts->client->dev, "%s: node = %d\n", __func__, node); |
| |
| return node; |
| } |
| static void fw_update(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[64] = { 0 }; |
| int retval = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| retval = sec_ts_firmware_update_on_hidden_menu(ts, sec->cmd_param[0]); |
| if (retval < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NA"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| input_err(true, &ts->client->dev, "%s: failed [%d]\n", |
| __func__, retval); |
| } else { |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: success [%d]\n", |
| __func__, retval); |
| } |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| int sec_ts_fix_tmode(struct sec_ts_data *ts, u8 mode, u8 state) |
| { |
| int ret; |
| u8 onoff[1] = {STATE_MANAGE_OFF}; |
| u8 tBuff[2] = { mode, state }; |
| |
| input_info(true, &ts->client->dev, "%s: mode %d state %d\n", |
| __func__, mode, state); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_STATEMANAGE_ON, onoff, 1); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x failed, return %i\n", |
| __func__, SEC_TS_CMD_STATEMANAGE_ON, ret); |
| sec_ts_delay(20); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CHG_SYSMODE, tBuff, |
| sizeof(tBuff)); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x failed, return %i\n", |
| __func__, SEC_TS_CMD_CHG_SYSMODE, ret); |
| sec_ts_delay(20); |
| |
| return ret; |
| } |
| |
| int sec_ts_release_tmode(struct sec_ts_data *ts) |
| { |
| int ret; |
| u8 onoff[1] = {STATE_MANAGE_ON}; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_STATEMANAGE_ON, onoff, 1); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: write reg %#x failed, return %i\n", |
| __func__, SEC_TS_CMD_STATEMANAGE_ON, ret); |
| sec_ts_delay(20); |
| |
| return ret; |
| } |
| |
| /* sec_ts_cm_spec_over_check : apply gap calculation with ts->pFrame data |
| * gap = abs(N1 - N2) / MAX(N1, N2) * 100 (%) |
| */ |
| static int sec_ts_cm_spec_over_check(struct sec_ts_data *ts, short *gap, |
| bool gap_dir) |
| { |
| int i = 0; |
| int j = 0; |
| int gapx, gapy, pos1, pos2; |
| short dpos1, dpos2; |
| int specover_count = 0; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| /* Get x-direction cm gap */ |
| if (!gap_dir) { |
| input_info(true, &ts->client->dev, "gapX TX\n"); |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count - 1; j++) { |
| /* Exclude last line to get gap between two |
| * lines. |
| */ |
| pos1 = (i * ts->tx_count) + j; |
| pos2 = (i * ts->tx_count) + (j + 1); |
| |
| dpos1 = ts->pFrame[pos1]; |
| dpos2 = ts->pFrame[pos2]; |
| |
| if (dpos1 > dpos2) |
| gapx = 100 - (dpos2 * 100 / dpos1); |
| else |
| gapx = 100 - (dpos1 * 100 / dpos2); |
| |
| gap[pos1] = gapx; |
| |
| if (gapx > cm_gap[i][j]) |
| specover_count++; |
| } |
| } |
| } |
| |
| /* get y-direction cm gap */ |
| else { |
| input_info(true, &ts->client->dev, "gapY RX\n"); |
| |
| for (i = 0; i < ts->rx_count - 1; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| pos1 = (i * ts->tx_count) + j; |
| pos2 = ((i + 1) * ts->tx_count) + j; |
| |
| dpos1 = ts->pFrame[pos1]; |
| dpos2 = ts->pFrame[pos2]; |
| |
| if (dpos1 > dpos2) |
| gapy = 100 - (dpos2 * 100 / dpos1); |
| else |
| gapy = 100 - (dpos1 * 100 / dpos2); |
| |
| gap[pos1] = gapy; |
| |
| if (gapy > cm_gap[i][j]) |
| specover_count++; |
| } |
| } |
| } |
| |
| input_info(true, &ts->client->dev, "%s: Gap NG for %d node(s)\n", |
| gap_dir == 0 ? "gapX" : "gapY", specover_count); |
| |
| return specover_count; |
| } |
| |
| static int sec_ts_cs_spec_over_check(struct sec_ts_data *ts, short *gap) |
| { |
| int i; |
| int specover_count = 0; |
| short dTmp; |
| |
| for (i = 0; i < ts->tx_count - 1; i++) { |
| dTmp = ts->pFrame[i] - ts->pFrame[i + 1]; |
| if (dTmp < 0) |
| dTmp *= -1; |
| |
| gap[i] = dTmp; |
| |
| if (dTmp > cs_tx_gap) |
| specover_count++; |
| } |
| |
| for (i = ts->tx_count; i < ts->tx_count + ts->rx_count - 1; i++) { |
| dTmp = ts->pFrame[i] - ts->pFrame[i + 1]; |
| if (dTmp < 0) |
| dTmp *= -1; |
| |
| gap[i] = dTmp; |
| |
| if (dTmp > cs_rx_gap) |
| specover_count++; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: Gap NG for %d node(s)\n", |
| __func__, specover_count); |
| |
| return specover_count; |
| } |
| |
| static int sec_ts_get_gain_table(struct sec_ts_data *ts) |
| { |
| int i, j; |
| int temp; |
| int tmp_dv; |
| unsigned int str_size, str_len = 0; |
| unsigned char *pStr = NULL; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| tmp_dv = ts->pFrame[i * ts->tx_count + j]; |
| |
| /* skip notch area */ |
| if (cm_region[i][j] == REGION_NOTCH) { |
| ts->gainTable[j * ts->rx_count + i] = 0; |
| continue; |
| } |
| |
| if (tmp_dv <= 0) { |
| input_info(true, &ts->client->dev, |
| "%s: node[%d,%d] == 0\n", __func__, i, |
| j); |
| tmp_dv = 1; |
| } |
| |
| temp = (fs_target[i][j] * 1000) / (tmp_dv) * 64; |
| /* Add 500 to round the result */ |
| temp = (temp + 500) / 1000; |
| if (temp > 255) |
| temp = 255; |
| ts->gainTable[j * ts->rx_count + i] = (temp & 0xFF); |
| } |
| } |
| |
| str_size = 6 * (ts->tx_count + 1); |
| pStr = kzalloc(str_size, GFP_KERNEL); |
| if (pStr == NULL) |
| return -ENOMEM; |
| |
| input_info(true, &ts->client->dev, "%s: Gain Table\n", __func__); |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| pStr[0] = 0; |
| str_len = 0; |
| for (j = 0; j < ts->tx_count; j++) { |
| str_len += scnprintf(pStr + str_len, str_size - str_len, |
| " %3d", |
| ts->gainTable[(j * ts->rx_count) + i]); |
| } |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| } |
| |
| kfree(pStr); |
| |
| return 0; |
| } |
| |
| static int sec_ts_write_gain_table(struct sec_ts_data *ts) |
| { |
| int node_cnt = ts->tx_count * ts->rx_count; |
| u8 *gainTable = NULL; |
| u8 *tCmd = NULL; |
| int copy_max, copy_left, copy_size, copy_cur; |
| int ret = -1; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| /* Write norm table to ic |
| * divide data into 256 bytes: |
| * buffer size limit 256 bytes |
| */ |
| gainTable = ts->gainTable; |
| |
| copy_max = ts->io_burstmax - 3; |
| copy_left = node_cnt; |
| copy_size = 0; |
| copy_cur = (copy_left > copy_max) ? copy_max : copy_left; |
| |
| tCmd = kzalloc(copy_cur + 3, GFP_KERNEL); |
| if (!tCmd) |
| goto ErrorAlloc; |
| |
| while (copy_left > 0) { |
| tCmd[0] = SEC_TS_CMD_WRITE_NORM_TABLE; |
| tCmd[1] = (copy_size >> 8) & 0xFF; |
| tCmd[2] = (copy_size >> 0) & 0xFF; |
| |
| memcpy(&tCmd[3], &gainTable[copy_size], copy_cur); |
| |
| input_info(true, &ts->client->dev, |
| "%s: left = %d, cur = %d, size = %d\n", |
| __func__, copy_left, copy_cur, copy_size); |
| |
| ret = ts->sec_ts_write_burst_heap(ts, tCmd, 3 + copy_cur); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: table write failed\n", __func__); |
| |
| copy_size += copy_cur; |
| copy_left -= copy_cur; |
| copy_cur = (copy_left > copy_max) ? copy_max : copy_left; |
| } |
| |
| ErrorAlloc: |
| kfree(tCmd); |
| |
| return ret; |
| } |
| |
| /* sec_ts_get_postcal_mean : get mean value for all nodes */ |
| static int sec_ts_get_postcal_mean(struct sec_ts_data *ts) |
| { |
| int i, j; |
| int sum = 0; |
| int nCnt = 0; |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| if (cm_region[i][j] == REGION_NOTCH) { |
| /* Count notch nodes, where fs target is 0 */ |
| nCnt++; |
| continue; |
| } |
| sum += ts->pFrame[(i * ts->tx_count) + j]; |
| } |
| } |
| |
| /* exclude notch area from average */ |
| sum = sum / (ts->tx_count * ts->rx_count - nCnt); |
| |
| return sum; |
| } |
| |
| static int sec_ts_get_postcal_uniformity(struct sec_ts_data *ts, short *diff) |
| { |
| int pos1, pos2; |
| short dpos1, dpos2, gap; |
| int i = 0; |
| int j = 0; |
| int specover_cnt = 0; |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count - 1; j++) { |
| /* At the notch boundary, skip (leave gap as 0) |
| * if node[row][col] or node[row][col+1] is 0, |
| * it is notch boundary for column direction |
| */ |
| if ((cm_region[i][j] == REGION_NOTCH) || |
| (cm_region[i][j + 1] == REGION_NOTCH)) |
| continue; |
| |
| pos1 = (i * ts->tx_count) + j; |
| pos2 = (i * ts->tx_count) + (j + 1); |
| |
| dpos1 = ts->pFrame[pos1]; |
| dpos2 = ts->pFrame[pos2]; |
| |
| gap = (dpos1 > dpos2) ? (dpos1 - dpos2) : |
| (dpos2 - dpos1); |
| |
| diff[pos1] = gap; |
| } |
| } |
| |
| for (i = 0; i < ts->rx_count - 1; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| /* At the notch boundary, skip (leave gap as 0) |
| * if node[row][col] or node[row+1][col] is 0, |
| * it is notch boundary for row direction |
| */ |
| if ((cm_region[i][j] == REGION_NOTCH) || |
| (cm_region[i + 1][j] == REGION_NOTCH)) |
| continue; |
| |
| pos1 = (i * ts->tx_count) + j; |
| pos2 = ((i + 1) * ts->tx_count) + j; |
| |
| dpos1 = ts->pFrame[pos1]; |
| dpos2 = ts->pFrame[pos2]; |
| |
| gap = (dpos1 > dpos2) ? (dpos1 - dpos2) : |
| (dpos2 - dpos1); |
| |
| /* find max gap between x and y direction */ |
| if (diff[pos1] < gap) |
| diff[pos1] = gap; |
| } |
| } |
| |
| for (i = 0; i < ts->rx_count * ts->tx_count; i++) { |
| /* since spec is in % unit, multiply 100 */ |
| diff[i] *= 100; |
| diff[i] /= (ts->fs_postcal_mean); |
| if (diff[i] > fs_postcal_uniform_spec) |
| specover_cnt++; |
| } |
| |
| return specover_cnt; |
| } |
| |
| static void sec_ts_print_frame(struct sec_ts_data *ts, short *min, short *max) |
| { |
| int i = 0; |
| int j = 0; |
| const unsigned int buff_size = 6 * (ts->tx_count + 1); |
| unsigned int buff_len = 0; |
| unsigned char *pStr = NULL; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| pStr = kzalloc(buff_size, GFP_KERNEL); |
| if (pStr == NULL) |
| return; |
| |
| buff_len += scnprintf(pStr + buff_len, buff_size - buff_len, |
| " TX"); |
| |
| for (i = 0; i < ts->tx_count; i++) |
| buff_len += scnprintf(pStr + buff_len, buff_size - buff_len, |
| " %02d ", i); |
| |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| buff_len = 0; |
| memset(pStr, 0x0, buff_size); |
| buff_len += scnprintf(pStr + buff_len, buff_size - buff_len, " +"); |
| |
| for (i = 0; i < ts->tx_count; i++) |
| buff_len += scnprintf(pStr + buff_len, buff_size - buff_len, |
| "----"); |
| |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| buff_len = 0; |
| memset(pStr, 0x0, buff_size); |
| buff_len += scnprintf(pStr + buff_len, buff_size - buff_len, |
| "Rx%02d | ", i); |
| |
| for (j = 0; j < ts->tx_count; j++) { |
| buff_len += scnprintf(pStr + buff_len, |
| buff_size - buff_len, |
| " %3d", ts->pFrame[(j * ts->rx_count) + i]); |
| |
| if (i > 0) { |
| if (ts->pFrame[(j * ts->rx_count) + i] < *min) |
| *min = ts->pFrame[(j * ts->rx_count) + |
| i]; |
| |
| if (ts->pFrame[(j * ts->rx_count) + i] > *max) |
| *max = ts->pFrame[(j * ts->rx_count) + |
| i]; |
| } |
| } |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| } |
| kfree(pStr); |
| } |
| |
| static int sec_ts_read_frame(struct sec_ts_data *ts, u8 type, short *min, |
| short *max, enum spec_check_type *spec_check) |
| { |
| unsigned int readbytes = 0xFF; |
| unsigned char *pRead = NULL; |
| u8 mode = TYPE_INVALID_DATA; |
| int ret = 0; |
| int i = 0; |
| int j = 0; |
| short dTmp = 0; |
| short *temp = NULL; |
| u8 w_type; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| /* set data length, allocation buffer memory */ |
| readbytes = ts->rx_count * ts->tx_count * 2; |
| |
| pRead = kzalloc(readbytes, GFP_KERNEL); |
| if (!pRead) |
| return -ENOMEM; |
| |
| /* set OPCODE and data type */ |
| if (type == TYPE_OFFSET_DATA_SDC_CM2) |
| w_type = TYPE_OFFSET_DATA_SDC; |
| else if (type == TYPE_OFFSET_DATA_SDC_NOT_SAVE) |
| w_type = TYPE_OFFSET_DATA_SDC; |
| else |
| w_type = type; |
| |
| /* Set raw type to TYPE_INVALID_DATA if change before */ |
| ret = ts->sec_ts_read(ts, |
| SEC_TS_CMD_MUTU_RAW_TYPE, &ts->ms_frame_type, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: read rawdata type failed\n", |
| __func__); |
| goto ErrorExit; |
| } |
| |
| if (ts->ms_frame_type != TYPE_INVALID_DATA) { |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &mode, 1); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: recover rawdata type failed\n", __func__); |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &w_type, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Set rawdata type failed\n", __func__); |
| goto ErrorExit; |
| } |
| ts->ms_frame_type = w_type; |
| |
| sec_ts_delay(50); |
| |
| if (type == TYPE_OFFSET_DATA_SDC || type == TYPE_OFFSET_DATA_SDC_CM2 |
| || type == TYPE_OFFSET_DATA_SDC_NOT_SAVE) { |
| /* excute selftest for real cap offset data, because real cap |
| * data is not memory data in normal touch. |
| **/ |
| char para = TO_TOUCH_MODE; |
| |
| disable_irq(ts->client->irq); |
| |
| if (type == TYPE_OFFSET_DATA_SDC) |
| execute_selftest(ts, |
| TEST_OPEN | TEST_NODE_VARIANCE); |
| else if (type == |
| TYPE_OFFSET_DATA_SDC_CM2) |
| execute_selftest(ts, |
| TEST_OPEN | TEST_NOT_SAVE | TEST_HIGH_FREQ); |
| else if (type == |
| TYPE_OFFSET_DATA_SDC_NOT_SAVE) |
| execute_selftest(ts, |
| TEST_OPEN | TEST_NODE_VARIANCE | TEST_NOT_SAVE); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Set powermode failed\n", __func__); |
| enable_irq(ts->client->irq); |
| goto ErrorRelease; |
| } |
| |
| /* read data and check ret later */ |
| ret = ts->sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_RAWDATA, pRead, |
| readbytes); |
| enable_irq(ts->client->irq); |
| } else |
| /* read data and check ret later */ |
| ret = ts->sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_RAWDATA, pRead, |
| readbytes); |
| |
| /* check read data */ |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: read rawdata failed!\n", __func__); |
| goto ErrorRelease; |
| } |
| |
| memset(ts->pFrame, 0x00, readbytes); |
| |
| for (i = 0; i < readbytes; i += 2) |
| ts->pFrame[i / 2] = pRead[i + 1] + (pRead[i] << 8); |
| |
| #ifdef DEBUG_MSG |
| input_info(true, &ts->client->dev, |
| "%s: 02X%02X%02X readbytes=%d\n", __func__, |
| pRead[0], pRead[1], pRead[2], readbytes); |
| #endif |
| sec_ts_print_frame(ts, min, max); |
| |
| temp = kzalloc(readbytes, GFP_KERNEL); |
| if (!temp) |
| goto ErrorRelease; |
| |
| memcpy(temp, ts->pFrame, ts->tx_count * ts->rx_count * 2); |
| memset(ts->pFrame, 0x00, ts->tx_count * ts->rx_count * 2); |
| |
| for (i = 0; i < ts->tx_count; i++) { |
| for (j = 0; j < ts->rx_count; j++) |
| ts->pFrame[(j * ts->tx_count) + i] = |
| temp[(i * ts->rx_count) + j]; |
| } |
| |
| /* spec check */ |
| if (*spec_check == SPEC_CHECK) { |
| int specover_count = 0; |
| |
| if (type == TYPE_OFFSET_DATA_SDC) { |
| unsigned int region = 0; |
| /* set initial value for min, max */ |
| for (i = 0; i < REGION_TYPE_COUNT; i++) { |
| min[i] = SHRT_MAX; |
| max[i] = SHRT_MIN; |
| } |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| dTmp = ts->pFrame[i * ts->tx_count + j]; |
| region = cm_region[i][j]; |
| |
| if (region == REGION_NOTCH) |
| continue; |
| |
| min[region] = min(min[region], dTmp); |
| max[region] = max(max[region], dTmp); |
| |
| if (dTmp > cm_max[region]) |
| specover_count++; |
| if (dTmp < cm_min[region]) |
| specover_count++; |
| } |
| } |
| input_info(true, &ts->client->dev, |
| "%s: type = %d, specover = %d\n", |
| __func__, type, specover_count); |
| |
| if (specover_count == 0 && |
| (max[REGION_NORMAL] - min[REGION_NORMAL] < |
| cm_mm[REGION_NORMAL]) && |
| (max[REGION_EDGE] - min[REGION_EDGE] < |
| cm_mm[REGION_EDGE]) && |
| (max[REGION_CORNER] - min[REGION_CORNER] < |
| cm_mm[REGION_CORNER])) |
| *spec_check = SPEC_PASS; |
| else |
| *spec_check = SPEC_FAIL; |
| } else if (type == TYPE_NOI_P2P_MIN) { |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| dTmp = ts->pFrame[i * ts->tx_count + j]; |
| if (cm_region[i][j] != REGION_NOTCH && |
| dTmp < noi_min[i][j]) |
| specover_count++; |
| } |
| } |
| input_info(true, &ts->client->dev, |
| "%s: type = %d, specover = %d\n", |
| __func__, type, specover_count); |
| |
| if (specover_count == 0) |
| *spec_check = SPEC_PASS; |
| else |
| *spec_check = SPEC_FAIL; |
| } else if (type == TYPE_NOI_P2P_MAX) { |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| dTmp = ts->pFrame[i * ts->tx_count + j]; |
| if (cm_region[i][j] != REGION_NOTCH && |
| dTmp > noi_max[i][j]) |
| specover_count++; |
| } |
| } |
| input_info(true, &ts->client->dev, |
| "%s: type = %d, specover = %d\n", |
| __func__, type, specover_count); |
| |
| if (specover_count == 0) |
| *spec_check = SPEC_PASS; |
| else |
| *spec_check = SPEC_FAIL; |
| } |
| } |
| |
| kfree(temp); |
| |
| ErrorRelease: |
| /* release data monitory (unprepare AFE data memory) */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &mode, 1); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: Set rawdata type failed\n", __func__); |
| else |
| ts->ms_frame_type = mode; |
| |
| ErrorExit: |
| kfree(pRead); |
| |
| return ret; |
| } |
| |
| static void sec_ts_print_channel(struct sec_ts_data *ts) |
| { |
| unsigned char *pStr = NULL; |
| unsigned int str_size, str_len = 0; |
| int i = 0, j = 0, k = 0; |
| |
| if (!ts->tx_count) |
| return; |
| |
| str_size = 7 * (ts->tx_count + 1); |
| pStr = vzalloc(str_size); |
| if (!pStr) |
| return; |
| |
| str_len = scnprintf(pStr, str_size, " TX"); |
| |
| for (k = 0; k < ts->tx_count; k++) { |
| str_len += scnprintf(pStr + str_len, str_size - str_len, |
| " %02d", k); |
| } |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| |
| str_len = scnprintf(pStr, str_size, " +"); |
| |
| for (k = 0; k < ts->tx_count; k++) { |
| str_len += scnprintf(pStr + str_len, str_size - str_len, |
| "------"); |
| } |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| |
| str_len = scnprintf(pStr, str_size, " | "); |
| |
| for (i = 0; i < (ts->tx_count + ts->rx_count) * 2; i += 2) { |
| if (j == ts->tx_count) { |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| input_info(true, &ts->client->dev, "\n"); |
| str_len = scnprintf(pStr, str_size, " RX"); |
| |
| for (k = 0; k < ts->tx_count; k++) { |
| str_len += scnprintf(pStr + str_len, |
| str_size - str_len, |
| " %02d", k); |
| } |
| |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| |
| str_len = scnprintf(pStr, str_size, " +"); |
| |
| for (k = 0; k < ts->tx_count; k++) { |
| str_len += scnprintf(pStr + str_len, |
| str_size - str_len, |
| "------"); |
| } |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| |
| str_len = scnprintf(pStr, str_size, " | "); |
| } else if (j && !(j % ts->tx_count)) { |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| str_len = scnprintf(pStr, str_size, " | "); |
| } |
| |
| str_len += scnprintf(pStr + str_len, str_size - str_len, " %5d", |
| ts->pFrame[j]); |
| |
| j++; |
| } |
| input_info(true, &ts->client->dev, "%s\n", pStr); |
| vfree(pStr); |
| } |
| |
| static int sec_ts_read_channel(struct sec_ts_data *ts, u8 type, short *min, |
| short *max, enum spec_check_type *spec_check) |
| { |
| unsigned char *pRead = NULL; |
| u8 mode = TYPE_INVALID_DATA; |
| int ret = 0; |
| int ii = 0; |
| int jj = 0; |
| unsigned int data_length = (ts->tx_count + ts->rx_count) * 2; |
| u8 w_data; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| pRead = kzalloc(data_length, GFP_KERNEL); |
| if (!pRead) |
| return -ENOMEM; |
| |
| /* set OPCODE and data type */ |
| if (type == TYPE_OFFSET_DATA_SDC_NOT_SAVE) |
| w_data = TYPE_OFFSET_DATA_SDC; |
| else |
| w_data = type; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SELF_RAW_TYPE, &w_data, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Set rawdata type failed\n", __func__); |
| goto out_read_channel; |
| } |
| |
| sec_ts_delay(50); |
| |
| if (type == TYPE_OFFSET_DATA_SDC || |
| type == TYPE_OFFSET_DATA_SDC_NOT_SAVE) { |
| /* excute selftest for real cap offset data, because real cap |
| * data is not memory data in normal touch. |
| **/ |
| char para = TO_TOUCH_MODE; |
| |
| disable_irq(ts->client->irq); |
| if (type == TYPE_OFFSET_DATA_SDC) |
| execute_selftest(ts, TEST_SELF_NODE); |
| else if (type == TYPE_OFFSET_DATA_SDC_NOT_SAVE) |
| execute_selftest(ts, TEST_SELF_NODE | TEST_NOT_SAVE); |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: set rawdata type failed!\n", __func__); |
| enable_irq(ts->client->irq); |
| goto err_read_data; |
| } |
| |
| /* read data and check ret later */ |
| ret = ts->sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_SELF_RAWDATA, |
| pRead, data_length); |
| enable_irq(ts->client->irq); |
| /* end */ |
| } else |
| /* read data and check ret later */ |
| ret = ts->sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_SELF_RAWDATA, |
| pRead, data_length); |
| |
| /* check read data */ |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: read rawdata failed!\n", __func__); |
| goto err_read_data; |
| } |
| |
| /* clear all pFrame data */ |
| memset(ts->pFrame, 0x00, data_length); |
| |
| /* d[00] ~ d[14] : TX channel |
| * d[15] ~ d[51] : none |
| * d[52] ~ d[77] : RX channel |
| * d[78] ~ d[103] : none |
| */ |
| for (ii = 0; ii < data_length; ii += 2) { |
| ts->pFrame[jj] = ((pRead[ii] << 8) | pRead[ii + 1]); |
| jj++; |
| } |
| |
| sec_ts_print_channel(ts); |
| |
| if (*spec_check == SPEC_CHECK) { |
| int specover_count = 0; |
| |
| if (type == TYPE_OFFSET_DATA_SDC) { |
| min[0] = min[1] = SHRT_MAX; |
| max[0] = max[1] = SHRT_MIN; |
| |
| for (ii = 0; ii < ts->tx_count; ii++) { |
| if (ts->pFrame[ii] > cs_tx_max) |
| specover_count++; |
| if (ts->pFrame[ii] < cs_tx_min) |
| specover_count++; |
| |
| min[0] = min(min[0], ts->pFrame[ii]); |
| max[0] = max(max[0], ts->pFrame[ii]); |
| } |
| for (ii = ts->tx_count; |
| ii < ts->tx_count + ts->rx_count; ii++) { |
| if (ts->pFrame[ii] > cs_rx_max) |
| specover_count++; |
| if (ts->pFrame[ii] < cs_rx_min) |
| specover_count++; |
| |
| min[1] = min(min[1], ts->pFrame[ii]); |
| max[1] = max(max[1], ts->pFrame[ii]); |
| } |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: type : %d, specover = %d\n", |
| __func__, type, specover_count); |
| |
| if (specover_count == 0 && |
| (max[0] - min[0]) < cs_tx_mm && |
| (max[1] - min[1]) < cs_rx_mm) |
| *spec_check = SPEC_PASS; |
| else |
| *spec_check = SPEC_FAIL; |
| } |
| |
| err_read_data: |
| /* release data monitory (unprepare AFE data memory) */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SELF_RAW_TYPE, &mode, 1); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: Set rawdata type failed\n", __func__); |
| |
| out_read_channel: |
| kfree(pRead); |
| |
| return ret; |
| } |
| |
| static int sec_ts_read_gain_table(struct sec_ts_data *ts) |
| { |
| int readbytes = ts->tx_count * ts->rx_count; |
| unsigned char *pRead = NULL; |
| short min = 0; |
| short max = 0; |
| int ret; |
| int i; |
| |
| /* readbytes : 1 byte for enable/disable info + 1 byte per node */ |
| pRead = kzalloc(1 + readbytes, GFP_KERNEL); |
| if (!pRead) |
| return -ENOMEM; |
| |
| ret = ts->sec_ts_read_heap(ts, SEC_TS_CMD_READ_NORM_TABLE, pRead, |
| 1 + readbytes); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: read rawdata failed!\n", |
| __func__); |
| goto ErrorRead; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: gain table is %s\n", |
| __func__, pRead[0] ? "On." : "Off."); |
| |
| for (i = 0; i < readbytes; i++) |
| ts->pFrame[i] = (short)pRead[i + 1]; |
| |
| sec_ts_print_frame(ts, &min, &max); |
| |
| ErrorRead: |
| kfree(pRead); |
| |
| return ret; |
| } |
| |
| int sec_ts_read_raw_data(struct sec_ts_data *ts, |
| struct sec_cmd_data *sec, struct sec_ts_test_mode *mode) |
| { |
| int ii, jj; |
| int ret = 0; |
| const unsigned int buff_size = ts->tx_count * ts->rx_count * |
| CMD_RESULT_WORD_LEN; |
| unsigned int buff_len = 0; |
| char *buff; |
| |
| buff = kzalloc(buff_size, GFP_KERNEL); |
| if (!buff) |
| goto error_alloc_mem; |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| goto error_power_state; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: %d, %s\n", |
| __func__, mode->type, mode->allnode ? "ALL" : ""); |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode\n", |
| __func__); |
| goto error_test_fail; |
| } |
| |
| if (mode->frame_channel) |
| ret = sec_ts_read_channel(ts, mode->type, mode->min, |
| mode->max, &mode->spec_check); |
| else |
| ret = sec_ts_read_frame(ts, mode->type, mode->min, |
| mode->max, &mode->spec_check); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to read frame\n", |
| __func__); |
| goto error_test_fail; |
| } |
| |
| if (mode->allnode) { |
| if (mode->frame_channel) { |
| if (mode->spec_check == SPEC_PASS) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "OK %d %d", |
| ts->rx_count, ts->tx_count); |
| } else if (mode->spec_check == SPEC_FAIL) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "NG %d %d", |
| ts->rx_count, ts->tx_count); |
| } |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n "); |
| if (!ts->print_format) { |
| for (ii = 0; |
| ii < (ts->rx_count + ts->tx_count); |
| ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", ts->pFrame[ii]); |
| if (ii >= ts->tx_count - 1) |
| buff_len += scnprintf( |
| buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } else { |
| for (ii = ts->tx_count; |
| ii < (ts->rx_count + ts->tx_count); |
| ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", ts->pFrame[ii]); |
| } |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n"); |
| for (ii = 0; ii < ts->tx_count; ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,\n", ts->pFrame[ii]); |
| } |
| } |
| } else { |
| if (mode->spec_check == SPEC_NO_CHECK) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n"); |
| else if (mode->spec_check == SPEC_PASS) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "OK %d %d\n", |
| ts->rx_count, ts->tx_count); |
| } else { /* mode->spec_check == SPEC_FAIL) */ |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "NG %d %d\n", ts->rx_count, |
| ts->tx_count); |
| } |
| if (!ts->print_format) { |
| for (ii = 0; |
| ii < (ts->rx_count * ts->tx_count); ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", ts->pFrame[ii]); |
| if (ii % ts->tx_count == (ts->tx_count - 1)) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } else { |
| for (ii = 0; ii < ts->tx_count; ii++) { |
| for (jj = 0; jj < ts->rx_count; jj++) { |
| buff_len += scnprintf( |
| buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", |
| ts->pFrame[(jj * |
| ts->tx_count) + ii]); |
| } |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } |
| } |
| } else { |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, |
| "%3d,%3d", mode->min[0], mode->max[0]); |
| } |
| |
| ret = sec_ts_release_tmode(ts); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to release tmode\n", __func__); |
| goto error_test_fail; |
| } |
| |
| if (!sec) |
| goto out_rawdata; |
| sec_cmd_set_cmd_result(sec, buff, buff_len); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| out_rawdata: |
| kfree(buff); |
| |
| sec_ts_locked_release_all_finger(ts); |
| |
| return ret; |
| |
| error_test_fail: |
| error_power_state: |
| kfree(buff); |
| error_alloc_mem: |
| if (!sec) |
| return ret; |
| |
| sec_cmd_set_cmd_result(sec, "FAIL", 4); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| sec_ts_locked_release_all_finger(ts); |
| |
| return ret; |
| } |
| |
| int sec_ts_check_fs_precal(struct sec_ts_data *ts) |
| { |
| int i, j; |
| int fail_count = 0; |
| short temp; |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| for (j = 0; j < ts->tx_count; j++) { |
| temp = ts->pFrame[i * ts->tx_count + j]; |
| if (cm_region[i][j] == REGION_NOTCH) |
| continue; |
| /* check whether fs_precal data is within range */ |
| if ((temp > fs_precal_h[i][j]) || |
| (temp < fs_precal_l[i][j])) |
| fail_count++; |
| } |
| } |
| |
| return fail_count; |
| } |
| |
| static void get_fw_ver_bin(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| |
| snprintf(buff, sizeof(buff), "SE-V%02X.%02X.%02X", |
| ts->plat_data->panel_revision, |
| ts->plat_data->img_version_of_bin[2], |
| ts->plat_data->img_version_of_bin[3]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void get_fw_ver_ic(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| int ret; |
| u8 fw_ver[4]; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_IMG_VERSION, fw_ver, 4); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: firmware version read error\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| snprintf(buff, sizeof(buff), "SE-V%02X.%02X.%02X", |
| ts->plat_data->panel_revision, fw_ver[2], fw_ver[3]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_config_ver(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[22] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| |
| snprintf(buff, sizeof(buff), "%s_SE_%02X%02X", |
| ts->plat_data->model_name, |
| ts->plat_data->config_version_of_ic[2], |
| ts->plat_data->config_version_of_ic[3]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| #ifdef PAT_CONTROL |
| static void get_pat_information(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[22] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| |
| /* fixed tune version will be saved at excute autotune */ |
| snprintf(buff, sizeof(buff), "P%02XT%04X", |
| ts->cal_count, ts->tune_fix_ver); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void set_external_factory(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[22] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| |
| ts->external_factory = true; |
| snprintf(buff, sizeof(buff), "OK"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| #endif |
| |
| static void get_threshold(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[20] = { 0 }; |
| char threshold[2] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| goto err; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_TOUCH_MODE_FOR_THRESHOLD, |
| threshold, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: threshold write type failed. ret: %d\n", |
| __func__, ret); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| goto err; |
| } |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_TOUCH_THRESHOLD, threshold, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: read threshold fail!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| goto err; |
| } |
| |
| input_info(true, &ts->client->dev, "0x%02X, 0x%02X\n", |
| threshold[0], threshold[1]); |
| |
| snprintf(buff, sizeof(buff), "%d", (threshold[0] << 8) | threshold[1]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| err: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void module_off_master(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[3] = { 0 }; |
| int ret = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| ret = sec_ts_stop_device(ts); |
| |
| if (ret == 0) |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| else |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| |
| sec_cmd_set_default_result(sec); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| if (strncmp(buff, "OK", 2) == 0) |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| else |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void module_on_master(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[3] = { 0 }; |
| int ret = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| ret = sec_ts_start_device(ts); |
| |
| /* TODO: check this for SPI case |
| * if (ts->input_dev->disabled) { |
| * sec_ts_set_lowpowermode(ts, TO_LOWPOWER_MODE); |
| * ts->power_status = SEC_TS_STATE_LPM; |
| * } |
| **/ |
| |
| if (ret == 0) |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| else |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| |
| sec_cmd_set_default_result(sec); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| if (strncmp(buff, "OK", 2) == 0) |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| else |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_chip_vendor(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| strncpy(buff, "SEC", sizeof(buff)); |
| sec_cmd_set_default_result(sec); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void get_chip_name(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| if (ts->plat_data->img_version_of_ic[0] == 0x02) |
| strncpy(buff, "MC44", sizeof(buff)); |
| else if (ts->plat_data->img_version_of_ic[0] == 0x05) |
| strncpy(buff, "A552", sizeof(buff)); |
| else if (ts->plat_data->img_version_of_ic[0] == 0x09) |
| strncpy(buff, "Y661", sizeof(buff)); |
| else if (ts->plat_data->img_version_of_ic[0] == 0x10) |
| strncpy(buff, "Y761", sizeof(buff)); |
| else |
| strncpy(buff, "N/A", sizeof(buff)); |
| |
| sec_cmd_set_default_result(sec); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void set_mis_cal_spec(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| char wreg[5] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->plat_data->mis_cal_check == 0) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] not support, %d\n", __func__); |
| goto NG; |
| } else if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| goto NG; |
| } else { |
| if ((sec->cmd_param[0] < 0 || sec->cmd_param[0] > 255) || |
| (sec->cmd_param[1] < 0 || sec->cmd_param[1] > 255) || |
| (sec->cmd_param[2] < 0 || sec->cmd_param[2] > 255)) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| goto NG; |
| } else { |
| wreg[0] = sec->cmd_param[0]; |
| wreg[1] = sec->cmd_param[1]; |
| wreg[2] = sec->cmd_param[2]; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_MIS_CAL_SPEC, |
| wreg, 3); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", |
| __func__, ret); |
| goto NG; |
| } else { |
| input_info(true, &ts->client->dev, |
| "%s: tx gap=%d, rx gap=%d, peak=%d\n", |
| __func__, wreg[0], wreg[1], wreg[2]); |
| sec_ts_delay(20); |
| } |
| } |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| |
| } |
| |
| /* |
| * ## Mis Cal result ## |
| * FF : initial value in Firmware. |
| * FD : Cal fail case |
| * F4 : fail case (5F) |
| * F3 : fail case (5E) |
| * F2 : power off state |
| * F1 : not support mis cal concept |
| * F0 : initial value in fucntion |
| * 08 : Ambient Ambient condition check(PEAK) result 0 (PASS), 1(FAIL) |
| * 04 : Ambient Ambient condition check(DIFF MAX TX) |
| * result 0 (PASS), 1(FAIL) |
| * 02 : Ambient Ambient condition check(DIFF MAX RX) |
| * result 0 (PASS), 1(FAIL) |
| * 01 : Wet Wet mode result 0 (PASS), 1(FAIL) |
| * 00 : Pass |
| **/ |
| static void get_mis_cal_info(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| char mis_cal_data = 0xF0; |
| char wreg[5] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->plat_data->mis_cal_check == 0) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] not support, %d\n", __func__); |
| mis_cal_data = 0xF1; |
| goto NG; |
| } else if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| mis_cal_data = 0xF2; |
| goto NG; |
| } else { |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_MIS_CAL_READ, |
| &mis_cal_data, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail!, %d\n", __func__, ret); |
| mis_cal_data = 0xF3; |
| goto NG; |
| } else { |
| input_info(true, &ts->client->dev, |
| "%s: miss cal data : %d\n", |
| __func__, mis_cal_data); |
| } |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_MIS_CAL_SPEC, wreg, 3); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail!, %d\n", __func__, ret); |
| mis_cal_data = 0xF4; |
| goto NG; |
| } else { |
| input_info(true, &ts->client->dev, |
| "%s: miss cal spec : %d,%d,%d\n", __func__, |
| wreg[0], wreg[1], wreg[2]); |
| } |
| } |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d,%d", |
| mis_cal_data, wreg[0], wreg[1], wreg[2]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| snprintf(buff, sizeof(buff), "%d,%d,%d,%d", mis_cal_data, 0, 0, 0); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_wet_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| char wet_mode_info = 0; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_WET_MODE, &wet_mode_info, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail!, %d\n", __func__, ret); |
| goto NG; |
| } |
| |
| snprintf(buff, sizeof(buff), "%d", wet_mode_info); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_x_num(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| snprintf(buff, sizeof(buff), "%d", ts->tx_count); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void get_y_num(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| snprintf(buff, sizeof(buff), "%d", ts->rx_count); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void get_x_cross_routing(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void get_y_cross_routing(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| int ret; |
| |
| sec_cmd_set_default_result(sec); |
| |
| ret = strncmp(ts->plat_data->model_name, "G935", 4) |
| && strncmp(ts->plat_data->model_name, "N930", 4); |
| if (ret == 0) |
| snprintf(buff, sizeof(buff), "13,14"); |
| else |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| } |
| |
| static void get_checksum_data(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| char csum_result[4] = { 0 }; |
| u8 cal_result; |
| u8 nv_result; |
| u8 temp; |
| u8 csum = 0; |
| int ret, i; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| goto err; |
| } |
| |
| temp = DO_FW_CHECKSUM | DO_PARA_CHECKSUM; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_GET_CHECKSUM, &temp, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: send get_checksum_cmd fail!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "SendCMDfail"); |
| goto err; |
| } |
| |
| sec_ts_delay(20); |
| |
| #ifdef I2C_INTERFACE |
| ret = ts->sec_ts_read_bulk(ts, csum_result, 4); |
| #else |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_GET_CHECKSUM, csum_result, 4); |
| #endif |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: read get_checksum result fail!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "ReadCSUMfail"); |
| goto err; |
| } |
| |
| nv_result = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_FAC_RESULT); |
| nv_result += get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_CAL_COUNT); |
| |
| cal_result = sec_ts_read_calibration_report(ts); |
| |
| for (i = 0; i < 4; i++) |
| csum += csum_result[i]; |
| |
| csum += nv_result; |
| csum += cal_result; |
| |
| csum = ~csum; |
| |
| input_info(true, &ts->client->dev, |
| "%s: checksum = %02X\n", __func__, csum); |
| snprintf(buff, sizeof(buff), "%02X", csum); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_reference_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SEC; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_reference_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SEC; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_reference(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| short val = 0; |
| int node = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| node = sec_ts_check_index(ts); |
| if (node < 0) { |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| val = ts->pFrame[node]; |
| snprintf(buff, sizeof(buff), "%d", val); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_rawcap_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SDC; |
| mode.spec_check = SPEC_CHECK; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_rawcap_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SDC; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| mode.spec_check = SPEC_CHECK; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_rawcap(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| short val = 0; |
| int node = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| node = sec_ts_check_index(ts); |
| if (node < 0) { |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| val = ts->pFrame[node]; |
| snprintf(buff, sizeof(buff), "%d", val); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_rawcap_gap_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| int ret_x, ret_y; |
| int i; |
| short *gap_x, *gap_y; |
| short dTmp; |
| char *buff; |
| char temp[SEC_CMD_STR_LEN] = { 0 }; |
| const unsigned int buff_size = ts->tx_count * ts->rx_count * 2 |
| * CMD_RESULT_WORD_LEN + 4 * CMD_RESULT_WORD_LEN; |
| const unsigned int readbytes = ts->tx_count * ts->rx_count * 2; |
| const unsigned int X_DIR = 0; |
| const unsigned int Y_DIR = 1; |
| |
| if (!sec) |
| return; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| |
| gap_x = kzalloc(readbytes, GFP_KERNEL); |
| gap_y = kzalloc(readbytes, GFP_KERNEL); |
| buff = kzalloc(buff_size, GFP_KERNEL); |
| if (!gap_x || !gap_y || !buff) { |
| snprintf(temp, sizeof(temp), "FAIL"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, temp, sizeof(temp)); |
| goto ErrorAlloc; |
| } |
| |
| mode.type = TYPE_OFFSET_DATA_SDC; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| mode.spec_check = SPEC_NO_CHECK; |
| |
| sec_ts_read_frame(ts, mode.type, mode.min, mode.max, |
| &mode.spec_check); |
| |
| ret_x = sec_ts_cm_spec_over_check(ts, gap_x, X_DIR); |
| |
| ret_y = sec_ts_cm_spec_over_check(ts, gap_y, Y_DIR); |
| |
| if (0 == (ret_x + ret_y)) { |
| strlcat(buff, "OK", buff_size); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } else { |
| strlcat(buff, "NG", buff_size); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } |
| strlcat(buff, "\n", buff_size); |
| for (i = 0; i < (ts->tx_count * ts->rx_count); i++) { |
| dTmp = (gap_x[i] > gap_y[i]) ? gap_x[i] : gap_y[i]; |
| snprintf(temp, sizeof(temp), "%3d,", dTmp); |
| strlcat(buff, temp, buff_size); |
| if (i % ts->tx_count == (ts->tx_count - 1)) |
| strlcat(buff, "\n", buff_size); |
| memset(temp, 0x00, sizeof(temp)); |
| } |
| strlcat(buff, "\n", buff_size); |
| |
| sec_cmd_set_cmd_result(sec, buff, buff_size); |
| |
| ErrorAlloc: |
| kfree(buff); |
| kfree(gap_y); |
| kfree(gap_x); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_rawcap_high_freq_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = |
| (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = |
| container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SDC_CM2; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_delta_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_SIGNAL_DATA; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_delta_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_SIGNAL_DATA; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_delta(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| short val = 0; |
| int node = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| node = sec_ts_check_index(ts); |
| if (node < 0) { |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| val = ts->pFrame[node]; |
| snprintf(buff, sizeof(buff), "%d", val); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static int sec_ts_read_frame_stdev(struct sec_ts_data *ts, |
| struct sec_cmd_data *sec, u8 type, short *min, short *max, |
| enum spec_check_type *spec_check, bool get_average_only) |
| { |
| unsigned char *pRead = NULL; |
| short *pFrameAll = NULL; |
| int *pFrameAvg = NULL; |
| u64 *pFrameStd = NULL; |
| u8 inval_type = TYPE_INVALID_DATA; |
| int node_tot = 0; |
| int ret = 0; |
| int i = 0; |
| int j = 0; |
| int frame_len_byte = 0; |
| int frame_cnt = 0; |
| int frame_tot = 0; |
| int tmp = 0; |
| |
| const unsigned int buff_size = ts->tx_count * ts->rx_count * |
| CMD_RESULT_WORD_LEN; |
| unsigned int buff_len = 0; |
| char *pBuff; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| frame_tot = 100; |
| |
| /* set data length, allocation buffer memory */ |
| |
| ret = -ENOMEM; |
| pBuff = kzalloc(buff_size, GFP_KERNEL); |
| if (!pBuff) |
| goto ErrorAlloc; |
| |
| /* each node data 2bytes : 1frame bytes = node_tot * 2 */ |
| node_tot = ts->rx_count * ts->tx_count; |
| frame_len_byte = node_tot * 2; |
| |
| pRead = kzalloc(frame_len_byte, GFP_KERNEL); |
| if (!pRead) |
| goto ErrorAlloc; |
| |
| /* memory whole frame data : 1frame bytes * total frame */ |
| pFrameAll = kzalloc(frame_len_byte * frame_tot, GFP_KERNEL); |
| if (!pFrameAll) |
| goto ErrorAlloc; |
| |
| /* float type : type size is double */ |
| pFrameAvg = kzalloc(frame_len_byte * 2, GFP_KERNEL); |
| if (!pFrameAvg) |
| goto ErrorAlloc; |
| |
| /* 64-bit to prevent overflow */ |
| pFrameStd = kzalloc(frame_len_byte * 4, GFP_KERNEL); |
| if (!pFrameStd) |
| goto ErrorAlloc; |
| |
| /* fix touch mode */ |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode\n", |
| __func__); |
| goto ErrorAlloc; |
| } |
| |
| /* set OPCODE and data type */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &type, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Set rawdata type failed\n", __func__); |
| goto ErrorDataType; |
| } |
| |
| sec_ts_delay(50); |
| |
| for (frame_cnt = 0; frame_cnt < frame_tot; frame_cnt++) { |
| /* read data */ |
| ret = ts->sec_ts_read_heap(ts, SEC_TS_READ_TOUCH_RAWDATA, |
| pRead, frame_len_byte); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: read rawdata failed!\n", __func__); |
| goto ErrorRelease; |
| } |
| |
| memset(ts->pFrame, 0x00, frame_len_byte); |
| |
| for (i = 0; i < frame_len_byte; i += 2) { |
| ts->pFrame[i / 2] = pRead[i + 1] + (pRead[i] << 8); |
| pFrameAvg[i / 2] += ts->pFrame[i / 2]; |
| } |
| |
| memcpy(pFrameAll + (frame_len_byte * frame_cnt) / sizeof(short), |
| ts->pFrame, frame_len_byte); |
| } |
| |
| /* get total frame average of each node */ |
| /* in the case of getting only average, *1000 not needed */ |
| for (j = 0; j < node_tot; j++) { |
| if (!get_average_only) |
| pFrameAvg[j] = pFrameAvg[j] * 1000; |
| pFrameAvg[j] = pFrameAvg[j] / frame_tot; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: FrameAvg x 1000\n", __func__); |
| |
| /* print frame average x 1000 of each node */ |
| for (i = 0; i < ts->rx_count; i++) { |
| buff_len = scnprintf(pBuff, buff_size, "Rx%02d | ", i); |
| |
| for (j = 0; j < ts->tx_count; j++) { |
| buff_len += scnprintf(pBuff + buff_len, |
| buff_size - buff_len, |
| " %6d", |
| pFrameAvg[(j * ts->rx_count) + i]); |
| } |
| input_info(true, &ts->client->dev, "%s\n", pBuff); |
| } |
| |
| /* when only getting average, put average in |
| * ts->pFrame and goto set cmd_result |
| */ |
| if (get_average_only) { |
| for (i = 0; i < ts->tx_count; i++) { |
| for (j = 0; j < ts->rx_count; j++) { |
| ts->pFrame[(j * ts->tx_count) + i] = |
| (short)(pFrameAvg[(i * ts->rx_count) + |
| j]); |
| } |
| } |
| goto OnlyAverage; |
| } |
| |
| /* get standard deviation */ |
| for (i = 0; i < frame_tot; i++) { |
| for (j = 0; j < node_tot; j++) { |
| tmp = pFrameAll[node_tot * i + j] * 1000; |
| pFrameStd[j] = pFrameStd[j] + |
| (tmp - pFrameAvg[j]) * (tmp - pFrameAvg[j]); |
| } |
| } |
| |
| for (j = 0; j < node_tot; j++) |
| pFrameStd[j] = int_sqrt(pFrameStd[j] / frame_tot); |
| |
| /* print standard deviation x 1000 of each node */ |
| input_info(true, &ts->client->dev, "%s: FrameStd x 1000\n", __func__); |
| |
| *min = *max = pFrameStd[0]; |
| |
| for (i = 0; i < ts->rx_count; i++) { |
| buff_len = scnprintf(pBuff, buff_size, "Rx%02d | ", i); |
| |
| for (j = 0; j < ts->tx_count; j++) { |
| if (i > 0) { |
| if (pFrameStd[(j * ts->rx_count) + i] < *min) |
| *min = |
| pFrameStd[(j * ts->rx_count) + i]; |
| |
| if (pFrameStd[(j * ts->rx_count) + i] > *max) |
| *max = |
| pFrameStd[(j * ts->rx_count) + i]; |
| } |
| buff_len += scnprintf(pBuff + buff_len, |
| buff_size - buff_len, |
| " %6d", |
| (int)pFrameStd[(j * ts->rx_count) + i]); |
| } |
| input_info(true, &ts->client->dev, "%s\n", pBuff); |
| } |
| // SQRT(VAR) |
| |
| /* Rotate 90 degrees for readability */ |
| for (i = 0; i < ts->tx_count; i++) { |
| for (j = 0; j < ts->rx_count; j++) { |
| if (pFrameStd[(i * ts->rx_count) + j] > 32767) |
| /* Reduce to short data type and allow high |
| * values to saturate. |
| */ |
| ts->pFrame[(j * ts->tx_count) + i] = 32767; |
| else { |
| ts->pFrame[(j * ts->tx_count) + i] = |
| (short)(pFrameStd[(i * ts->rx_count) + |
| j]); |
| } |
| } |
| } |
| |
| if (*spec_check == SPEC_CHECK) { |
| int specover_count = 0; |
| |
| for (i = 0; i < ts->tx_count; i++) { |
| for (j = 0; j < ts->rx_count; j++) { |
| if (ts->pFrame[(j * ts->tx_count) + i] > |
| cm_stdev_max) |
| specover_count++; |
| } |
| } |
| |
| if (specover_count == 0) |
| *spec_check = SPEC_PASS; |
| else |
| *spec_check = SPEC_FAIL; |
| } |
| |
| if (*spec_check == SPEC_PASS) |
| buff_len = scnprintf(pBuff, buff_size, "OK %d %d\n", |
| ts->rx_count, ts->tx_count); |
| else if (*spec_check == SPEC_FAIL) |
| buff_len = scnprintf(pBuff, buff_size, "NG %d %d\n", |
| ts->rx_count, ts->tx_count); |
| else |
| buff_len = scnprintf(pBuff, buff_size, "\n"); |
| |
| for (i = 0; i < node_tot; i++) { |
| buff_len += scnprintf(pBuff + buff_len, buff_size - buff_len, |
| "%4d,", ts->pFrame[i]); |
| |
| if (i % ts->tx_count == ts->tx_count - 1) |
| buff_len += scnprintf(pBuff + buff_len, |
| buff_size - buff_len, "\n"); |
| } |
| |
| if (!sec) |
| goto ErrorRelease; |
| |
| sec_cmd_set_cmd_result(sec, pBuff, buff_len); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| ErrorRelease: |
| OnlyAverage: |
| /* release data monitory (unprepare AFE data memory) */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_MUTU_RAW_TYPE, &inval_type, |
| 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Set rawdata type failed\n", __func__); |
| goto ErrorAlloc; |
| } |
| |
| ErrorDataType: |
| /* release mode fix */ |
| ret = sec_ts_release_tmode(ts); |
| if (ret < 0) { |
| input_err(true, |
| &ts->client->dev, "%s: failed to release tmode\n", |
| __func__); |
| } |
| |
| ErrorAlloc: |
| kfree(pFrameStd); |
| kfree(pFrameAvg); |
| kfree(pFrameAll); |
| kfree(pRead); |
| kfree(pBuff); |
| |
| return ret; |
| } |
| |
| static void run_rawdata_stdev_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_REMV_AMB_DATA; |
| mode.spec_check = SPEC_CHECK; |
| |
| sec_ts_read_frame_stdev(ts, sec, mode.type, mode.min, mode.max, |
| &mode.spec_check, false); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static int sec_ts_read_frame_p2p(struct sec_ts_data *ts, |
| struct sec_cmd_data *sec, struct sec_ts_test_mode mode) |
| { |
| const unsigned int frame_size = ts->rx_count * ts->tx_count * 2; |
| short *temp = NULL; |
| unsigned short readbytes; |
| int i; |
| int ret = -1; |
| char para = TO_TOUCH_MODE; |
| const unsigned int buff_size = ts->tx_count * ts->rx_count * |
| CMD_RESULT_WORD_LEN; |
| unsigned int buff_len = 0; |
| char *buff; |
| u8 result = 0x0; |
| |
| buff = kzalloc(buff_size, GFP_KERNEL); |
| if (!buff) |
| goto ErrorAllocbuff; |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| goto ErrorPowerState; |
| } |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| |
| disable_irq(ts->client->irq); |
| |
| ret = execute_p2ptest(ts); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: P2P test failed\n", |
| __func__); |
| goto ErrorP2PTest; |
| } |
| |
| /* get min data */ |
| mode.type = TYPE_NOI_P2P_MIN; |
| mode.spec_check = SPEC_CHECK; |
| sec_ts_read_frame(ts, mode.type, mode.min, mode.max, |
| &mode.spec_check); |
| if (mode.spec_check == SPEC_FAIL) |
| result |= 0x1; |
| |
| readbytes = ts->rx_count * ts->tx_count; |
| |
| /* 2 bytes for each node data */ |
| temp = kzalloc(frame_size, GFP_KERNEL); |
| if (!temp) |
| goto ErrorAlloctemp; |
| |
| memcpy(temp, ts->pFrame, frame_size); |
| memset(ts->pFrame, 0x00, frame_size); |
| |
| /* get max data */ |
| mode.type = TYPE_NOI_P2P_MAX; |
| mode.spec_check = SPEC_CHECK; |
| sec_ts_read_frame(ts, mode.type, mode.min, mode.max, |
| &mode.spec_check); |
| if (mode.spec_check == SPEC_FAIL) |
| result |= 0x2; |
| |
| for (i = 0; i < readbytes; i++) { |
| /* get p2p by subtract min from max data */ |
| ts->pFrame[i] = ts->pFrame[i] - temp[i]; |
| if (ts->pFrame[i] > noi_mm) |
| result |= 0x4; |
| } |
| |
| if (result != 0x0) |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, |
| "NG\n"); |
| else |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, |
| "OK\n"); |
| |
| for (i = 0; i < readbytes; i++) { |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, |
| "%3d,", ts->pFrame[i]); |
| if (i % ts->tx_count == (ts->tx_count - 1)) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n"); |
| } |
| |
| if (sec) { |
| sec_cmd_set_cmd_result(sec, buff, buff_len); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| kfree(temp); |
| ErrorAlloctemp: |
| ErrorP2PTest: |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE, ¶, 1); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, "%s: Set powermode failed\n", |
| __func__); |
| |
| enable_irq(ts->client->irq); |
| ErrorPowerState: |
| kfree(buff); |
| ErrorAllocbuff: |
| |
| if (sec && ret < 0) { |
| sec_cmd_set_cmd_result(sec, "NG", 3); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } |
| |
| return ret; |
| } |
| |
| static void run_rawdata_p2p_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| |
| sec_ts_read_frame_p2p(ts, sec, mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| /* self reference : send TX power in TX channel, receive in TX channel */ |
| static void run_self_reference_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SEC; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_self_reference_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SEC; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_self_rawcap_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SDC; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| mode.spec_check = SPEC_CHECK; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_self_rawcap_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SDC; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| mode.spec_check = SPEC_CHECK; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_self_rawcap_gap_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| int i; |
| int ret = 0; |
| char *buff = NULL; |
| short *gap = NULL; |
| const int gap_buff_size = (ts->tx_count - 1) + (ts->rx_count - 1); |
| const int buff_size = gap_buff_size * CMD_RESULT_WORD_LEN + 4; |
| unsigned int buff_len = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_OFFSET_DATA_SDC; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| gap = kzalloc(gap_buff_size, GFP_KERNEL); |
| buff = kzalloc(buff_size, GFP_KERNEL); |
| if (!gap || !buff) { |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "FAIL", 4); |
| goto ErrorAlloc; |
| } |
| |
| sec_ts_read_channel(ts, mode.type, mode.min, mode.max, |
| &mode.spec_check); |
| |
| /* ret is number of spec over channel */ |
| ret = sec_ts_cs_spec_over_check(ts, gap); |
| |
| if (ret == 0) { |
| buff_len = scnprintf(buff, buff_size, "OK\n "); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } else { |
| buff_len = scnprintf(buff, buff_size, "NG\n "); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } |
| |
| for (i = 0; i < (ts->tx_count - 1); i++) { |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, |
| "%6d,", gap[i]); |
| } |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, "\n"); |
| |
| for (i = ts->tx_count; i < ts->tx_count + (ts->rx_count - 1); i++) { |
| buff_len += scnprintf(buff + buff_len, buff_size - buff_len, |
| "%6d,\n", gap[i]); |
| } |
| |
| sec_cmd_set_cmd_result(sec, buff, buff_len); |
| |
| ErrorAlloc: |
| kfree(buff); |
| kfree(gap); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_self_delta_read(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_SIGNAL_DATA; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_self_delta_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_SIGNAL_DATA; |
| mode.frame_channel = TEST_MODE_READ_CHANNEL; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| sec_ts_read_raw_data(ts, sec, &mode); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| /* Use TSP NV area |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, value is 1 - 1 = 0) |
| * buff[2] : write data |
| * buff[..] : cont. |
| */ |
| void set_tsp_nvm_data_clear(struct sec_ts_data *ts, u8 offset) |
| { |
| char buff[4] = { 0 }; |
| int ret; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| buff[0] = offset; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 3); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| |
| sec_ts_delay(20); |
| } |
| |
| int get_tsp_nvm_data(struct sec_ts_data *ts, u8 offset) |
| { |
| char buff[2] = { 0 }; |
| int ret; |
| |
| /* SENSE OFF -> CELAR EVENT STACK -> READ NV -> SENSE ON */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_OFF, NULL, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to write Sense_off\n", __func__); |
| goto out_nvm; |
| } |
| |
| input_dbg(true, &ts->client->dev, "%s: SENSE OFF\n", __func__); |
| |
| sec_ts_delay(100); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CLEAR_EVENT_STACK, NULL, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write clear event failed\n", __func__); |
| goto out_nvm; |
| } |
| |
| input_dbg(true, &ts->client->dev, "%s: CLEAR EVENT STACK\n", __func__); |
| |
| sec_ts_delay(100); |
| |
| sec_ts_locked_release_all_finger(ts); |
| |
| /* send NV data using command |
| * Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| **/ |
| memset(buff, 0x00, 2); |
| buff[0] = offset; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm send command failed. ret: %d\n", |
| __func__, ret); |
| goto out_nvm; |
| } |
| |
| sec_ts_delay(20); |
| |
| /* read NV data |
| * Use TSP NV area : in this model, use only one byte |
| */ |
| #ifdef I2C_INTERFACE |
| ret = ts->sec_ts_read_bulk(ts, buff, 1); |
| #else |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_NVM, buff, 1); |
| #endif |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm send command failed. ret: %d\n", |
| __func__, ret); |
| goto out_nvm; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: offset:%u data:%02X\n", __func__, offset, buff[0]); |
| |
| out_nvm: |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: fail to write Sense_on\n", __func__); |
| |
| input_dbg(true, &ts->client->dev, "%s: SENSE ON\n", __func__); |
| |
| return buff[0]; |
| } |
| |
| int get_tsp_nvm_data_by_size(struct sec_ts_data *ts, u8 offset, |
| int length, u8 *data) |
| { |
| char *buff = NULL; |
| int ret; |
| |
| buff = kzalloc(length, GFP_KERNEL); |
| if (!buff) |
| return -ENOMEM; |
| |
| input_info(true, &ts->client->dev, |
| "%s: offset:%u, length:%d, size:%d\n", |
| __func__, offset, length, sizeof(data)); |
| |
| /* SENSE OFF -> CELAR EVENT STACK -> READ NV -> SENSE ON */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_OFF, NULL, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to write Sense_off\n", __func__); |
| goto out_nvm; |
| } |
| |
| input_dbg(true, &ts->client->dev, "%s: SENSE OFF\n", __func__); |
| |
| sec_ts_delay(100); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CLEAR_EVENT_STACK, NULL, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: write clear event failed\n", __func__); |
| goto out_nvm; |
| } |
| |
| input_dbg(true, &ts->client->dev, "%s: CLEAR EVENT STACK\n", __func__); |
| |
| sec_ts_delay(100); |
| |
| sec_ts_locked_release_all_finger(ts); |
| |
| /* send NV data using command |
| * Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| **/ |
| memset(buff, 0x00, 2); |
| buff[0] = offset; |
| buff[1] = length - 1; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm send command failed. ret: %d\n", |
| __func__, ret); |
| goto out_nvm; |
| } |
| |
| sec_ts_delay(20); |
| |
| /* read NV data |
| * Use TSP NV area : in this model, use only one byte |
| */ |
| #ifdef I2C_INTERFACE |
| ret = ts->sec_ts_read_bulk_heap(ts, buff, length); |
| #else |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_NVM, buff, length); |
| #endif |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm send command failed. ret: %d\n", |
| __func__, ret); |
| goto out_nvm; |
| } |
| |
| memcpy(data, buff, length); |
| |
| out_nvm: |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SENSE_ON, NULL, 0); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: fail to write Sense_on\n", __func__); |
| |
| input_dbg(true, &ts->client->dev, "%s: SENSE ON\n", __func__); |
| |
| kfree(buff); |
| |
| return ret; |
| } |
| |
| #ifdef PAT_CONTROL |
| void set_pat_magic_number(struct sec_ts_data *ts) |
| { |
| char buff[4] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| buff[0] = SEC_TS_NVM_OFFSET_CAL_COUNT; |
| buff[1] = 0; |
| buff[2] = PAT_MAGIC_NUMBER; |
| |
| input_info(true, &ts->client->dev, "%s: %02X\n", __func__, buff[2]); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 3); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| } |
| sec_ts_delay(20); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| #endif |
| |
| |
| /* FACTORY TEST RESULT SAVING FUNCTION |
| * bit 3 ~ 0 : OCTA Assy |
| * bit 7 ~ 4 : OCTA module |
| * param[0] : OCTA modue(1) / OCTA Assy(2) |
| * param[1] : TEST NONE(0) / TEST FAIL(1) / TEST PASS(2) : 2 bit |
| */ |
| |
| #define TEST_OCTA_MODULE 1 |
| #define TEST_OCTA_ASSAY 2 |
| |
| #define TEST_OCTA_NONE 0 |
| #define TEST_OCTA_FAIL 1 |
| #define TEST_OCTA_PASS 2 |
| |
| static void set_tsp_test_result(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_result *result; |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| char r_data[1] = { 0 }; |
| int ret = 0; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP_truned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| r_data[0] = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_FAC_RESULT); |
| if (r_data[0] == 0xFF) |
| r_data[0] = 0; |
| |
| result = (struct sec_ts_test_result *)r_data; |
| |
| if (sec->cmd_param[0] == TEST_OCTA_ASSAY) { |
| result->assy_result = sec->cmd_param[1]; |
| if (result->assy_count < 3) |
| result->assy_count++; |
| } |
| |
| if (sec->cmd_param[0] == TEST_OCTA_MODULE) { |
| result->module_result = sec->cmd_param[1]; |
| if (result->module_count < 3) |
| result->module_count++; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: %d, %d, %d, %d, 0x%X\n", __func__, |
| result->module_result, result->module_count, |
| result->assy_result, result->assy_count, result->data[0]); |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * buff[2] : write data |
| **/ |
| memset(buff, 0x00, SEC_CMD_STR_LEN); |
| buff[2] = *result->data; |
| |
| input_info(true, &ts->client->dev, "%s: command (1)%X, (2)%X: %X\n", |
| __func__, sec->cmd_param[0], sec->cmd_param[1], buff[2]); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 3); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| |
| sec_ts_delay(20); |
| |
| ts->nv = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_FAC_RESULT); |
| |
| snprintf(buff, sizeof(buff), "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_tsp_test_result(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| struct sec_ts_test_result *result; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP_truned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| memset(buff, 0x00, SEC_CMD_STR_LEN); |
| buff[0] = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_FAC_RESULT); |
| if (buff[0] == 0xFF) { |
| set_tsp_nvm_data_clear(ts, SEC_TS_NVM_OFFSET_FAC_RESULT); |
| buff[0] = 0; |
| } |
| |
| ts->nv = buff[0]; |
| |
| result = (struct sec_ts_test_result *)buff; |
| |
| input_info(true, &ts->client->dev, |
| "%s: [0x%X][0x%X] M:%d, M:%d, A:%d, A:%d\n", |
| __func__, *result->data, buff[0], |
| result->module_result, result->module_count, |
| result->assy_result, result->assy_count); |
| |
| snprintf(buff, sizeof(buff), "M:%s, M:%d, A:%s, A:%d", |
| result->module_result == 0 ? "NONE" : |
| result->module_result == 1 ? "FAIL" : "PASS", |
| result->module_count, |
| result->assy_result == 0 ? "NONE" : |
| result->assy_result == 1 ? "FAIL" : "PASS", |
| result->assy_count); |
| |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void increase_disassemble_count(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[3] = { 0 }; |
| int ret = 0; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP_truned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| buff[2] = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_DISASSEMBLE_COUNT); |
| |
| input_info(true, &ts->client->dev, |
| "%s: disassemble count is #1 %d\n", __func__, buff[2]); |
| |
| if (buff[2] == 0xFF) |
| buff[2] = 0; |
| |
| if (buff[2] < 0xFE) |
| buff[2]++; |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * buff[2] : write data |
| **/ |
| buff[0] = SEC_TS_NVM_OFFSET_DISASSEMBLE_COUNT; |
| buff[1] = 0; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 3); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| |
| sec_ts_delay(20); |
| |
| memset(buff, 0x00, 3); |
| buff[0] = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_DISASSEMBLE_COUNT); |
| input_info(true, &ts->client->dev, |
| "%s: check disassemble count: %d\n", __func__, buff[0]); |
| |
| snprintf(buff, sizeof(buff), "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_disassemble_count(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| input_info(true, &ts->client->dev, "%s\n", __func__); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: [ERROR] Touch is stopped\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP_truned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| memset(buff, 0x00, SEC_CMD_STR_LEN); |
| buff[0] = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_DISASSEMBLE_COUNT); |
| if (buff[0] == 0xFF) { |
| set_tsp_nvm_data_clear(ts, SEC_TS_NVM_OFFSET_DISASSEMBLE_COUNT); |
| buff[0] = 0; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: read disassemble count: %d\n", __func__, buff[0]); |
| |
| snprintf(buff, sizeof(buff), "%d", buff[0]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| #define GLOVE_MODE_EN (1 << 0) |
| #define CLEAR_COVER_EN (1 << 1) |
| #define FAST_GLOVE_MODE_EN (1 << 2) |
| |
| static void glove_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int glove_mode_enables = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| snprintf(buff, sizeof(buff), "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| int retval; |
| |
| if (sec->cmd_param[0]) |
| glove_mode_enables |= GLOVE_MODE_EN; |
| else |
| glove_mode_enables &= ~(GLOVE_MODE_EN); |
| |
| retval = sec_ts_glove_mode_enables(ts, glove_mode_enables); |
| |
| if (retval < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed, retval = %d\n", __func__, retval); |
| snprintf(buff, sizeof(buff), "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| snprintf(buff, sizeof(buff), "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| } |
| |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| sec->cmd_state = SEC_CMD_STATUS_WAITING; |
| sec_cmd_set_cmd_exit(sec); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void clear_cover_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| input_info(true, &ts->client->dev, |
| "%s...\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| if (sec->cmd_param[0] > 1) { |
| ts->flip_enable = true; |
| ts->cover_type = sec->cmd_param[1]; |
| ts->cover_cmd = (u8)ts->cover_type; |
| } else { |
| ts->flip_enable = false; |
| } |
| |
| if (!(ts->power_status == SEC_TS_STATE_POWER_OFF) && |
| ts->reinit_done) { |
| if (ts->flip_enable) |
| sec_ts_set_cover_type(ts, true); |
| else |
| sec_ts_set_cover_type(ts, false); |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_WAITING; |
| sec_cmd_set_cmd_exit(sec); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| }; |
| |
| static void dead_zone_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int ret; |
| char data = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| data = sec->cmd_param[0]; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_EDGE_DEADZONE, &data, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to set deadzone\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto err_set_dead_zone; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| err_set_dead_zone: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| }; |
| |
| |
| static void drawing_test_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| if (ts->use_customlib) { |
| if (sec->cmd_param[0]) |
| ts->lowpower_mode &= |
| ~SEC_TS_MODE_CUSTOMLIB_FORCE_KEY; |
| else |
| ts->lowpower_mode |= |
| SEC_TS_MODE_CUSTOMLIB_FORCE_KEY; |
| |
| #ifdef SEC_TS_SUPPORT_CUSTOMLIB |
| ret = sec_ts_set_custom_library(ts); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| #endif |
| |
| } else { |
| snprintf(buff, sizeof(buff), "%s", "NA"); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| } |
| } |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| }; |
| |
| static void sec_ts_swap(u8 *a, u8 *b) |
| { |
| u8 temp = *a; |
| |
| *a = *b; |
| *b = temp; |
| } |
| |
| static void rearrange_sft_result(u8 *data, int length) |
| { |
| int i; |
| |
| for (i = 0; i < length; i += 4) { |
| sec_ts_swap(&data[i], &data[i + 3]); |
| sec_ts_swap(&data[i + 1], &data[i + 2]); |
| } |
| } |
| |
| int execute_p2ptest(struct sec_ts_data *ts) |
| { |
| int rc; |
| u8 tpara[2] = {0x0F, 0x11}; |
| |
| input_info(true, &ts->client->dev, "%s: P2P test start!\n", __func__); |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_SET_P2PTEST_MODE, tpara, 2); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Send P2Ptest Mode cmd failed!\n", __func__); |
| goto err_exit; |
| } |
| |
| sec_ts_delay(15); |
| |
| tpara[0] = 0x00; |
| tpara[1] = 0x64; |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_P2PTEST, tpara, 2); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Send P2Ptest cmd failed!\n", __func__); |
| goto err_exit; |
| } |
| |
| sec_ts_delay(1500); |
| |
| rc = sec_ts_wait_for_ready(ts, SEC_TS_VENDOR_ACK_P2P_TEST_DONE); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: P2Ptest execution time out!\n", __func__); |
| goto err_exit; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: P2P test done!\n", __func__); |
| |
| err_exit: |
| return rc; |
| } |
| |
| /* execute_selftest options |
| * bit[8] : Enable/disable the panel crack test |
| * bit[7] : Do NOT save |
| * bit[6] : Load self-test configuration only |
| * bit[5] : Get Self capacitance |
| * bit[4] : Reserved |
| * bit[3] : Reserved |
| * bit[2] : Enable/disable the short test |
| * bit[1] : Enable/disable the node variance test |
| * bit[0] : Enable/disable the open test |
| */ |
| int execute_selftest(struct sec_ts_data *ts, u32 option) |
| { |
| int rc; |
| /* Selftest setting |
| * Get self capacitance |
| * Enable/disable the short test |
| * Enable/disable the node variance test |
| * Enable/disable the open test |
| */ |
| u8 tpara[2] = {(u8)(option & 0xff), (u8)((option & 0xff00) >> 8)}; |
| u8 *rBuff; |
| int i; |
| int result_size = SEC_TS_SELFTEST_REPORT_SIZE + |
| ts->tx_count * ts->rx_count * 2; |
| |
| rBuff = kzalloc(result_size, GFP_KERNEL); |
| if (!rBuff) |
| return -ENOMEM; |
| |
| input_info(true, &ts->client->dev, "%s: Self test start!\n", __func__); |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_SELFTEST, tpara, 2); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Send selftest cmd failed!\n", __func__); |
| goto err_exit; |
| } |
| |
| sec_ts_delay(1500); |
| |
| rc = sec_ts_wait_for_ready(ts, SEC_TS_VENDOR_ACK_SELF_TEST_DONE); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Selftest execution time out!\n", __func__); |
| goto err_exit; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: Self test done!\n", __func__); |
| |
| rc = ts->sec_ts_read_heap(ts, SEC_TS_READ_SELFTEST_RESULT, rBuff, |
| result_size); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Selftest execution time out!\n", __func__); |
| goto err_exit; |
| } |
| rearrange_sft_result(rBuff, result_size); |
| |
| for (i = 0; i < 80; i += 4) { |
| if (i % 8 == 0) pr_cont("\n"); |
| if (i % 4 == 0) pr_cont("%s sec_ts : ", SECLOG); |
| |
| if (i / 4 == 0) pr_cont("SIG"); |
| else if (i / 4 == 1) pr_cont("VER"); |
| else if (i / 4 == 2) pr_cont("SIZ"); |
| else if (i / 4 == 3) pr_cont("CRC"); |
| else if (i / 4 == 4) pr_cont("RES"); |
| else if (i / 4 == 5) pr_cont("COU"); |
| else if (i / 4 == 6) pr_cont("PAS"); |
| else if (i / 4 == 7) pr_cont("FAI"); |
| else if (i / 4 == 8) pr_cont("CHA"); |
| else if (i / 4 == 9) pr_cont("AMB"); |
| else if (i / 4 == 10) pr_cont("RXS"); |
| else if (i / 4 == 11) pr_cont("TXS"); |
| else if (i / 4 == 12) pr_cont("RXO"); |
| else if (i / 4 == 13) pr_cont("TXO"); |
| else if (i / 4 == 14) pr_cont("RXG"); |
| else if (i / 4 == 15) pr_cont("TXG"); |
| else if (i / 4 == 16) pr_cont("RXR"); |
| else if (i / 4 == 17) pr_cont("TXT"); |
| else if (i / 4 == 18) pr_cont("RXT"); |
| else if (i / 4 == 19) pr_cont("TXR"); |
| |
| pr_cont(" %2X, %2X, %2X, %2X ", |
| rBuff[i], rBuff[i + 1], rBuff[i + 2], rBuff[i + 3]); |
| |
| |
| if (i / 4 == 4) { |
| /* RX, RX open check. */ |
| if ((rBuff[i + 3] & 0x30) != 0) |
| rc = 0; |
| /* TX, RX GND(VDD) short check. */ |
| else if ((rBuff[i + 3] & 0xC0) != 0) |
| rc = 0; |
| /* RX-RX, TX-TX short check. */ |
| else if ((rBuff[i + 2] & 0x03) != 0) |
| rc = 0; |
| /* TX-RX short check. */ |
| else if ((rBuff[i + 2] & 0x04) != 0) |
| rc = 0; |
| else |
| rc = 1; |
| |
| ts->ito_test[0] = rBuff[i]; |
| ts->ito_test[1] = rBuff[i + 1]; |
| ts->ito_test[2] = rBuff[i + 2]; |
| ts->ito_test[3] = rBuff[i + 3]; |
| } |
| |
| } |
| |
| err_exit: |
| kfree(rBuff); |
| return rc; |
| } |
| |
| static void run_fs_cal_pre_press(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int ret = 0; |
| u8 off[1] = {STATE_MANAGE_OFF}; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| input_info(true, &ts->client->dev, "%s: initial sequence for fs cal\n", |
| __func__); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| goto ErrorPowerOff; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_GAIN_LIMIT, off, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to disable gain limit\n", __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: fail to fix tmode\n", |
| __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_BASELINE_ADAPT, off, |
| 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to disable baselineAdapt\n", __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_DF, off, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: fail to disable df\n", |
| __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_TOUCH_ENGINE_MODE, |
| off, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to disable touch engine\n", __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_RESET_BASELINE, NULL, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: fail to fix tmode\n", |
| __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| sec_ts_delay(50); |
| |
| input_info(true, &ts->client->dev, "%s: ready to press\n", __func__); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| ErrorSendingCmd: |
| ErrorPowerOff: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_fs_cal_get_data(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| struct sec_ts_test_mode mode; |
| short *diff_table = NULL; |
| const bool only_average = true; |
| char *buff; |
| int ret; |
| int i, j; |
| const unsigned int buff_size = ts->tx_count * ts->rx_count * |
| CMD_RESULT_WORD_LEN; |
| unsigned int buff_len = 0; |
| |
| input_info(true, &ts->client->dev, "%s: fs cal with stim pad\n", |
| __func__); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) { |
| input_err(true, &ts->client->dev, |
| "%s: Parameter Error\n", __func__); |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| buff = kzalloc(buff_size, GFP_KERNEL); |
| if (!buff) { |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| memset(&mode, 0x00, sizeof(struct sec_ts_test_mode)); |
| |
| if (sec->cmd_param[0] == 0) { |
| mode.type = TYPE_REMV_AMB_DATA; |
| mode.spec_check = SPEC_NO_CHECK; |
| ret = sec_ts_read_frame_stdev(ts, sec, mode.type, mode.min, |
| mode.max, &mode.spec_check, only_average); |
| if (ret < 0) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto SetCmdResult; |
| } |
| ret = sec_ts_check_fs_precal(ts); |
| |
| /* ret = NG node count */ |
| if (ret > 0) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "NG\n"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "OK\n"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| for (i = 0; i < ts->tx_count * ts->rx_count; i++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "%4d,", |
| ts->pFrame[i]); |
| |
| if (i % ts->tx_count == ts->tx_count - 1) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| /* calculate gain table, and store it to ts->gainTable */ |
| sec_ts_get_gain_table(ts); |
| |
| } else if (sec->cmd_param[0] == 1) { |
| /* write gaintable(ts->gainTable) to ic */ |
| ret = sec_ts_write_gain_table(ts); |
| if (ret < 0) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "NG %d %d\n", |
| ts->rx_count, ts->tx_count); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "OK %d %d\n", |
| ts->rx_count, ts->tx_count); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| for (j = 0; j < ts->rx_count; j++) { |
| for (i = 0; i < ts->tx_count; i++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%4d,", |
| ts->gainTable[i*ts->rx_count |
| + j]); |
| } |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n"); |
| } |
| } else if (sec->cmd_param[0] == 2) { |
| int mean; |
| /* for stim pad fixture 2 */ |
| mode.type = TYPE_NORM2_DATA; |
| mode.spec_check = SPEC_NO_CHECK; |
| |
| ret = sec_ts_read_frame_stdev(ts, sec, mode.type, mode.min, |
| mode.max, &mode.spec_check, only_average); |
| if (ret < 0) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto SetCmdResult; |
| } |
| |
| mean = sec_ts_get_postcal_mean(ts); |
| ts->fs_postcal_mean = mean; |
| |
| input_info(true, &ts->client->dev, |
| "%s : FS mean = %d\n", __func__, mean); |
| |
| if ((mean > fs_mean_target_h) || (mean < fs_mean_target_l)) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "NG %d %d\n%d\n", |
| ts->rx_count, ts->tx_count, |
| ts->fs_postcal_mean); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "OK %d %d\n%d\n", |
| ts->rx_count, ts->tx_count, |
| ts->fs_postcal_mean); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| for (i = 0; i < ts->tx_count * ts->rx_count; i++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "%4d,", |
| ts->pFrame[i]); |
| |
| if (i % ts->tx_count == ts->tx_count - 1) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } else { //(sec->cmd_param[0] == 3) |
| /* get fs_uniformity */ |
| |
| diff_table = kzalloc(ts->tx_count * ts->rx_count * 2, |
| GFP_KERNEL); |
| |
| if ((diff_table == NULL) || (ts->fs_postcal_mean == 0)) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to alloc diffTable, postcal mean = %d\n", |
| __func__, ts->fs_postcal_mean); |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "NG %d %d", |
| ts->rx_count, ts->tx_count); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto SetCmdResult; |
| } |
| |
| ret = sec_ts_get_postcal_uniformity(ts, diff_table); |
| |
| if (ret == 0) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "OK %d %d\n", |
| ts->rx_count, ts->tx_count); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } else { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "NG %d %d\n", |
| ts->rx_count, ts->tx_count); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } |
| |
| for (i = 0; i < ts->tx_count * ts->rx_count; i++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "%4d,", |
| diff_table[i]); |
| |
| if (i % ts->tx_count == ts->tx_count - 1) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } |
| |
| SetCmdResult: |
| |
| sec_cmd_set_cmd_result(sec, buff, buff_len); |
| |
| kfree(diff_table); |
| kfree(buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_fs_cal_post_press(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int ret = 0; |
| u8 on[1] = {STATE_MANAGE_ON}; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| goto ErrorPowerOff; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_TOUCH_ENGINE_MODE, on, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to enable touch engine\n", __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_DF, on, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: fail to enable df\n", |
| __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_BASELINE_ADAPT, on, |
| 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to enable baselineAdapt\n", __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_GAIN_LIMIT, on, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to enable gain limit\n", __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| ret = sec_ts_release_tmode(ts); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: fail to release tmode\n", |
| __func__); |
| goto ErrorSendingCmd; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| ErrorSendingCmd: |
| ErrorPowerOff: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| /* enable_fs_cal_table : enable or disable fs cal table |
| * cmd_param : 0 to disable, 1 to enable |
| * touch mode and state should be fixed before enable or disable |
| */ |
| static void enable_fs_cal_table(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| u8 tPara; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: fail to fix tmode\n", |
| __func__); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| tPara = sec->cmd_param[0]; |
| |
| input_info(true, &ts->client->dev, "%s: fs cal table %s\n", |
| __func__, ((tPara == 0) ? "disable" : "enable")); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_NORM_TABLE, |
| &tPara, 1); |
| |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed\n", __func__); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| } else { |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, "OK", 2); |
| } |
| |
| ret = sec_ts_release_tmode(ts); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, "%s: fail to release tmode\n", |
| __func__); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void enable_coordinate_report(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int ret = 0; |
| u8 tPara; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| sec_cmd_set_cmd_result(sec, "TSP turned off", 14); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| tPara = sec->cmd_param[0]; |
| |
| input_info(true, &ts->client->dev, "%s: coordinate report %s\n", |
| __func__, ((tPara == 0) ? "disable" : "enable")); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_TOUCH_ENGINE_MODE, |
| &tPara, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed\n", __func__); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| } else { |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, "OK", 2); |
| } |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void enable_gain_limit(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int ret = 0; |
| u8 tPara; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| sec_cmd_set_cmd_result(sec, "TSP turned off", 14); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| tPara = sec->cmd_param[0]; |
| |
| input_info(true, &ts->client->dev, "%s: gain limit %s\n", |
| __func__, ((tPara == 0) ? "disable" : "enable")); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DISABLE_GAIN_LIMIT, &tPara, |
| 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed\n", __func__); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| } else { |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, "OK", 2); |
| } |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_trx_short_test(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int rc; |
| char para = TO_TOUCH_MODE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: Touch is stopped!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| disable_irq(ts->client->irq); |
| |
| rc = execute_selftest(ts, TEST_SHORT | TEST_OPEN | TEST_NODE_VARIANCE); |
| if (rc > 0) { |
| ts->sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE, ¶, 1); |
| enable_irq(ts->client->irq); |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| ts->sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE, ¶, 1); |
| enable_irq(ts->client->irq); |
| |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| |
| int sec_ts_execute_force_calibration(struct sec_ts_data *ts, int cal_mode) |
| { |
| int rc = -1; |
| u8 cmd; |
| |
| input_info(true, &ts->client->dev, "%s: %d\n", __func__, cal_mode); |
| |
| if (cal_mode == OFFSET_CAL_SEC) |
| cmd = SEC_TS_CMD_FACTORY_PANELCALIBRATION; |
| else if (cal_mode == AMBIENT_CAL) |
| cmd = SEC_TS_CMD_CALIBRATION_AMBIENT; |
| #ifdef USE_PRESSURE_SENSOR |
| else if (cal_mode == PRESSURE_CAL) |
| cmd = SEC_TS_CMD_CALIBRATION_PRESSURE; |
| #endif |
| else |
| return rc; |
| |
| if (ts->sec_ts_write(ts, cmd, NULL, 0) < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Write Cal commend failed!\n", __func__); |
| return rc; |
| } |
| |
| sec_ts_delay(4000); |
| |
| rc = sec_ts_wait_for_ready(ts, SEC_TS_VENDOR_ACK_OFFSET_CAL_DONE); |
| |
| return rc; |
| } |
| |
| static void run_force_calibration(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int rc; |
| #ifdef PAT_CONTROL |
| u8 img_ver[4]; |
| #endif |
| struct sec_ts_test_mode mode; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: Touch is stopped!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| sec_ts_read_calibration_report(ts); |
| |
| if (ts->touch_count > 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG_FINGER_ON"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_force_cal; |
| } |
| |
| disable_irq(ts->client->irq); |
| |
| rc = sec_ts_execute_force_calibration(ts, OFFSET_CAL_SEC); |
| if (rc < 0) { |
| snprintf(buff, sizeof(buff), "%s", "FAIL"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| #ifdef USE_PRESSURE_SENSOR |
| rc = sec_ts_execute_force_calibration(ts, PRESSURE_CAL); |
| if (rc < 0) |
| input_err(true, &ts->client->dev, |
| "%s: fail to write PRESSURE CAL!\n", __func__); |
| #endif |
| |
| if (ts->plat_data->mis_cal_check && |
| sec_ts_run_cal_check(ts)) { |
| memset(&mode, 0x00, |
| sizeof(struct sec_ts_test_mode)); |
| mode.type = TYPE_AMBIENT_DATA; |
| mode.allnode = TEST_MODE_ALL_NODE; |
| |
| sec_ts_read_raw_data(ts, NULL, &mode); |
| snprintf(buff, sizeof(buff), "%s", "MIS CAL"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| enable_irq(ts->client->irq); |
| goto out_force_cal; |
| } |
| |
| #ifdef PAT_CONTROL |
| ts->cal_count = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_CAL_COUNT); |
| |
| if (ts->external_factory == true) { |
| /* for external factory mode */ |
| if (ts->cal_count == PAT_MAX_EXT) |
| ts->cal_count = PAT_MAX_EXT; |
| else if (ts->cal_count >= PAT_EXT_FACT && |
| ts->cal_count < PAT_MAX_EXT) |
| ts->cal_count++; |
| else |
| ts->cal_count = PAT_EXT_FACT; |
| |
| /* not to enter external factory mode without setting |
| * everytime |
| **/ |
| ts->external_factory = false; |
| } else { |
| /* change from (virtual pat or vpat by external fatory) |
| * to real pat by forced calibarion by LCIA |
| **/ |
| if (ts->cal_count >= PAT_MAGIC_NUMBER) |
| ts->cal_count = 1; |
| else if (ts->cal_count == PAT_MAX_LCIA) |
| ts->cal_count = PAT_MAX_LCIA; |
| else |
| ts->cal_count++; |
| } |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| value is 1 - 1 = 0) |
| * buff[2] : write data |
| **/ |
| buff[0] = SEC_TS_NVM_OFFSET_CAL_COUNT; |
| buff[1] = 0; |
| buff[2] = ts->cal_count; |
| input_info(true, &ts->client->dev, |
| "%s: write to nvm cal_count(%2X)\n", |
| __func__, buff[2]); |
| |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 3); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", |
| __func__, rc); |
| } |
| |
| sec_ts_delay(20); |
| |
| ts->cal_count = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_CAL_COUNT); |
| |
| rc = ts->sec_ts_read(ts, SEC_TS_READ_IMG_VERSION, img_ver, 4); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Image version read error\n", __func__); |
| } else { |
| memset(buff, 0x00, SEC_CMD_STR_LEN); |
| buff[0] = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_TUNE_VERSION); |
| if (buff[0] == 0xFF) { |
| set_tsp_nvm_data_clear(ts, |
| SEC_TS_NVM_OFFSET_TUNE_VERSION); |
| set_tsp_nvm_data_clear(ts, |
| SEC_TS_NVM_OFFSET_TUNE_VERSION + 1); |
| } |
| |
| ts->tune_fix_ver = (img_ver[2]<<8 | img_ver[3]); |
| buff[0] = SEC_TS_NVM_OFFSET_TUNE_VERSION; |
| buff[1] = 1;// 2bytes |
| buff[2] = img_ver[2]; |
| buff[3] = img_ver[3]; |
| input_info(true, &ts->client->dev, |
| "%s: write tune_ver to nvm (%2X %2X)\n", |
| __func__, buff[2], buff[3]); |
| |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, buff, 4); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", |
| __func__, rc); |
| } |
| sec_ts_delay(20); |
| |
| buff[0] = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_TUNE_VERSION); |
| buff[1] = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_TUNE_VERSION + 1); |
| ts->tune_fix_ver = buff[0]<<8 | buff[1]; |
| input_info(true, &ts->client->dev, |
| "%s: cal_count [%2X] tune_fix_ver [%04X]\n", |
| __func__, ts->cal_count, ts->tune_fix_ver); |
| } |
| #endif |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| enable_irq(ts->client->irq); |
| |
| out_force_cal: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_force_calibration(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int buff_len = sizeof(buff); |
| int written = 0; |
| int rc; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| written += scnprintf(buff + written, buff_len - written, |
| "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| rc = sec_ts_read_calibration_report(ts); |
| if (rc < 0) { |
| written += scnprintf(buff + written, buff_len - written, |
| "%s\n", "FAIL"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else if (rc == SEC_TS_STATUS_CALIBRATION_SDC) { |
| written += scnprintf(buff + written, buff_len - written, |
| "%s\n", "OK(MODULE)"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } else if (rc == SEC_TS_STATUS_CALIBRATION_SEC) { |
| written += scnprintf(buff + written, buff_len - written, |
| "%s\n", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } else { |
| written += scnprintf(buff + written, buff_len - written, |
| "%s\n", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } |
| |
| written += scnprintf(buff + written, buff_len - written, |
| "%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", |
| ts->cali_report[0], ts->cali_report[1], ts->cali_report[2], |
| ts->cali_report[3], ts->cali_report[4], ts->cali_report[5], |
| ts->cali_report[6], ts->cali_report[7]); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| #ifdef USE_PRESSURE_SENSOR |
| static void run_force_pressure_calibration(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int rc; |
| char data[3] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if (ts->touch_count > 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG_FINGER_ON"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_force_pressure_cal; |
| } |
| |
| disable_irq(ts->client->irq); |
| |
| rc = sec_ts_execute_force_calibration(ts, PRESSURE_CAL); |
| if (rc < 0) { |
| snprintf(buff, sizeof(buff), "%s", "FAIL"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| ts->pressure_cal_base = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_PRESSURE_BASE_CAL_COUNT); |
| if (ts->pressure_cal_base == 0xFF) |
| ts->pressure_cal_base = 0; |
| if (ts->pressure_cal_base > 0xFD) |
| ts->pressure_cal_base = 0xFD; |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * data[0] : offset from user NVM storage |
| * data[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * data[2] : write data |
| **/ |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_BASE_CAL_COUNT; |
| data[1] = 0; |
| data[2] = ts->pressure_cal_base + 1; |
| |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 3); |
| if (rc < 0) |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, rc); |
| |
| ts->pressure_cal_base = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_PRESSURE_BASE_CAL_COUNT); |
| |
| input_info(true, &ts->client->dev, "%s: count:%d\n", |
| __func__, ts->pressure_cal_base); |
| |
| enable_irq(ts->client->irq); |
| |
| out_force_pressure_cal: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_pressure_test_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int ret; |
| unsigned char data = TYPE_INVALID_DATA; |
| unsigned char enable = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if (sec->cmd_param[0] == 1) { |
| enable = 0x1; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_TEMPERATURE_COMP_MODE, |
| &enable, 1); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_test_mode; |
| } |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_test_mode; |
| } |
| |
| } else { |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SELECT_PRESSURE_TYPE, |
| &data, 1); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_test_mode; |
| } |
| |
| ret = sec_ts_release_tmode(ts); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_test_mode; |
| } |
| |
| enable = 0x0; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_TEMPERATURE_COMP_MODE, |
| &enable, 1); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out_test_mode; |
| } |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| out_test_mode: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static int read_pressure_data(struct sec_ts_data *ts, u8 type, short *value) |
| { |
| unsigned char data[6] = { 0 }; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) |
| return -ENODEV; |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_SELECT_PRESSURE_TYPE, data, 1); |
| if (ret < 0) |
| return -EIO; |
| |
| if (data[0] != type) { |
| input_info(true, &ts->client->dev, "%s: type change to %02X\n", |
| __func__, type); |
| |
| data[1] = type; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SELECT_PRESSURE_TYPE, |
| &data[1], 1); |
| if (ret < 0) |
| return -EIO; |
| |
| sec_ts_delay(30); |
| } |
| |
| memset(data, 0x00, 6); |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_READ_PRESSURE_DATA, data, 6); |
| if (ret < 0) |
| return -EIO; |
| |
| pressure[0] = (data[0] << 8 | data[1]); |
| pressure[1] = (data[2] << 8 | data[3]); |
| pressure[2] = (data[4] << 8 | data[5]); |
| |
| input_info(true, &ts->client->dev, |
| "%s: Left: %d, Center: %d, Rignt: %d\n", |
| __func__, pressure[2], pressure[1], pressure[0]); |
| |
| memcpy(value, pressure, 3 * 2); |
| |
| return ret; |
| } |
| |
| static void run_pressure_filtered_strength_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| ret = read_pressure_data(ts, TYPE_SIGNAL_DATA, pressure); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "WRITE FAILED"); |
| goto error_read_str; |
| } |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d", |
| pressure[2], pressure[1], pressure[0]); |
| |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| error_read_str: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_pressure_strength_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| ret = read_pressure_data(ts, TYPE_REMV_AMB_DATA, pressure); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "WRITE FAILED"); |
| goto error_read_str; |
| } |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d", |
| pressure[2], pressure[1], pressure[0]); |
| |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| error_read_str: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_pressure_rawdata_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| ret = read_pressure_data(ts, TYPE_RAW_DATA, pressure); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "WRITE FAILED"); |
| goto error_read_rawdata; |
| } |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d", |
| pressure[2], pressure[1], pressure[0]); |
| |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| error_read_rawdata: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void run_pressure_offset_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| ret = read_pressure_data(ts, TYPE_OFFSET_DATA_SEC, pressure); |
| if (ret < 0) { |
| snprintf(buff, sizeof(buff), "%s", "WRITE FAILED"); |
| goto error_read_str; |
| } |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d", |
| pressure[2], pressure[1], pressure[0]); |
| |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| error_read_str: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_pressure_strength(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| u8 data[8] = { 0 }; |
| u8 cal_data[18] = { 0 }; |
| int index; |
| int ret; |
| short pressure[3] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) |
| goto err_cmd_param_str; |
| |
| index = sec->cmd_param[0] - 1; |
| |
| /* RIGHT */ |
| cal_data[0] = (sec->cmd_param[3] >> 8); |
| cal_data[1] = (sec->cmd_param[3] & 0xFF); |
| /* CENTER */ |
| cal_data[8] = (sec->cmd_param[2] >> 8); |
| cal_data[9] = (sec->cmd_param[2] & 0xFF); |
| /* LEFT */ |
| cal_data[16] = (sec->cmd_param[1] >> 8); |
| cal_data[17] = (sec->cmd_param[1] & 0xFF); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GET_PRESSURE, cal_data, 18); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed. ret: %d\n", __func__, ret); |
| goto err_comm_str; |
| } |
| |
| sec_ts_delay(30); |
| |
| memset(cal_data, 0x00, 18); |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_SET_GET_PRESSURE, cal_data, 18); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed. ret: %d\n", __func__, ret); |
| goto err_comm_str; |
| } |
| |
| pressure[0] = ((cal_data[16] << 8) | cal_data[17]); |
| pressure[1] = ((cal_data[8] << 8) | cal_data[9]); |
| pressure[2] = ((cal_data[0] << 8) | cal_data[1]); |
| |
| input_info(true, &ts->client->dev, "%s: [%d] : %d, %d, %d\n", |
| __func__, pressure[0], pressure[1], pressure[2]); |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : [n] length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * buff[2] ... [n] : write data ... |
| **/ |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_STRENGTH + |
| (index * SEC_TS_NVM_SIZE_PRESSURE_BLOCK); |
| data[1] = SEC_TS_NVM_SIZE_PRESSURE_BLOCK - 1; |
| /* RIGHT */ |
| data[2] = (sec->cmd_param[3] >> 8); |
| data[3] = (sec->cmd_param[3] & 0xFF); |
| /* CENTER */ |
| data[4] = (sec->cmd_param[2] >> 8); |
| data[5] = (sec->cmd_param[2] & 0xFF); |
| /*LEFT */ |
| data[6] = (sec->cmd_param[1] >> 8); |
| data[7] = (sec->cmd_param[1] & 0xFF); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 8); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| goto err_comm_str; |
| } |
| |
| sec_ts_delay(20); |
| |
| input_info(true, &ts->client->dev, "%s: [%d] : %d, %d, %d\n", |
| __func__, index, |
| (data[6] << 8) + data[7], |
| (data[4] << 8) + data[5], |
| (data[0] << 8) + data[1]); |
| |
| memset(data, 0x00, 8); |
| |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_INDEX; |
| data[1] = 0; |
| data[2] = (u8)(index & 0xFF); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 3); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| goto err_comm_str; |
| } |
| |
| sec_ts_delay(20); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| ts->pressure_cal_delta = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT); |
| if (ts->pressure_cal_delta == 0xFF) |
| ts->pressure_cal_delta = 0; |
| |
| if (ts->pressure_cal_delta > 0xFD) |
| ts->pressure_cal_delta = 0xFD; |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * data[0] : offset from user NVM storage |
| * data[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * data[2] : write data |
| **/ |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT; |
| data[1] = 0; |
| data[2] = ts->pressure_cal_delta + 1; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 3); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| |
| ts->pressure_cal_delta = get_tsp_nvm_data(ts, |
| SEC_TS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT); |
| |
| input_info(true, &ts->client->dev, |
| "%s: count:%d\n", __func__, ts->pressure_cal_delta); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_cmd_param_str: |
| input_info(true, &ts->client->dev, "%s: parameter error: %u\n", |
| __func__, sec->cmd_param[0]); |
| err_comm_str: |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_pressure_rawdata(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| u8 data[8] = { 0 }; |
| int index; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) |
| goto err_cmd_param_raw; |
| |
| index = sec->cmd_param[0] - 1; |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : [n] length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * buff[2] ... [n] : write data ... |
| **/ |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_RAWDATA + |
| (index * SEC_TS_NVM_SIZE_PRESSURE_BLOCK); |
| data[1] = SEC_TS_NVM_SIZE_PRESSURE_BLOCK - 1; |
| data[2] = (sec->cmd_param[3] >> 8); |
| data[3] = (sec->cmd_param[3] & 0xFF); |
| data[4] = (sec->cmd_param[2] >> 8); |
| data[5] = (sec->cmd_param[2] & 0xFF); |
| data[6] = (sec->cmd_param[1] >> 8); |
| data[7] = (sec->cmd_param[1] & 0xFF); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 8); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| goto err_comm_raw; |
| } |
| sec_ts_delay(20); |
| |
| memset(data, 0x00, 8); |
| |
| ret = get_tsp_nvm_data_by_size(ts, SEC_TS_NVM_OFFSET_PRESSURE_RAWDATA + |
| (index * SEC_TS_NVM_SIZE_PRESSURE_BLOCK), |
| SEC_TS_NVM_SIZE_PRESSURE_BLOCK, data); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm read failed. ret: %d\n", __func__, ret); |
| goto err_comm_raw; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| input_info(true, &ts->client->dev, "%s: [%d] : %d, %d, %d\n", |
| __func__, index, |
| (data[4] << 8) + data[5], |
| (data[2] << 8) + data[3], |
| (data[1] << 8) + data[0]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_cmd_param_raw: |
| input_info(true, &ts->client->dev, "%s: parameter error: %u\n", |
| __func__, sec->cmd_param[0]); |
| err_comm_raw: |
| |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_pressure_data_index(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| u8 data[8] = { 0 }; |
| u8 cal_data[18] = { 0 }; |
| int index; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] > 4)) |
| goto err_set_cmd_param_index; |
| |
| if (sec->cmd_param[0] == 0) { |
| input_info(true, &ts->client->dev, |
| "%s: clear calibration result\n", __func__); |
| /* clear pressure calibrated data */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GET_PRESSURE, |
| cal_data, 18); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed. ret: %d\n", |
| __func__, ret); |
| goto err_set_comm_index; |
| } |
| |
| sec_ts_delay(30); |
| |
| goto clear_index; |
| } |
| |
| index = sec->cmd_param[0] - 1; |
| |
| ret = get_tsp_nvm_data_by_size(ts, SEC_TS_NVM_OFFSET_PRESSURE_STRENGTH, |
| 24, data); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm read failed. ret: %d\n", __func__, ret); |
| goto err_set_comm_index; |
| } |
| |
| cal_data[16] = data[6 * index + 4]; |
| cal_data[17] = data[6 * index + 5]; /* LEFT */ |
| |
| cal_data[8] = data[6 * index + 2]; |
| cal_data[9] = data[6 * index + 3]; /* CENTER */ |
| |
| cal_data[0] = data[6 * index + 0]; |
| cal_data[1] = data[6 * index + 1]; /* RIGHT */ |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GET_PRESSURE, cal_data, 18); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed. ret: %d\n", __func__, ret); |
| goto err_set_comm_index; |
| } |
| |
| sec_ts_delay(30); |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * buff[2] : write data |
| **/ |
| memset(data, 0x00, 8); |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_INDEX; |
| data[1] = 0; |
| data[2] = (u8)(index & 0xFF); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 3); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| goto err_set_comm_index; |
| } |
| |
| sec_ts_delay(20); |
| |
| clear_index: |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_set_cmd_param_index: |
| input_info(true, &ts->client->dev, "%s: parameter error: %u\n", |
| __func__, sec->cmd_param[0]); |
| err_set_comm_index: |
| |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_pressure_strength(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int index; |
| u8 data[24] = { 0 }; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) |
| goto err_get_cmd_param_str; |
| |
| index = sec->cmd_param[0] - 1; |
| |
| ret = get_tsp_nvm_data_by_size(ts, SEC_TS_NVM_OFFSET_PRESSURE_STRENGTH, |
| 24, data); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm read failed. ret: %d\n", __func__, ret); |
| goto err_get_comm_str; |
| } |
| |
| pressure[0] = ((data[6 * index + 4] << 8) + data[6 * index + 5]); |
| pressure[1] = ((data[6 * index + 2] << 8) + data[6 * index + 3]); |
| pressure[2] = ((data[6 * index + 0] << 8) + data[6 * index + 1]); |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d", |
| pressure[0], pressure[1], pressure[2]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| input_info(true, &ts->client->dev, "%s: [%d] : %d, %d, %d\n", |
| __func__, index, pressure[0], pressure[1], pressure[2]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_get_comm_str: |
| input_info(true, &ts->client->dev, "%s: parameter error: %u\n", |
| __func__, sec->cmd_param[0]); |
| err_get_cmd_param_str: |
| |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_pressure_rawdata(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int index; |
| u8 data[24] = { 0 }; |
| short pressure[3] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) |
| goto err_get_cmd_param_raw; |
| |
| index = sec->cmd_param[0] - 1; |
| |
| ret = get_tsp_nvm_data_by_size(ts, SEC_TS_NVM_OFFSET_PRESSURE_RAWDATA, |
| 24, data); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm read failed. ret: %d\n", __func__, ret); |
| goto err_get_comm_raw; |
| } |
| |
| pressure[0] = ((data[6 * index + 4] << 8) + data[6 * index + 5]); |
| pressure[1] = ((data[6 * index + 2] << 8) + data[6 * index + 3]); |
| pressure[2] = ((data[6 * index + 0] << 8) + data[6 * index + 1]); |
| |
| snprintf(buff, sizeof(buff), "%d,%d,%d", |
| pressure[0], pressure[1], pressure[2]); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| input_info(true, &ts->client->dev, "%s: [%d] : %d, %d, %d\n", |
| __func__, index, pressure[0], pressure[1], pressure[2]); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| err_get_cmd_param_raw: |
| input_info(true, &ts->client->dev, "%s: parameter error: %u\n", |
| __func__, sec->cmd_param[0]); |
| err_get_comm_raw: |
| |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_pressure_data_index(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int index = 0; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| index = get_tsp_nvm_data(ts, SEC_TS_NVM_OFFSET_PRESSURE_INDEX); |
| if (index < 0) { |
| goto err_get_index; |
| } else { |
| if (index == 0xFF) |
| snprintf(buff, sizeof(buff), "%d", 0); |
| else |
| snprintf(buff, sizeof(buff), "%d", index + 1); |
| } |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| input_info(true, &ts->client->dev, "%s: %d\n", |
| __func__, index); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_get_index: |
| |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| static void set_pressure_strength_clear(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| u8 *data; |
| u8 cal_data[18] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| /* clear pressure calibrated data */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_GET_PRESSURE, cal_data, 18); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: cmd write failed. ret: %d\n", __func__, ret); |
| goto err_comm_str; |
| } |
| |
| sec_ts_delay(30); |
| |
| /* Use TSP NV area : in this model, use only one byte |
| * buff[0] : offset from user NVM storage |
| * buff[1] : length of stroed data - 1 (ex. using 1byte, |
| * value is 1 - 1 = 0) |
| * buff[2] : write data |
| **/ |
| |
| /* strength 6 * 4, rawdata 6 * 4, buff[0], buff[1] */ |
| data = kzalloc(50, GFP_KERNEL); |
| if (!data) { |
| input_err(true, &ts->client->dev, |
| "%s failed to allocate memory. ret: %d\n", |
| __func__, ret); |
| goto err_comm_str; |
| } |
| |
| data[0] = SEC_TS_NVM_OFFSET_PRESSURE_INDEX; |
| data[1] = (SEC_TS_NVM_SIZE_PRESSURE_BLOCK * 8) - 1; |
| |
| /* remove calicated strength, rawdata in NVM */ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_NVM, data, 50); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: nvm write failed. ret: %d\n", __func__, ret); |
| goto err_mem_str; |
| } |
| |
| sec_ts_delay(20); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| |
| kfree(data); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_mem_str: |
| kfree(data); |
| err_comm_str: |
| snprintf(buff, sizeof(buff), "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_pressure_threshold(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| |
| sec_cmd_set_default_result(sec); |
| |
| snprintf(buff, sizeof(buff), "300"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| /* low level is more sensitivity, except level-0(value 0) */ |
| static void set_pressure_user_level(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| int ret; |
| char addr[3] = { 0 }; |
| char data[2] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 5)) |
| goto out_set_user_level; |
| |
| /* |
| * byte[0]: m_customlib_ifpacket_addr[7:0] |
| * byte[1]: m_customlib_ifpacket_addr[15:8] |
| * byte[n] : user data (max 32 bytes) |
| */ |
| addr[0] = SEC_TS_CMD_CUSTOMLIB_OFFSET_PRESSURE_LEVEL; |
| addr[1] = 0x00; |
| addr[2] = sec->cmd_param[0]; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_WRITE_PARAM, addr, 3); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_NOTIFY_PACKET, NULL, 0); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, addr, 2); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, data, 1); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| input_info(true, &ts->client->dev, "%s: set user level: %d\n", |
| __func__, data[0]); |
| |
| ts->pressure_user_level = data[0]; |
| |
| addr[0] = SEC_TS_CMD_CUSTOMLIB_OFFSET_PRESSURE_THD_HIGH; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, addr, 2); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, data, 1); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| input_info(true, &ts->client->dev, "%s: HIGH THD: %d\n", |
| __func__, data[0]); |
| |
| addr[0] = SEC_TS_CMD_CUSTOMLIB_OFFSET_PRESSURE_THD_LOW; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, addr, 2); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, data, 1); |
| if (ret < 0) |
| goto out_set_user_level; |
| |
| input_info(true, &ts->client->dev, "%s: LOW THD: %d\n", |
| __func__, data[0]); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| out_set_user_level: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void get_pressure_user_level(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = {0}; |
| char addr[3] = { 0 }; |
| char data[2] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| snprintf(buff, sizeof(buff), "%d", ts->pressure_user_level); |
| |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| addr[0] = SEC_TS_CMD_CUSTOMLIB_OFFSET_PRESSURE_LEVEL; |
| addr[1] = 0x00; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, addr, 2); |
| if (ret < 0) |
| goto out_get_user_level; |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_CUSTOMLIB_READ_PARAM, data, 1); |
| if (ret < 0) |
| goto out_get_user_level; |
| |
| input_err(true, &ts->client->dev, "%s: set user level: %d\n", |
| __func__, data[0]); |
| ts->pressure_user_level = data[0]; |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| out_get_user_level: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| #endif |
| |
| static void set_lowpower_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| |
| /* set lowpower mode by spay, edge_swipe function. |
| * ts->lowpower_mode = sec->cmd_param[0]; |
| **/ |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| |
| sec_cmd_set_cmd_exit(sec); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_wirelesscharger_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int ret; |
| bool mode; |
| u8 w_data[1] = {0x00}; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) |
| goto OUT; |
| |
| if (sec->cmd_param[0] == 0) { |
| ts->charger_mode |= SEC_TS_BIT_CHARGER_MODE_NO; |
| mode = false; |
| } else { |
| ts->charger_mode &= (~SEC_TS_BIT_CHARGER_MODE_NO); |
| mode = true; |
| } |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: fail to enable w-charger status, POWER_STATUS=OFF\n", |
| __func__); |
| goto NG; |
| } |
| |
| if (sec->cmd_param[0] == 1) |
| ts->charger_mode = ts->charger_mode | |
| SEC_TS_BIT_CHARGER_MODE_WIRELESS_CHARGER; |
| else if (sec->cmd_param[0] == 3) |
| ts->charger_mode = ts->charger_mode | |
| SEC_TS_BIT_CHARGER_MODE_WIRELESS_BATTERY_PACK; |
| else if (mode == false) |
| ts->charger_mode = ts->charger_mode & |
| (~SEC_TS_BIT_CHARGER_MODE_WIRELESS_CHARGER) & |
| (~SEC_TS_BIT_CHARGER_MODE_WIRELESS_BATTERY_PACK); |
| |
| w_data[0] = ts->charger_mode; |
| ret = ts->sec_ts_write(ts, SET_TS_CMD_SET_CHARGER_MODE, w_data, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to send command 74\n", __func__); |
| goto NG; |
| } |
| |
| input_err(true, &ts->client->dev, "%s: %s, status =%x\n", |
| __func__, (mode) ? "wireless enable" : "wireless disable", |
| ts->charger_mode); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| input_err(true, &ts->client->dev, "%s: %s, status =%x\n", |
| __func__, (mode) ? "wireless enable" : "wireless disable", |
| ts->charger_mode); |
| |
| OUT: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void spay_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) |
| goto NG; |
| |
| if (sec->cmd_param[0]) { |
| if (ts->use_customlib) |
| ts->lowpower_mode |= SEC_TS_MODE_CUSTOMLIB_SPAY; |
| } else { |
| if (ts->use_customlib) |
| ts->lowpower_mode &= ~SEC_TS_MODE_CUSTOMLIB_SPAY; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: %02X\n", __func__, ts->lowpower_mode); |
| |
| #ifdef SEC_TS_SUPPORT_CUSTOMLIB |
| if (ts->use_customlib) |
| sec_ts_set_custom_library(ts); |
| #endif |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_aod_rect(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| u8 data[10] = {0x02, 0}; |
| int ret, i; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| input_info(true, &ts->client->dev, "%s: w:%d, h:%d, x:%d, y:%d\n", |
| __func__, sec->cmd_param[0], sec->cmd_param[1], |
| sec->cmd_param[2], sec->cmd_param[3]); |
| |
| for (i = 0; i < 4; i++) { |
| data[i * 2 + 2] = sec->cmd_param[i] & 0xFF; |
| data[i * 2 + 3] = (sec->cmd_param[i] >> 8) & 0xFF; |
| ts->rect_data[i] = sec->cmd_param[i]; |
| } |
| |
| if (ts->use_customlib) { |
| disable_irq(ts->client->irq); |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_WRITE_PARAM, |
| &data[0], 10); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to write offset\n", __func__); |
| goto NG; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_CUSTOMLIB_NOTIFY_PACKET, |
| NULL, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to send notify\n", __func__); |
| goto NG; |
| } |
| enable_irq(ts->client->irq); |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| NG: |
| enable_irq(ts->client->irq); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| |
| static void get_aod_rect(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| u8 data[8] = {0x02, 0}; |
| u16 rect_data[4] = {0, }; |
| int ret, i; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->use_customlib) { |
| disable_irq(ts->client->irq); |
| ret = ts->sec_ts_read_customlib(ts, data, 8); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to read rect\n", __func__); |
| goto NG; |
| } |
| enable_irq(ts->client->irq); |
| } |
| |
| for (i = 0; i < 4; i++) |
| rect_data[i] = (data[i * 2 + 1] & 0xFF) << 8 | |
| (data[i * 2] & 0xFF); |
| |
| input_info(true, &ts->client->dev, "%s: w:%d, h:%d, x:%d, y:%d\n", |
| __func__, |
| rect_data[0], rect_data[1], rect_data[2], rect_data[3]); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| NG: |
| enable_irq(ts->client->irq); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void aod_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) |
| goto NG; |
| |
| if (sec->cmd_param[0]) { |
| if (ts->use_customlib) |
| ts->lowpower_mode |= SEC_TS_MODE_CUSTOMLIB_AOD; |
| } else { |
| if (ts->use_customlib) |
| ts->lowpower_mode &= ~SEC_TS_MODE_CUSTOMLIB_AOD; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: %02X\n", __func__, ts->lowpower_mode); |
| |
| #ifdef SEC_TS_SUPPORT_CUSTOMLIB |
| if (ts->use_customlib) |
| sec_ts_set_custom_library(ts); |
| #endif |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| /* |
| * flag 1 : set edge handler |
| * 2 : set (portrait, normal) edge zone data |
| * 4 : set (portrait, normal) dead zone data |
| * 8 : set landscape mode data |
| * 16 : mode clear |
| * data |
| * 0x30, FFF (y start), FFF (y end), FF(direction) |
| * 0x31, FFFF (edge zone) |
| * 0x32, FF (up x), FF (down x), FFFF (y) |
| * 0x33, FF (mode), FFF (edge), FFF (dead zone) |
| * case |
| * edge handler set : 0x30.... |
| * booting time : 0x30... + 0x31... |
| * normal mode : 0x32... (+0x31...) |
| * landscape mode : 0x33... |
| * landscape -> normal (if same with old data) : 0x33, 0 |
| * landscape -> normal (etc) : 0x32.... + 0x33, 0 |
| */ |
| |
| void set_grip_data_to_ic(struct sec_ts_data *ts, u8 flag) |
| { |
| u8 data[8] = { 0 }; |
| |
| input_info(true, &ts->client->dev, "%s: flag: %02X (clr,lan,nor,edg,han)\n", |
| __func__, flag); |
| |
| if (flag & G_SET_EDGE_HANDLER) { |
| if (ts->grip_edgehandler_direction == 0) { |
| data[0] = 0x0; |
| data[1] = 0x0; |
| data[2] = 0x0; |
| data[3] = 0x0; |
| } else { |
| data[0] = (ts->grip_edgehandler_start_y >> 4) & 0xFF; |
| data[1] = (ts->grip_edgehandler_start_y << 4 & 0xF0) | |
| ((ts->grip_edgehandler_end_y >> 8) & 0xF); |
| data[2] = ts->grip_edgehandler_end_y & 0xFF; |
| data[3] = ts->grip_edgehandler_direction & 0x3; |
| } |
| ts->sec_ts_write(ts, SEC_TS_CMD_EDGE_HANDLER, data, 4); |
| input_info(true, &ts->client->dev, "%s: 0x%02X %02X,%02X,%02X,%02X\n", |
| __func__, SEC_TS_CMD_EDGE_HANDLER, |
| data[0], data[1], data[2], data[3]); |
| } |
| |
| if (flag & G_SET_EDGE_ZONE) { |
| data[0] = (ts->grip_edge_range >> 8) & 0xFF; |
| data[1] = ts->grip_edge_range & 0xFF; |
| ts->sec_ts_write(ts, SEC_TS_CMD_EDGE_AREA, data, 2); |
| input_info(true, &ts->client->dev, "%s: 0x%02X %02X,%02X\n", |
| __func__, SEC_TS_CMD_EDGE_AREA, data[0], data[1]); |
| } |
| |
| if (flag & G_SET_NORMAL_MODE) { |
| data[0] = ts->grip_deadzone_up_x & 0xFF; |
| data[1] = ts->grip_deadzone_dn_x & 0xFF; |
| data[2] = (ts->grip_deadzone_y >> 8) & 0xFF; |
| data[3] = ts->grip_deadzone_y & 0xFF; |
| ts->sec_ts_write(ts, SEC_TS_CMD_DEAD_ZONE, data, 4); |
| input_info(true, &ts->client->dev, "%s: 0x%02X %02X,%02X,%02X,%02X\n", |
| __func__, SEC_TS_CMD_DEAD_ZONE, |
| data[0], data[1], data[2], data[3]); |
| } |
| |
| if (flag & G_SET_LANDSCAPE_MODE) { |
| data[0] = ts->grip_landscape_mode & 0x1; |
| data[1] = (ts->grip_landscape_edge >> 4) & 0xFF; |
| data[2] = (ts->grip_landscape_edge << 4 & 0xF0) | |
| ((ts->grip_landscape_deadzone >> 8) & 0xF); |
| data[3] = ts->grip_landscape_deadzone & 0xFF; |
| ts->sec_ts_write(ts, SEC_TS_CMD_LANDSCAPE_MODE, data, 4); |
| input_info(true, &ts->client->dev, "%s: 0x%02X %02X,%02X,%02X,%02X\n", |
| __func__, SEC_TS_CMD_LANDSCAPE_MODE, |
| data[0], data[1], data[2], data[3]); |
| } |
| |
| if (flag & G_CLR_LANDSCAPE_MODE) { |
| data[0] = ts->grip_landscape_mode; |
| ts->sec_ts_write(ts, SEC_TS_CMD_LANDSCAPE_MODE, data, 1); |
| input_info(true, &ts->client->dev, "%s: 0x%02X %02X\n", |
| __func__, SEC_TS_CMD_LANDSCAPE_MODE, data[0]); |
| } |
| } |
| |
| /* |
| * index 0 : set edge handler |
| * 1 : portrait (normal) mode |
| * 2 : landscape mode |
| * |
| * data |
| * 0, X (direction), X (y start), X (y end) |
| * direction : 0 (off), 1 (left), 2 (right) |
| * ex) echo set_grip_data,0,2,600,900 > cmd |
| * |
| * 1, X (edge zone), X (dead zone up x), X (dead zone down x), X (dead zone y) |
| * ex) echo set_grip_data,1,200,10,50,1500 > cmd |
| * |
| * 2, 1 (landscape mode), X (edge zone), X (dead zone) |
| * ex) echo set_grip_data,2,1,200,100 > cmd |
| * |
| *2, 0 (portrait mode) |
| * ex) echo set_grip_data,2,0 > cmd |
| */ |
| |
| static void set_grip_data(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| /* u8 mode = G_NONE; */ |
| u8 tPara[2] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| memset(buff, 0, sizeof(buff)); |
| |
| mutex_lock(&ts->device_mutex); |
| |
| tPara[0] = sec->cmd_param[0] & 0xFF; |
| tPara[1] = (sec->cmd_param[0] >> 8) & 0xFF; |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_DEADZONE_RANGE, tPara, 2); |
| if (ret < 0) |
| goto err_grip_data; |
| /* |
| * if (sec->cmd_param[0] == 0) { // edge handler |
| * if (sec->cmd_param[1] == 0) { // clear |
| * ts->grip_edgehandler_direction = 0; |
| * } else if (sec->cmd_param[1] < 3) { |
| * ts->grip_edgehandler_direction = sec->cmd_param[1]; |
| * ts->grip_edgehandler_start_y = sec->cmd_param[2]; |
| * ts->grip_edgehandler_end_y = sec->cmd_param[3]; |
| * } else { |
| * input_err(true, &ts->client->dev, |
| * "%s: cmd1 is abnormal, %d (%d)\n", |
| * __func__, sec->cmd_param[1], __LINE__); |
| * goto err_grip_data; |
| * } |
| * |
| * mode = mode | G_SET_EDGE_HANDLER; |
| * set_grip_data_to_ic(ts, mode); |
| * |
| * } else if (sec->cmd_param[0] == 1) { // normal mode |
| * if (ts->grip_edge_range != sec->cmd_param[1]) |
| * mode = mode | G_SET_EDGE_ZONE; |
| * |
| * ts->grip_edge_range = sec->cmd_param[1]; |
| * ts->grip_deadzone_up_x = sec->cmd_param[2]; |
| * ts->grip_deadzone_dn_x = sec->cmd_param[3]; |
| * ts->grip_deadzone_y = sec->cmd_param[4]; |
| * mode = mode | G_SET_NORMAL_MODE; |
| * |
| * if (ts->grip_landscape_mode == 1) { |
| * ts->grip_landscape_mode = 0; |
| * mode = mode | G_CLR_LANDSCAPE_MODE; |
| * } |
| * set_grip_data_to_ic(ts, mode); |
| * } else if (sec->cmd_param[0] == 2) { // landscape mode |
| * if (sec->cmd_param[1] == 0) { // normal mode |
| * ts->grip_landscape_mode = 0; |
| * mode = mode | G_CLR_LANDSCAPE_MODE; |
| * } else if (sec->cmd_param[1] == 1) { |
| * ts->grip_landscape_mode = 1; |
| * ts->grip_landscape_edge = sec->cmd_param[2]; |
| * ts->grip_landscape_deadzone = sec->cmd_param[3]; |
| * mode = mode | G_SET_LANDSCAPE_MODE; |
| * } else { |
| * input_err(true, &ts->client->dev, |
| * "%s: cmd1 is abnormal, %d (%d)\n", |
| * __func__, sec->cmd_param[1], __LINE__); |
| * goto err_grip_data; |
| * } |
| * set_grip_data_to_ic(ts, mode); |
| * } else { |
| * input_err(true, &ts->client->dev, |
| * "%s: cmd0 is abnormal, %d", |
| * __func__, sec->cmd_param[0]); |
| * goto err_grip_data; |
| * } |
| **/ |
| |
| mutex_unlock(&ts->device_mutex); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| err_grip_data: |
| mutex_unlock(&ts->device_mutex); |
| |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| /* |
| * Set/Get Dex Mode 0xE7 |
| * 0: Disable dex mode |
| * 1: Full screen mode |
| * 2: Iris mode |
| */ |
| static void dex_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (!ts->plat_data->support_dex) { |
| input_err(true, &ts->client->dev, "%s: not support DeX mode\n", |
| __func__); |
| goto NG; |
| } |
| |
| if ((sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) && |
| (sec->cmd_param[1] < 0 || sec->cmd_param[1] > 1)) { |
| input_err(true, &ts->client->dev, "%s: not support param\n", |
| __func__); |
| goto NG; |
| } |
| |
| ts->dex_mode = sec->cmd_param[0]; |
| if (ts->dex_mode) { |
| input_err(true, &ts->client->dev, "%s: set DeX touch_pad mode%s\n", |
| __func__, sec->cmd_param[1] ? " & Iris mode" : ""); |
| ts->input_dev = ts->input_dev_pad; |
| if (sec->cmd_param[1]) { |
| /* Iris mode */ |
| ts->dex_mode = 0x02; |
| ts->dex_name = "[DeXI]"; |
| } else { |
| ts->dex_name = "[DeX]"; |
| } |
| } else { |
| input_err(true, &ts->client->dev, "%s: set touch mode\n", |
| __func__); |
| ts->input_dev = ts->input_dev_touch; |
| ts->dex_name = ""; |
| } |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: Touch is stopped!\n", |
| __func__); |
| goto NG; |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_DEX_MODE, &ts->dex_mode, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to set dex %smode\n", __func__, |
| sec->cmd_param[1] ? "iris " : ""); |
| goto NG; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| |
| NG: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void brush_enable(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| |
| ts->brush_mode = sec->cmd_param[0]; |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: Touch is stopped!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| goto out; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: set brush mode %s\n", __func__, |
| ts->brush_mode ? "enable" : "disable"); |
| |
| /* - 0: Disable Artcanvas min phi mode |
| * - 1: Enable Artcanvas min phi mode |
| **/ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_BRUSH_MODE, |
| &ts->brush_mode, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to set brush mode\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| out: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void force_touch_active(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| int active, ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec_cmd_set_cmd_exit(sec); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| active = sec->cmd_param[0]; |
| input_info(true, &ts->client->dev, |
| "%s: %s\n", __func__, active ? "enable" : "disable"); |
| if (active) |
| pm_stay_awake(&ts->client->dev); |
| else |
| pm_relax(&ts->client->dev); |
| |
| ret = sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_FORCE_ACTIVE, active); |
| if (ret == 0) { |
| sec_cmd_set_cmd_result(sec, "OK", 2); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } else { |
| input_info(true, &ts->client->dev, |
| "%s: failed! ret %d\n", __func__, ret); |
| sec_cmd_set_cmd_result(sec, "NG", 2); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } |
| sec_cmd_set_cmd_exit(sec); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_touchable_area(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) { |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| |
| ts->touchable_area = sec->cmd_param[0]; |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: Touch is stopped!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| goto out; |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: set 16:9 mode %s\n", __func__, |
| ts->touchable_area ? "enable" : "disable"); |
| |
| /* - 0: Disable 16:9 mode |
| * - 1: Enable 16:9 mode |
| **/ |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_TOUCHABLE_AREA, |
| &ts->touchable_area, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to set 16:9 mode\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| out: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_cmd_set_cmd_exit(sec); |
| |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void set_log_level(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| char tBuff[2] = { 0 }; |
| u8 w_data[1] = {0x00}; |
| int ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, |
| "%s: Touch is stopped!\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "TSP turned off"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| if ((sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) || |
| (sec->cmd_param[1] < 0 || sec->cmd_param[1] > 1) || |
| (sec->cmd_param[2] < 0 || sec->cmd_param[2] > 1) || |
| (sec->cmd_param[3] < 0 || sec->cmd_param[3] > 1) || |
| (sec->cmd_param[4] < 0 || sec->cmd_param[4] > 1) || |
| (sec->cmd_param[5] < 0 || sec->cmd_param[5] > 1) || |
| (sec->cmd_param[6] < 0 || sec->cmd_param[6] > 1) || |
| (sec->cmd_param[7] < 0 || sec->cmd_param[7] > 1)) { |
| input_err(true, &ts->client->dev, |
| "%s: para out of range\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "Para out of range"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| } |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_STATUS_EVENT_TYPE, tBuff, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Read Event type enable status fail\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "Read Stat Fail"); |
| goto err; |
| } |
| |
| input_info(true, &ts->client->dev, "%s: STATUS_EVENT enable = 0x%02X, 0x%02X\n", |
| __func__, tBuff[0], tBuff[1]); |
| |
| tBuff[0] = BIT_STATUS_EVENT_VENDOR_INFO(sec->cmd_param[6]); |
| tBuff[1] = BIT_STATUS_EVENT_ERR(sec->cmd_param[0]) | |
| BIT_STATUS_EVENT_INFO(sec->cmd_param[1]) | |
| BIT_STATUS_EVENT_USER_INPUT(sec->cmd_param[2]); |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_STATUS_EVENT_TYPE, tBuff, 2); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Write Event type enable status fail\n", __func__); |
| snprintf(buff, sizeof(buff), "%s", "Write Stat Fail"); |
| goto err; |
| } |
| |
| if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 1 && |
| sec->cmd_param[2] == 1 && sec->cmd_param[3] == 1 && |
| sec->cmd_param[4] == 1 && sec->cmd_param[5] == 1 && |
| sec->cmd_param[6] == 1 && sec->cmd_param[7] == 1) { |
| w_data[0] = 0x1; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_VENDOR_EVENT_LEVEL, |
| w_data, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Write Vendor Event Level fail\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "%s", "Write Stat Fail"); |
| goto err; |
| } |
| } else { |
| w_data[0] = 0x0; |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_VENDOR_EVENT_LEVEL, |
| w_data, 0); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Write Vendor Event Level fail\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "%s", "Write Stat Fail"); |
| goto err; |
| } |
| } |
| |
| input_info(true, &ts->client->dev, |
| "%s: ERROR : %d, INFO : %d, USER_INPUT : %d, INFO_CUSTOMLIB : %d, VENDOR_INFO : %d, VENDOR_EVENT_LEVEL : %d\n", |
| __func__, sec->cmd_param[0], sec->cmd_param[1], |
| sec->cmd_param[2], sec->cmd_param[5], |
| sec->cmd_param[6], w_data[0]); |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| return; |
| err: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void debug(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| |
| ts->temp = sec->cmd_param[0]; |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| } |
| |
| static void set_print_format(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| |
| ts->print_format = !!sec->cmd_param[0]; |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| } |
| |
| u8 sec_ts_run_cal_check(struct sec_ts_data *ts) |
| { |
| int rc = 0; |
| u8 mis_cal_data = 0xF0; |
| |
| if (ts->plat_data->mis_cal_check) { |
| rc = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (rc < 0) |
| input_err(true, &ts->client->dev, |
| "%s: failed#1 ret: %d\n", __func__, rc); |
| |
| rc = ts->sec_ts_write(ts, SEC_TS_CMD_MIS_CAL_CHECK, |
| NULL, 0); |
| if (rc < 0) |
| input_err(true, &ts->client->dev, |
| "%s: failed#2 ret: %d\n", __func__, rc); |
| sec_ts_delay(200); |
| |
| rc = ts->sec_ts_read(ts, SEC_TS_CMD_MIS_CAL_READ, |
| &mis_cal_data, 1); |
| if (rc < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed#3 ret: %d\n", __func__, rc); |
| mis_cal_data = 0xF3; |
| } else { |
| input_info(true, &ts->client->dev, |
| "%s: mis cal data : %d\n", |
| __func__, mis_cal_data); |
| } |
| |
| rc = sec_ts_release_tmode(ts); |
| if (rc < 0) |
| input_err(true, &ts->client->dev, |
| "%s: failed#4 ret: %d\n", __func__, rc); |
| } else { |
| input_info(true, &ts->client->dev, |
| "%s: not support!\n", __func__); |
| mis_cal_data = 0xF1; |
| } |
| |
| return mis_cal_data; |
| } |
| |
| static void run_cal_check(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| u8 ret; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| ret = sec_ts_run_cal_check(ts); |
| if (ret) |
| scnprintf(buff, sizeof(buff), "FAIL(%#x)\n", ret); |
| else |
| scnprintf(buff, sizeof(buff), "OK\n"); |
| |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| static void not_support_cmd(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| |
| sec_cmd_set_default_result(sec); |
| snprintf(buff, sizeof(buff), "%s", "NA"); |
| |
| sec_cmd_set_cmd_result(sec, buff, strlen(buff)); |
| sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE; |
| sec_cmd_set_cmd_exit(sec); |
| } |
| |
| static void set_touch_mode(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[SEC_CMD_STR_LEN] = { 0 }; |
| int ret = 0; |
| u8 para[4] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: POWER off!\n", __func__); |
| goto err_out; |
| } |
| |
| switch (sec->cmd_param[0]) { |
| case 1: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, set Normal ACTIVE mode\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_fix_tmode(ts, |
| TOUCH_SYSTEM_MODE_TOUCH, TOUCH_MODE_STATE_TOUCH); |
| break; |
| case 2: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, set Normal IDLE mode\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_fix_tmode(ts, |
| TOUCH_SYSTEM_MODE_TOUCH, TOUCH_MODE_STATE_IDLE); |
| break; |
| case 3: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, set Lowpower ACTIVE mode\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_fix_tmode(ts, |
| TOUCH_SYSTEM_MODE_LOWPOWER, TOUCH_MODE_STATE_TOUCH); |
| break; |
| case 4: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, set Lowpower IDLE mode\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_fix_tmode(ts, |
| TOUCH_SYSTEM_MODE_LOWPOWER, TOUCH_MODE_STATE_IDLE); |
| break; |
| case 5: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, Sense On\n", |
| __func__, sec->cmd_param[0]); |
| ret = ts->sec_ts_write(ts, |
| SEC_TS_CMD_SENSE_ON, NULL, 0); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: fail to write Sense_on\n", __func__); |
| sec_ts_delay(300); |
| break; |
| case 6: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, Sense Off\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_SLEEP, |
| TOUCH_MODE_STATE_STOP); |
| break; |
| case 7: |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, do touch system reset\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_system_reset(ts); |
| break; |
| case 8: |
| input_info(true, &ts->client->dev, |
| "%s: Toggle Sense On/Off\n", |
| __func__, sec->cmd_param[0]); |
| ret = ts->sec_ts_read(ts, SEC_TS_READ_TS_STATUS, para, 4); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: failed to read status(%d)\n", __func__, |
| ret); |
| goto err_out; |
| } |
| |
| if (para[1] == 6) {// have to sense on |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, Sense On\n", |
| __func__, sec->cmd_param[0]); |
| ret = ts->sec_ts_write(ts, |
| SEC_TS_CMD_SENSE_ON, NULL, 0); |
| if (ret < 0) |
| input_err(true, &ts->client->dev, |
| "%s: fail to write Sense_on\n", |
| __func__); |
| |
| sec_ts_delay(300); |
| |
| input_dbg(false, &ts->client->dev, |
| "%s: SENSE ON\n", __func__); |
| } else {// have to sense off |
| input_info(true, &ts->client->dev, |
| "%s: param = %d, Sense Off\n", |
| __func__, sec->cmd_param[0]); |
| sec_ts_fix_tmode(ts, 0x6, 0x1); |
| } |
| |
| break; |
| default: |
| input_info(true, &ts->client->dev, |
| "%s: param error! param = %d\n", |
| __func__, sec->cmd_param[0]); |
| goto err_out; |
| } |
| |
| snprintf(buff, sizeof(buff), "%s", "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| |
| return; |
| |
| err_out: |
| snprintf(buff, sizeof(buff), "%s", "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| int sec_ts_fn_init(struct sec_ts_data *ts) |
| { |
| int retval; |
| |
| retval = sec_cmd_init(&ts->sec, sec_cmds, |
| ARRAY_SIZE(sec_cmds), SEC_CLASS_DEVT_TSP); |
| if (retval < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to sec_cmd_init\n", __func__); |
| goto exit; |
| } |
| |
| retval = sysfs_create_group(&ts->sec.fac_dev->kobj, |
| &cmd_attr_group); |
| if (retval < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: FTS Failed to create sysfs attributes\n", |
| __func__); |
| goto exit; |
| } |
| |
| retval = sysfs_create_link(&ts->sec.fac_dev->kobj, |
| &ts->input_dev->dev.kobj, "input"); |
| if (retval < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Failed to create input symbolic link\n", |
| __func__); |
| goto exit; |
| } |
| |
| ts->reinit_done = true; |
| |
| return 0; |
| |
| exit: |
| return retval; |
| } |
| |
| void sec_ts_fn_remove(struct sec_ts_data *ts) |
| { |
| input_err(true, &ts->client->dev, "%s\n", __func__); |
| |
| sysfs_remove_link(&ts->sec.fac_dev->kobj, "input"); |
| |
| sysfs_remove_group(&ts->sec.fac_dev->kobj, |
| &cmd_attr_group); |
| |
| sec_cmd_exit(&ts->sec, SEC_CLASS_DEVT_TSP); |
| |
| } |
| |
| int sec_ts_run_rawdata_type(struct sec_ts_data *ts, struct sec_cmd_data *sec) |
| { |
| short min[REGION_TYPE_COUNT], max[REGION_TYPE_COUNT]; |
| enum spec_check_type spec_check = SPEC_NO_CHECK; |
| int i, ii, jj; |
| int ret = -1; |
| u8 data_type = 0; |
| u8 touch_type = sec->cmd_param[1]; |
| u8 read_type[9] = {TYPE_RAW_DATA, TYPE_AMBIENT_DATA, |
| TYPE_DECODED_DATA, TYPE_REMV_AMB_DATA, |
| TYPE_SIGNAL_DATA, TYPE_OFFSET_DATA_SEC, TYPE_OFFSET_DATA_SDC, |
| TYPE_NOI_P2P_MIN, TYPE_NOI_P2P_MAX}; |
| const unsigned int buff_size = ts->tx_count * ts->rx_count * |
| CMD_RESULT_WORD_LEN; |
| unsigned int buff_len = 0; |
| char *buff; |
| char para = TO_TOUCH_MODE; |
| |
| #ifdef USE_PRESSURE_SENSOR |
| short pressure[3] = { 0 }; |
| u8 cal_data[18] = { 0 }; |
| #endif |
| |
| buff = kzalloc(buff_size, GFP_KERNEL); |
| if (!buff) |
| goto error_alloc_mem; |
| |
| for (i = 0; i < 9; i++) { |
| if (read_type[i] == sec->cmd_param[0]) |
| break; |
| } |
| if (i == 9) { |
| input_err(true, &ts->client->dev, "%s: invalid data type\n", |
| __func__); |
| goto out; |
| } |
| |
| ts->tsp_dump_lock = 1; |
| input_info(true, &ts->client->dev, |
| "%s: start (wet:%d)##\n", |
| __func__, ts->wet_mode); |
| |
| |
| if (sec->cmd_param[0] == TYPE_OFFSET_DATA_SDC) |
| data_type = TYPE_OFFSET_DATA_SDC_NOT_SAVE; |
| else |
| data_type = (u8)sec->cmd_param[0]; |
| |
| if (data_type == TYPE_NOI_P2P_MIN |
| || data_type == TYPE_NOI_P2P_MAX) { |
| disable_irq(ts->client->irq); |
| |
| ret = execute_p2ptest(ts); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: P2P test failed\n", |
| __func__); |
| } |
| |
| ret = ts->sec_ts_write(ts, SEC_TS_CMD_SET_POWER_MODE, ¶, 1); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, |
| "%s: Set powermode failed\n", __func__); |
| enable_irq(ts->client->irq); |
| goto out; |
| } |
| |
| enable_irq(ts->client->irq); |
| } else { |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode\n", |
| __func__); |
| goto out; |
| } |
| } |
| |
| if (touch_type == 0) { |
| ret = sec_ts_read_frame(ts, data_type, min, max, |
| &spec_check); |
| |
| if (ret < 0) |
| input_info(true, &ts->client->dev, |
| "%s: mutual %d : error ## ret:%d\n", |
| __func__, sec->cmd_param[0], ret); |
| else |
| input_info(true, &ts->client->dev, |
| "%s: mutual %d : Max/Min %d,%d ##\n", |
| __func__, sec->cmd_param[0], |
| max[0], min[0]); |
| |
| sec_ts_delay(20); |
| |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n"); |
| if (!ts->print_format) { |
| for (ii = 0; ii < (ts->rx_count * ts->tx_count); ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", ts->pFrame[ii]); |
| if (ii % ts->tx_count == (ts->tx_count - 1)) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } else { |
| for (ii = 0; ii < ts->tx_count; ii++) { |
| for (jj = 0; jj < ts->rx_count; jj++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", |
| ts->pFrame[(jj * ts->tx_count) |
| + ii]); |
| } |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } |
| } else if (touch_type > 0) { |
| ret = sec_ts_read_channel(ts, data_type, min, |
| max, &spec_check); |
| if (ret < 0) |
| input_info(true, &ts->client->dev, |
| "%s: self %d : error ## ret:%d\n", |
| __func__, sec->cmd_param[0], ret); |
| else |
| input_info(true, &ts->client->dev, |
| "%s: self %d : Max/Min %d,%d ##\n", |
| __func__, sec->cmd_param[0], max[0], |
| min[0]); |
| |
| sec_ts_delay(20); |
| |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n "); |
| if (!ts->print_format) { |
| for (ii = 0; ii < (ts->rx_count + ts->tx_count); ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", ts->pFrame[ii]); |
| if (ii >= ts->tx_count - 1) |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "\n"); |
| } |
| } else { |
| for (ii = ts->tx_count; |
| ii < (ts->rx_count + ts->tx_count); ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,", ts->pFrame[ii]); |
| } |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, "\n"); |
| for (ii = 0; ii < ts->tx_count; ii++) { |
| buff_len += scnprintf(buff + buff_len, |
| buff_size - buff_len, |
| "%3d,\n", ts->pFrame[ii]); |
| } |
| } |
| } |
| |
| #ifdef USE_PRESSURE_SENSOR |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode\n", |
| __func__); |
| goto out; |
| } |
| |
| /* run pressure offset data read */ |
| read_pressure_data(ts, TYPE_OFFSET_DATA_SEC, pressure); |
| sec_ts_delay(20); |
| |
| /* run pressure rawdata read */ |
| read_pressure_data(ts, TYPE_RAW_DATA, pressure); |
| sec_ts_delay(20); |
| |
| /* run pressure raw delta read */ |
| read_pressure_data(ts, TYPE_REMV_AMB_DATA, pressure); |
| sec_ts_delay(20); |
| |
| /* run pressure sigdata read */ |
| read_pressure_data(ts, TYPE_SIGNAL_DATA, pressure); |
| sec_ts_delay(20); |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_SET_GET_PRESSURE, cal_data, |
| 18); |
| ts->pressure_left = ((cal_data[16] << 8) | cal_data[17]); |
| ts->pressure_center = ((cal_data[8] << 8) | cal_data[9]); |
| ts->pressure_right = ((cal_data[0] << 8) | cal_data[1]); |
| input_info(true, &ts->client->dev, "%s: pressure cal data - Left: %d, Center: %d, Right: %d\n", |
| __func__, ts->pressure_left, ts->pressure_center, |
| ts->pressure_right); |
| #endif |
| sec_ts_release_tmode(ts); |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode.\n", |
| __func__); |
| goto out; |
| } |
| |
| sec_ts_read_gain_table(ts); |
| |
| sec_ts_release_tmode(ts); |
| out: |
| input_info(true, &ts->client->dev, "%s: ito : %02X %02X %02X %02X\n", |
| __func__, ts->ito_test[0], ts->ito_test[1] |
| , ts->ito_test[2], ts->ito_test[3]); |
| |
| input_info(true, &ts->client->dev, "%s: done (wet:%d)##\n", |
| __func__, ts->wet_mode); |
| ts->tsp_dump_lock = 0; |
| |
| sec_ts_locked_release_all_finger(ts); |
| |
| sec_cmd_set_cmd_result(sec, buff, buff_len); |
| kfree(buff); |
| |
| return ret; |
| |
| error_alloc_mem: |
| sec_cmd_set_cmd_result(sec, "FAIL", 4); |
| return ret; |
| } |
| |
| static void run_rawdata_read_type(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| int ret = -1; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->tsp_dump_lock == 1) { |
| input_err(true, &ts->client->dev, "%s: already checking now\n", |
| __func__); |
| scnprintf(buff, sizeof(buff), "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: IC is power off\n", |
| __func__); |
| scnprintf(buff, sizeof(buff), "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| |
| ret = sec_ts_run_rawdata_type(ts, sec); |
| if (ret < 0) { |
| scnprintf(buff, sizeof(buff), "NA"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| } else { |
| scnprintf(buff, sizeof(buff), "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| } |
| out: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |
| |
| /* |
| * sec_ts_run_rawdata_all : read all raw data |
| * |
| * when you want to read full raw data (full_read : true) |
| * "mutual/self 3, 5, 29, 1, 19" data will be saved in log |
| * |
| * otherwise, (full_read : false, especially on boot time) |
| * only "mutual 3, 5, 29" data will be saved in log |
| */ |
| void sec_ts_run_rawdata_all(struct sec_ts_data *ts, bool full_read) |
| { |
| short min[REGION_TYPE_COUNT], max[REGION_TYPE_COUNT]; |
| enum spec_check_type spec_check = SPEC_NO_CHECK; |
| int ret, i, read_num; |
| u8 test_type[5] = {TYPE_AMBIENT_DATA, TYPE_DECODED_DATA, |
| TYPE_SIGNAL_DATA, TYPE_OFFSET_DATA_SEC, TYPE_OFFSET_DATA_SDC}; |
| #ifdef USE_PRESSURE_SENSOR |
| short pressure[3] = { 0 }; |
| u8 cal_data[18] = { 0 }; |
| #endif |
| |
| ts->tsp_dump_lock = 1; |
| input_info(true, &ts->client->dev, |
| "%s: start (wet:%d)##\n", |
| __func__, ts->wet_mode); |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode\n", |
| __func__); |
| goto out; |
| } |
| |
| if (full_read) { |
| read_num = 5; |
| } else { |
| read_num = 3; |
| test_type[read_num - 1] = TYPE_OFFSET_DATA_SDC; |
| } |
| |
| for (i = 0; i < read_num; i++) { |
| ret = sec_ts_read_frame(ts, test_type[i], min, max, |
| &spec_check); |
| if (ret < 0) |
| input_info(true, &ts->client->dev, |
| "%s: mutual %d : error ## ret:%d\n", |
| __func__, test_type[i], ret); |
| else |
| input_info(true, &ts->client->dev, |
| "%s: mutual %d : Max/Min %d,%d ##\n", |
| __func__, test_type[i], max[0], min[0]); |
| sec_ts_delay(20); |
| |
| if (full_read) { |
| ret = sec_ts_read_channel(ts, test_type[i], min, |
| max, &spec_check); |
| if (ret < 0) |
| input_info(true, &ts->client->dev, |
| "%s: self %d : error ## ret:%d\n", |
| __func__, test_type[i], ret); |
| else |
| input_info(true, &ts->client->dev, |
| "%s: self %d : Max/Min %d,%d ##\n", |
| __func__, test_type[i], max[0], |
| min[0]); |
| sec_ts_delay(20); |
| } |
| } |
| |
| #ifdef USE_PRESSURE_SENSOR |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode\n", |
| __func__); |
| goto out; |
| } |
| |
| /* run pressure offset data read */ |
| read_pressure_data(ts, TYPE_OFFSET_DATA_SEC, pressure); |
| sec_ts_delay(20); |
| |
| /* run pressure rawdata read */ |
| read_pressure_data(ts, TYPE_RAW_DATA, pressure); |
| sec_ts_delay(20); |
| |
| /* run pressure raw delta read */ |
| read_pressure_data(ts, TYPE_REMV_AMB_DATA, pressure); |
| sec_ts_delay(20); |
| |
| /* run pressure sigdata read */ |
| read_pressure_data(ts, TYPE_SIGNAL_DATA, pressure); |
| sec_ts_delay(20); |
| |
| ret = ts->sec_ts_read(ts, SEC_TS_CMD_SET_GET_PRESSURE, cal_data, |
| 18); |
| ts->pressure_left = ((cal_data[16] << 8) | cal_data[17]); |
| ts->pressure_center = ((cal_data[8] << 8) | cal_data[9]); |
| ts->pressure_right = ((cal_data[0] << 8) | cal_data[1]); |
| input_info(true, &ts->client->dev, "%s: pressure cal data - Left: %d, Center: %d, Right: %d\n", |
| __func__, ts->pressure_left, ts->pressure_center, |
| ts->pressure_right); |
| #endif |
| sec_ts_release_tmode(ts); |
| |
| ret = sec_ts_fix_tmode(ts, TOUCH_SYSTEM_MODE_TOUCH, |
| TOUCH_MODE_STATE_TOUCH); |
| if (ret < 0) { |
| input_err(true, &ts->client->dev, "%s: failed to fix tmode.\n", |
| __func__); |
| goto out; |
| } |
| |
| sec_ts_read_gain_table(ts); |
| |
| sec_ts_release_tmode(ts); |
| out: |
| input_info(true, &ts->client->dev, "%s: ito : %02X %02X %02X %02X\n", |
| __func__, ts->ito_test[0], ts->ito_test[1] |
| , ts->ito_test[2], ts->ito_test[3]); |
| |
| input_info(true, &ts->client->dev, "%s: done (wet:%d)##\n", |
| __func__, ts->wet_mode); |
| ts->tsp_dump_lock = 0; |
| |
| sec_ts_locked_release_all_finger(ts); |
| } |
| |
| static void run_rawdata_read_all(void *device_data) |
| { |
| struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data; |
| struct sec_ts_data *ts = container_of(sec, struct sec_ts_data, sec); |
| char buff[16] = { 0 }; |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, true); |
| |
| sec_cmd_set_default_result(sec); |
| |
| if (ts->tsp_dump_lock == 1) { |
| input_err(true, &ts->client->dev, "%s: already checking now\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| if (ts->power_status == SEC_TS_STATE_POWER_OFF) { |
| input_err(true, &ts->client->dev, "%s: IC is power off\n", |
| __func__); |
| snprintf(buff, sizeof(buff), "NG"); |
| sec->cmd_state = SEC_CMD_STATUS_FAIL; |
| goto out; |
| } |
| |
| sec_ts_run_rawdata_all(ts, true); |
| |
| snprintf(buff, sizeof(buff), "OK"); |
| sec->cmd_state = SEC_CMD_STATUS_OK; |
| out: |
| sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff))); |
| input_info(true, &ts->client->dev, "%s: %s\n", __func__, buff); |
| |
| sec_ts_set_bus_ref(ts, SEC_TS_BUS_REF_SYSFS, false); |
| } |