| /* 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; |
| |
| |
| } |
| |
|