7613 lines
229 KiB
C
7613 lines
229 KiB
C
|
#ifdef SEC_TSP_FACTORY_TEST
|
||
|
|
||
|
#define BUFFER_MAX ((256 * 1024) - 16)
|
||
|
|
||
|
enum {
|
||
|
TYPE_RAW_DATA = 0x30, // only for winner, etc 0x31
|
||
|
TYPE_FILTERED_RAW_DATA = 0x31, // only for winner
|
||
|
TYPE_BASELINE_DATA = 0x32,
|
||
|
TYPE_STRENGTH_DATA = 0x33,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
BUILT_IN = 0,
|
||
|
UMS,
|
||
|
};
|
||
|
|
||
|
enum ito_error_type {
|
||
|
ITO_FORCE_SHRT_GND = 0x60,
|
||
|
ITO_SENSE_SHRT_GND = 0x61,
|
||
|
ITO_FORCE_SHRT_VDD = 0x62,
|
||
|
ITO_SENSE_SHRT_VDD = 0x63,
|
||
|
ITO_FORCE_SHRT_FORCE = 0x64,
|
||
|
ITO_SENSE_SHRT_SENSE = 0x65,
|
||
|
ITO_FORCE_OPEN = 0x66,
|
||
|
ITO_SENSE_OPEN = 0x67,
|
||
|
ITO_KEY_OPEN = 0x68
|
||
|
};
|
||
|
|
||
|
#define FTS_COMP_DATA_HEADER_SIZE 16
|
||
|
|
||
|
enum fts_nvm_data_type { /* Write Command */
|
||
|
FTS_NVM_OFFSET_FAC_RESULT = 1,
|
||
|
FTS_NVM_OFFSET_CAL_COUNT,
|
||
|
FTS_NVM_OFFSET_DISASSEMBLE_COUNT,
|
||
|
FTS_NVM_OFFSET_TUNE_VERSION,
|
||
|
FTS_NVM_OFFSET_CAL_POSITION,
|
||
|
FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT,
|
||
|
FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP,
|
||
|
FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO,
|
||
|
FTS_NVM_OFFSET_CAL_FAIL_FLAG,
|
||
|
FTS_NVM_OFFSET_CAL_FAIL_COUNT,
|
||
|
};
|
||
|
|
||
|
struct fts_nvm_data_map {
|
||
|
int type;
|
||
|
int offset;
|
||
|
int length;
|
||
|
};
|
||
|
|
||
|
#define NVM_CMD(mtype, moffset, mlength) .type = mtype, .offset = moffset, .length = mlength
|
||
|
|
||
|
/* This Flash Meory Map is FIXED by STM firmware
|
||
|
* Do not change MAP.
|
||
|
*/
|
||
|
struct fts_nvm_data_map nvm_data[] = {
|
||
|
{NVM_CMD(0, 0x00, 0),},
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_FAC_RESULT, 0x00, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_CAL_COUNT, 0x01, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_DISASSEMBLE_COUNT, 0x02, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_TUNE_VERSION, 0x03, 2),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_CAL_POSITION, 0x05, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT, 0x06, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP, 0x07, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO, 0x08, 20),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_CAL_FAIL_FLAG, 0x1C, 1),}, /* SEC */
|
||
|
{NVM_CMD(FTS_NVM_OFFSET_CAL_FAIL_COUNT, 0x1D, 1),}, /* SEC */
|
||
|
};
|
||
|
#define FTS_NVM_OFFSET_ALL 31
|
||
|
|
||
|
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);
|
||
|
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 run_jitter_test(void *device_data);
|
||
|
static void run_mutual_jitter(void *device_data);
|
||
|
static void run_self_jitter(void *device_data);
|
||
|
static void run_jitter_delta_test(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_checksum_data(void *device_data);
|
||
|
static void check_fw_corruption(void *device_data);
|
||
|
static void run_reference_read(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 get_rawcap(void *device_data);
|
||
|
static void run_lp_single_ended_rawcap_read(void *device_data);
|
||
|
static void run_lp_single_ended_rawcap_read_all(void *device_data);
|
||
|
static void run_low_frequency_rawcap_read(void *device_data);
|
||
|
static void run_low_frequency_rawcap_read_all(void *device_data);
|
||
|
static void run_high_frequency_rawcap_read(void *device_data);
|
||
|
static void run_high_frequency_rawcap_read_all(void *device_data);
|
||
|
static void run_delta_read(void *device_data);
|
||
|
static void get_delta(void *device_data);
|
||
|
static void run_rawdata_read_all(void *device_data);
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
static void get_pat_information(void *device_data);
|
||
|
static void set_external_factory(void *device_data);
|
||
|
static void tclm_test_cmd(void *device_data);
|
||
|
static void get_calibration(void *device_data);
|
||
|
#endif
|
||
|
static void run_ix_data_read(void *device_data);
|
||
|
static void run_ix_data_read_all(void *device_data);
|
||
|
static void run_self_raw_read(void *device_data);
|
||
|
static void run_factory_miscalibration(void *device_data);
|
||
|
static void run_miscalibration(void *device_data);
|
||
|
static void run_self_raw_read_all(void *device_data);
|
||
|
static void run_trx_short_test(void *device_data);
|
||
|
static void check_connection(void *device_data);
|
||
|
static void get_cx_data(void *device_data);
|
||
|
static void run_active_cx_data_read(void *device_data);
|
||
|
static void run_multi_mutual_cx_data_read(void *device_data);
|
||
|
static void run_cx_data_read(void *device_data);
|
||
|
static void get_cx_all_data(void *device_data);
|
||
|
static void run_cx_gap_data_x_all(void *device_data);
|
||
|
static void run_cx_gap_data_y_all(void *device_data);
|
||
|
static void run_rawdata_gap_data_rx_all(void *device_data);
|
||
|
static void run_rawdata_gap_data_tx_all(void *device_data);
|
||
|
static void run_prox_intensity_read_all(void *device_data);
|
||
|
static void get_strength_all_data(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 get_osc_trim_error(void *device_data);
|
||
|
static void get_osc_trim_info(void *device_data);
|
||
|
static void run_snr_non_touched(void *device_data);
|
||
|
static void run_snr_touched(void *device_data);
|
||
|
/*
|
||
|
static void run_elvss_test(void *device_data);
|
||
|
*/
|
||
|
#ifdef CONFIG_GLOVE_TOUCH
|
||
|
static void glove_mode(void *device_data);
|
||
|
#endif
|
||
|
static void clear_cover_mode(void *device_data);
|
||
|
static void report_rate(void *device_data);
|
||
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
||
|
static void interrupt_control(void *device_data);
|
||
|
#endif
|
||
|
|
||
|
static void set_wirelesscharger_mode(void *device_data);
|
||
|
static void set_grip_data(void *device_data);
|
||
|
static void dead_zone_enable(void *device_data);
|
||
|
static void drawing_test_enable(void *device_data);
|
||
|
static void spay_enable(void *device_data);
|
||
|
static void aot_enable(void *device_data);
|
||
|
static void aod_enable(void *device_data);
|
||
|
static void singletap_enable(void *device_data);
|
||
|
static void set_aod_rect(void *device_data);
|
||
|
static void get_aod_rect(void *device_data);
|
||
|
static void fod_enable(void *device_data);
|
||
|
static void set_fod_rect(void *device_data);
|
||
|
static void external_noise_mode(void *device_data);
|
||
|
static void brush_enable(void *device_data);
|
||
|
static void set_touchable_area(void *device_data);
|
||
|
static void debug(void *device_data);
|
||
|
static void factory_cmd_result_all(void *device_data);
|
||
|
static void factory_cmd_result_all_imagetest(void *device_data);
|
||
|
static void run_force_calibration(void *device_data);
|
||
|
static void set_factory_level(void *device_data);
|
||
|
static void fix_active_mode(void *device_data);
|
||
|
static void touch_aging_mode(void *device_data);
|
||
|
static void run_sram_test(void *device_data);
|
||
|
static void set_rear_selfie_mode(void *device_data);
|
||
|
static void ear_detect_enable(void *device_data);
|
||
|
static void pocket_mode_enable(void *device_data);
|
||
|
static void set_sip_mode(void *device_data);
|
||
|
static void set_note_mode(void *device_data);
|
||
|
static void set_game_mode(void *device_data);
|
||
|
static void not_support_cmd(void *device_data);
|
||
|
|
||
|
static ssize_t fts_scrub_position(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf);
|
||
|
|
||
|
struct sec_cmd ft_commands[] = {
|
||
|
{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),},
|
||
|
{SEC_CMD("get_threshold", get_threshold),},
|
||
|
{SEC_CMD("module_off_master", module_off_master),},
|
||
|
{SEC_CMD("module_on_master", module_on_master),},
|
||
|
{SEC_CMD("module_off_slave", not_support_cmd),},
|
||
|
{SEC_CMD("module_on_slave", not_support_cmd),},
|
||
|
{SEC_CMD("get_chip_vendor", get_chip_vendor),},
|
||
|
{SEC_CMD("get_chip_name", get_chip_name),},
|
||
|
{SEC_CMD("run_jitter_test", run_jitter_test),},
|
||
|
{SEC_CMD("run_mutual_jitter", run_mutual_jitter),},
|
||
|
{SEC_CMD("run_self_jitter", run_self_jitter),},
|
||
|
{SEC_CMD("run_jitter_delta_test", run_jitter_delta_test),},
|
||
|
{SEC_CMD("get_wet_mode", get_wet_mode),},
|
||
|
{SEC_CMD("get_module_vendor", not_support_cmd),},
|
||
|
{SEC_CMD("get_x_num", get_x_num),},
|
||
|
{SEC_CMD("get_y_num", get_y_num),},
|
||
|
{SEC_CMD("get_checksum_data", get_checksum_data),},
|
||
|
{SEC_CMD("get_crc_check", check_fw_corruption),},
|
||
|
{SEC_CMD("run_reference_read", run_reference_read),},
|
||
|
{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_lp_single_ended_rawcap_read", run_lp_single_ended_rawcap_read),},
|
||
|
{SEC_CMD("run_lp_single_ended_rawcap_read_all", run_lp_single_ended_rawcap_read_all),},
|
||
|
{SEC_CMD("run_low_frequency_rawcap_read", run_low_frequency_rawcap_read),},
|
||
|
{SEC_CMD("run_low_frequency_rawcap_read_all", run_low_frequency_rawcap_read_all),},
|
||
|
{SEC_CMD("run_high_frequency_rawcap_read", run_high_frequency_rawcap_read),},
|
||
|
{SEC_CMD("run_high_frequency_rawcap_read_all", run_high_frequency_rawcap_read_all),},
|
||
|
{SEC_CMD("run_delta_read", run_delta_read),},
|
||
|
{SEC_CMD("get_delta", get_delta),},
|
||
|
{SEC_CMD("run_cs_raw_read_all", run_rawcap_read_all),},
|
||
|
{SEC_CMD("run_prox_intensity_read_all", run_prox_intensity_read_all),},
|
||
|
{SEC_CMD("run_cs_delta_read_all", get_strength_all_data),},
|
||
|
{SEC_CMD("run_rawdata_read_all_for_ghost", run_rawdata_read_all),},
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
{SEC_CMD("get_pat_information", get_pat_information),},
|
||
|
{SEC_CMD("set_external_factory", set_external_factory),},
|
||
|
{SEC_CMD("tclm_test_cmd", tclm_test_cmd),},
|
||
|
{SEC_CMD("get_calibration", get_calibration),},
|
||
|
#endif
|
||
|
{SEC_CMD("run_ix_data_read", run_ix_data_read),},
|
||
|
{SEC_CMD("run_ix_data_read_all", run_ix_data_read_all),},
|
||
|
{SEC_CMD("run_self_raw_read", run_self_raw_read),},
|
||
|
{SEC_CMD("run_self_raw_read_all", run_self_raw_read_all),},
|
||
|
{SEC_CMD("run_factory_miscalibration", run_factory_miscalibration),},
|
||
|
{SEC_CMD("run_miscalibration", run_miscalibration),},
|
||
|
{SEC_CMD("run_trx_short_test", run_trx_short_test),},
|
||
|
{SEC_CMD("check_connection", check_connection),},
|
||
|
{SEC_CMD("get_cx_data", get_cx_data),},
|
||
|
{SEC_CMD("run_active_cx_data_read", run_active_cx_data_read),},
|
||
|
{SEC_CMD("run_multi_mutual_cx_data_read", run_multi_mutual_cx_data_read),},
|
||
|
{SEC_CMD("run_cx_data_read", run_cx_data_read),},
|
||
|
{SEC_CMD("run_cx_data_read_all", get_cx_all_data),},
|
||
|
{SEC_CMD("get_cx_all_data", get_cx_all_data),},
|
||
|
{SEC_CMD("run_cx_gap_data_rx_all", run_cx_gap_data_x_all),},
|
||
|
{SEC_CMD("run_cx_gap_data_tx_all", run_cx_gap_data_y_all),},
|
||
|
{SEC_CMD("run_rawdata_gap_data_rx_all", run_rawdata_gap_data_rx_all),},
|
||
|
{SEC_CMD("run_rawdata_gap_data_tx_all", run_rawdata_gap_data_tx_all),},
|
||
|
{SEC_CMD("get_strength_all_data", get_strength_all_data),},
|
||
|
{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("get_osc_trim_error", get_osc_trim_error),},
|
||
|
{SEC_CMD("get_osc_trim_info", get_osc_trim_info),},
|
||
|
{SEC_CMD("run_snr_non_touched", run_snr_non_touched),},
|
||
|
{SEC_CMD("run_snr_touched", run_snr_touched),},
|
||
|
/*
|
||
|
{SEC_CMD("run_elvss_test", run_elvss_test),},
|
||
|
*/
|
||
|
#ifdef CONFIG_GLOVE_TOUCH
|
||
|
{SEC_CMD_H("glove_mode", glove_mode),},
|
||
|
#endif
|
||
|
{SEC_CMD_H("clear_cover_mode", clear_cover_mode),},
|
||
|
{SEC_CMD("report_rate", report_rate),},
|
||
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
||
|
{SEC_CMD("interrupt_control", interrupt_control),},
|
||
|
#endif
|
||
|
{SEC_CMD("set_wirelesscharger_mode", set_wirelesscharger_mode),},
|
||
|
{SEC_CMD("set_grip_data", set_grip_data),},
|
||
|
{SEC_CMD("dead_zone_enable", dead_zone_enable),},
|
||
|
{SEC_CMD("drawing_test_enable", drawing_test_enable),},
|
||
|
{SEC_CMD_H("spay_enable", spay_enable),},
|
||
|
{SEC_CMD_H("aot_enable", aot_enable),},
|
||
|
{SEC_CMD_H("aod_enable", aod_enable),},
|
||
|
{SEC_CMD_H("singletap_enable", singletap_enable),},
|
||
|
{SEC_CMD("set_aod_rect", set_aod_rect),},
|
||
|
{SEC_CMD("get_aod_rect", get_aod_rect),},
|
||
|
{SEC_CMD_H("fod_enable", fod_enable),},
|
||
|
{SEC_CMD("set_fod_rect", set_fod_rect),},
|
||
|
{SEC_CMD_H("external_noise_mode", external_noise_mode),},
|
||
|
{SEC_CMD_H("brush_enable", brush_enable),},
|
||
|
{SEC_CMD_H("set_touchable_area", set_touchable_area),},
|
||
|
{SEC_CMD("debug", debug),},
|
||
|
{SEC_CMD("factory_cmd_result_all", factory_cmd_result_all),},
|
||
|
{SEC_CMD("factory_cmd_result_all_imagetest", factory_cmd_result_all_imagetest),},
|
||
|
{SEC_CMD("run_force_calibration", run_force_calibration),},
|
||
|
{SEC_CMD("set_factory_level", set_factory_level),},
|
||
|
{SEC_CMD("fix_active_mode", fix_active_mode),},
|
||
|
{SEC_CMD("touch_aging_mode", touch_aging_mode),},
|
||
|
{SEC_CMD("run_sram_test", run_sram_test),},
|
||
|
{SEC_CMD_H("set_rear_selfie_mode", set_rear_selfie_mode),},
|
||
|
{SEC_CMD_H("ear_detect_enable", ear_detect_enable),},
|
||
|
{SEC_CMD_H("pocket_mode_enable", pocket_mode_enable),},
|
||
|
{SEC_CMD("set_sip_mode", set_sip_mode),},
|
||
|
{SEC_CMD_H("set_note_mode", set_note_mode),},
|
||
|
{SEC_CMD("set_game_mode", set_game_mode),},
|
||
|
{SEC_CMD("not_support_cmd", not_support_cmd),},
|
||
|
};
|
||
|
|
||
|
/* read param */
|
||
|
static ssize_t hardware_param_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[516];
|
||
|
char tbuff[128];
|
||
|
char temp[128];
|
||
|
|
||
|
memset(buff, 0x00, sizeof(buff));
|
||
|
|
||
|
/* ito_check */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TITO\":\"%02X%02X%02X%02X\",",
|
||
|
info->ito_test[0], info->ito_test[1],
|
||
|
info->ito_test[2], info->ito_test[3]);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* muli_count */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TMUL\":\"%d\",", info->multi_count);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* wet_mode */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TWET\":\"%d\",", info->wet_count);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* noise_mode */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TNOI\":\"%d\",", info->noise_count);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* comm_err_count */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TCOM\":\"%d\",", info->comm_err_count);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* module_id */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TMOD\":\"ST%02X%04X%02X%c%01X\",",
|
||
|
info->panel_revision, info->fw_main_version_of_ic,
|
||
|
info->test_result.data[0],
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
info->tdata->tclm_string[info->tdata->nvdata.cal_position].s_name,
|
||
|
info->tdata->nvdata.cal_count & 0xF);
|
||
|
#else
|
||
|
'0',0);
|
||
|
#endif
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* vendor_id */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
if (info->board->firmware_name) {
|
||
|
memset(temp, 0x00, sizeof(temp));
|
||
|
snprintf(temp, 9, "%s", info->board->firmware_name + 8);
|
||
|
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TVEN\":\"STM_%s\",", temp);
|
||
|
} else {
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TVEN\":\"STM\",");
|
||
|
}
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* checksum */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TCHK\":\"%d\",", info->checksum_result);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* all_touch_count */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TTCN\":\"%d\",\"TACN\":\"%d\",\"TSCN\":\"%d\",",
|
||
|
info->all_finger_count, info->all_aod_tap_count,
|
||
|
info->all_spay_count);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
/* xenosensor_detect_count */
|
||
|
memset(tbuff, 0x00, sizeof(tbuff));
|
||
|
snprintf(tbuff, sizeof(tbuff), "\"TXEN\":\"%02d/%02d_%02d:%02d:%02d_%d,%d_%d\",",
|
||
|
(info->xenosensor_detect_count > 0) ? info->xenosensor_time.tm_mon + 1 : info->xenosensor_time.tm_mon,
|
||
|
info->xenosensor_time.tm_mday, info->xenosensor_time.tm_hour, info->xenosensor_time.tm_min,
|
||
|
info->xenosensor_time.tm_sec, info->xenosensor_detect_x, info->xenosensor_detect_y,
|
||
|
info->xenosensor_detect_count);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s", buff);
|
||
|
}
|
||
|
|
||
|
/* clear param */
|
||
|
static ssize_t hardware_param_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
info->multi_count = 0;
|
||
|
info->wet_count = 0;
|
||
|
info->noise_count = 0;
|
||
|
info->comm_err_count = 0;
|
||
|
info->checksum_result = 0;
|
||
|
info->all_finger_count = 0;
|
||
|
info->all_aod_tap_count = 0;
|
||
|
info->all_spay_count = 0;
|
||
|
info->xenosensor_detect_count = 0;
|
||
|
memset(&info->xenosensor_time, 0, sizeof(info->xenosensor_time));
|
||
|
info->xenosensor_detect_x = 0;
|
||
|
info->xenosensor_detect_y = 0;
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t read_ambient_info_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
input_info(true, &info->client->dev,
|
||
|
"\"TAMB_MAX\":\"%d\",\"TAMB_MAX_TX\":\"%d\",\"TAMB_MAX_RX\":\"%d\""
|
||
|
"\"TAMB_MIN\":\"%d\",\"TAMB_MIN_TX\":\"%d\",\"TAMB_MIN_RX\":\"%d\"",
|
||
|
info->rawcap_max, info->rawcap_max_tx, info->rawcap_max_rx,
|
||
|
info->rawcap_min, info->rawcap_min_tx, info->rawcap_min_rx);
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"\"TAMB_MAX\":\"%d\",\"TAMB_MAX_TX\":\"%d\",\"TAMB_MAX_RX\":\"%d\","
|
||
|
"\"TAMB_MIN\":\"%d\",\"TAMB_MIN_TX\":\"%d\",\"TAMB_MIN_RX\":\"%d\"",
|
||
|
info->rawcap_max, info->rawcap_max_tx, info->rawcap_max_rx,
|
||
|
info->rawcap_min, info->rawcap_min_tx, info->rawcap_min_rx);
|
||
|
}
|
||
|
|
||
|
static ssize_t sensitivity_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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
unsigned char wbuf[3] = { 0 };
|
||
|
unsigned long value = 0;
|
||
|
int ret = 0;
|
||
|
|
||
|
if (count > 2)
|
||
|
return -EINVAL;
|
||
|
|
||
|
ret = kstrtoul(buf, 10, &value);
|
||
|
if (ret != 0)
|
||
|
return ret;
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
return -EPERM;
|
||
|
}
|
||
|
|
||
|
wbuf[0] = FTS_CMD_SENSITIVITY_MODE;
|
||
|
|
||
|
switch (value) {
|
||
|
case 0:
|
||
|
wbuf[1] = 0xFF; /* disable */
|
||
|
break;
|
||
|
case 1:
|
||
|
wbuf[1] = 0x24; /* enable */
|
||
|
wbuf[2] = 0x01;
|
||
|
info->sensitivity_mode = 1;
|
||
|
break;
|
||
|
case 2:
|
||
|
wbuf[1] = 0x24; /* flex mode enable */
|
||
|
wbuf[2] = 0x02;
|
||
|
info->sensitivity_mode = 2;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ret = fts_write_reg(info, wbuf, 3);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: write failed. ret: %d\n", __func__, ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
fts_delay(30);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %ld\n", __func__, value);
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t sensitivity_mode_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
u8 *rbuf;
|
||
|
u8 reg_read = FTS_READ_SENSITIVITY_VALUE;
|
||
|
int ret, i;
|
||
|
s16 value[10];
|
||
|
u8 count = 9;
|
||
|
char *buffer;
|
||
|
ssize_t len;
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
return -EPERM;
|
||
|
}
|
||
|
|
||
|
if (info->sensitivity_mode == 2) /* flex mode */
|
||
|
count = 12;
|
||
|
|
||
|
rbuf = kzalloc(count * 2, GFP_KERNEL);
|
||
|
if (!rbuf)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
buffer = kzalloc(SEC_CMD_BUF_SIZE, GFP_KERNEL);
|
||
|
if (!buffer) {
|
||
|
kfree(rbuf);
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
ret = info->fts_read_reg(info, ®_read, 1, rbuf, count * 2);
|
||
|
if (ret < 0) {
|
||
|
kfree(rbuf);
|
||
|
kfree(buffer);
|
||
|
input_err(true, &info->client->dev, "%s: read failed ret = %d\n", __func__, ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < count; i++) {
|
||
|
char temp[16];
|
||
|
|
||
|
memset(temp, 0x00, 16);
|
||
|
value[i] = rbuf[i * 2] + (rbuf[i * 2 + 1] << 8);
|
||
|
snprintf(temp, 16, "%d,", value[i]);
|
||
|
strlcat(buffer, temp, SEC_CMD_BUF_SIZE);
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buffer);
|
||
|
len = snprintf(buf, SEC_CMD_BUF_SIZE, "%s", buffer);
|
||
|
|
||
|
kfree(rbuf);
|
||
|
kfree(buffer);
|
||
|
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* read_support_feature function
|
||
|
* returns the bit combination of specific feature that is supported.
|
||
|
*/
|
||
|
static ssize_t read_support_feature(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u32 feature = 0;
|
||
|
|
||
|
if (info->board->enable_settings_aot)
|
||
|
feature |= INPUT_FEATURE_ENABLE_SETTINGS_AOT;
|
||
|
|
||
|
if (info->board->sync_reportrate_120)
|
||
|
feature |= INPUT_FEATURE_ENABLE_SYNC_RR120;
|
||
|
|
||
|
if (info->board->support_open_short_test)
|
||
|
feature |= INPUT_FEATURE_SUPPORT_OPEN_SHORT_TEST;
|
||
|
|
||
|
if (info->board->support_mis_calibration_test)
|
||
|
feature |= INPUT_FEATURE_SUPPORT_MIS_CALIBRATION_TEST;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d", feature);
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s", buff);
|
||
|
}
|
||
|
|
||
|
#ifdef FTS_SUPPORT_SPONGELIB
|
||
|
#ifdef CONFIG_TOUCHSCREEN_DUAL_FOLDABLE
|
||
|
ssize_t get_lp_dump(struct device *dev, struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info;
|
||
|
|
||
|
u8 string_data[10] = {0, };
|
||
|
u16 current_index;
|
||
|
u8 dump_format, dump_num;
|
||
|
u16 dump_start, dump_end;
|
||
|
int i, j, ret;
|
||
|
u16 addr;
|
||
|
u8 buffer[30];
|
||
|
u8 position = FTS_SPONGE_LP_DUMP_DATA_FORMAT_10_LEN;
|
||
|
|
||
|
if (!sec)
|
||
|
return -ENODEV;
|
||
|
|
||
|
info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
if (!info->lp_dump)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
if (!info->use_sponge)
|
||
|
return -ENODEV;
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
goto read_buf;
|
||
|
}
|
||
|
|
||
|
if (info->reset_is_on_going) {
|
||
|
input_err(true, &info->client->dev, "%s: reset is ongoing\n",
|
||
|
__func__);
|
||
|
goto read_buf;
|
||
|
}
|
||
|
|
||
|
if (info->lp_dump_readmore == 0)
|
||
|
goto read_buf;
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
addr = FTS_CMD_SPONGE_LP_DUMP;
|
||
|
|
||
|
ret = info->fts_read_from_sponge(info, addr, string_data, 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: Failed to read from Sponge, addr=0x%X\n", __func__, addr);
|
||
|
if (buf)
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"NG, Failed to read from Sponge, addr=0x%X", addr);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
dump_format = string_data[0];
|
||
|
dump_num = string_data[1];
|
||
|
dump_start = FTS_CMD_SPONGE_LP_DUMP + 4;
|
||
|
dump_end = dump_start + (dump_format * (dump_num - 1));
|
||
|
|
||
|
if (dump_format > 10) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: abnormal data:0x%X, 0x%X\n", __func__, string_data[0], string_data[1]);
|
||
|
if (buf)
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE, "%s",
|
||
|
"NG, Failed to read from dump format");
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
current_index = (string_data[3] & 0xFF) << 8 | (string_data[2] & 0xFF);
|
||
|
if (current_index > dump_end || current_index < dump_start) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"Failed to Sponge LP log %d\n", current_index);
|
||
|
if (buf)
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"NG, Failed to Sponge LP log, current_index=%d",
|
||
|
current_index);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: DEBUG format=%d, num=%d, start=%d, end=%d, current_index=%d\n",
|
||
|
__func__, dump_format, dump_num, dump_start, dump_end, current_index);
|
||
|
|
||
|
for (i = dump_num - 1 ; i >= 0 ; i--) {
|
||
|
u16 string_addr;
|
||
|
int value, j;
|
||
|
|
||
|
if (current_index < (dump_format * i))
|
||
|
string_addr = (dump_format * dump_num) + current_index - (dump_format * i);
|
||
|
else
|
||
|
string_addr = current_index - (dump_format * i);
|
||
|
|
||
|
if (string_addr < dump_start)
|
||
|
string_addr += (dump_format * dump_num);
|
||
|
|
||
|
addr = string_addr;
|
||
|
|
||
|
ret = info->fts_read_from_sponge(info, addr, string_data, dump_format);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: Failed to read from Sponge, addr=0x%X\n", __func__, addr);
|
||
|
if (buf)
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"NG, Failed to read from Sponge, addr=0x%X", addr);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
value = 0;
|
||
|
|
||
|
for (j = 0; j < 10; j++)
|
||
|
value += string_data[j];
|
||
|
|
||
|
if (value == 0)
|
||
|
continue;
|
||
|
|
||
|
info->lp_dump[info->lp_dump_index] = (string_addr >> 8) & 0xFF;
|
||
|
info->lp_dump[info->lp_dump_index + 1] = string_addr & 0xFF;
|
||
|
|
||
|
for (j = 0; j < 10; j += 2) {
|
||
|
info->lp_dump[info->lp_dump_index + 2 + j] = string_data[j + 1];
|
||
|
info->lp_dump[info->lp_dump_index + 2 + j + 1] = string_data[j];
|
||
|
}
|
||
|
info->lp_dump_index += position;
|
||
|
|
||
|
if (info->lp_dump_index >= position * FTS_SPONGE_LP_DUMP_LENGTH)
|
||
|
info->lp_dump_index = 0;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
read_buf:
|
||
|
if (buf) {
|
||
|
int pos = info->lp_dump_index;
|
||
|
|
||
|
for (i = 0; i < FTS_SPONGE_LP_DUMP_LENGTH; i++) {
|
||
|
if (pos >= FTS_SPONGE_LP_DUMP_DATA_FORMAT_10_LEN * FTS_SPONGE_LP_DUMP_LENGTH)
|
||
|
pos = 0;
|
||
|
|
||
|
if (info->lp_dump[pos] == 0 && info->lp_dump[pos + 1] == 0) {
|
||
|
pos += position;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
snprintf(buffer, sizeof(buffer), "%d: ", info->lp_dump[pos] << 8 | info->lp_dump[pos + 1]);
|
||
|
strlcat(buf, buffer, PAGE_SIZE);
|
||
|
memset(buffer, 0x00, sizeof(buffer));
|
||
|
for (j = 0; j < 10; j++) {
|
||
|
snprintf(buffer, sizeof(buffer), "%02x", info->lp_dump[pos + 2 + j]);
|
||
|
strlcat(buf, buffer, PAGE_SIZE);
|
||
|
memset(buffer, 0x00, sizeof(buffer));
|
||
|
}
|
||
|
snprintf(buffer, sizeof(buffer), "\n");
|
||
|
strlcat(buf, buffer, PAGE_SIZE);
|
||
|
memset(buffer, 0x00, sizeof(buffer));
|
||
|
|
||
|
pos += position;
|
||
|
}
|
||
|
}
|
||
|
out:
|
||
|
info->lp_dump_readmore = 0;
|
||
|
|
||
|
if (buf) {
|
||
|
if (strlen(buf) == 0)
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE, "%s", "empty");
|
||
|
|
||
|
return strlen(buf);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#else
|
||
|
static ssize_t get_lp_dump(struct device *dev, struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
u8 string_data[10] = {0, };
|
||
|
u16 current_index;
|
||
|
u16 dump_start, dump_end, dump_cnt;
|
||
|
int i, ret, dump_area, dump_gain;
|
||
|
unsigned char *sec_spg_dat;
|
||
|
u8 dump_clear_packet = 0x01;
|
||
|
u16 addr;
|
||
|
|
||
|
if (!info->use_sponge)
|
||
|
return -ENODEV;
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s", "TSP turned off");
|
||
|
}
|
||
|
|
||
|
/* preparing dump buffer */
|
||
|
sec_spg_dat = vmalloc(FTS_MAX_SPONGE_DUMP_BUFFER);
|
||
|
if (!sec_spg_dat) {
|
||
|
input_err(true, &info->client->dev, "%s : Failed!!\n", __func__);
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "vmalloc failed");
|
||
|
}
|
||
|
memset(sec_spg_dat, 0, FTS_MAX_SPONGE_DUMP_BUFFER);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
addr = FTS_CMD_SPONGE_LP_DUMP_CUR_IDX;
|
||
|
|
||
|
ret = info->fts_read_from_sponge(info, addr, string_data, 2);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: Failed to read from Sponge, addr=0x%X\n", __func__, addr);
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"NG, Failed to read from Sponge, addr=0x%X", addr);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
if (info->sponge_inf_dump)
|
||
|
dump_gain = 2;
|
||
|
else
|
||
|
dump_gain = 1;
|
||
|
|
||
|
current_index = (string_data[1] & 0xFF) << 8 | (string_data[0] & 0xFF);
|
||
|
dump_start = FTS_CMD_SPONGE_LP_DUMP_EVENT;
|
||
|
dump_end = dump_start + (info->sponge_dump_format * ((info->sponge_dump_event * dump_gain) - 1));
|
||
|
|
||
|
if (current_index > dump_end || current_index < dump_start) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"Failed to Sponge LP log %d\n", current_index);
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"NG, Failed to Sponge LP log, current_index=%d",
|
||
|
current_index);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
/* legacy get_lp_dump */
|
||
|
input_info(true, &info->client->dev, "%s: DEBUG format=%d, num=%d, start=%d, end=%d, current_index=%d\n",
|
||
|
__func__, info->sponge_dump_format, info->sponge_dump_event, dump_start, dump_end, current_index);
|
||
|
|
||
|
for (i = (info->sponge_dump_event * dump_gain) - 1 ; i >= 0 ; i--) {
|
||
|
u16 data0, data1, data2, data3, data4;
|
||
|
char buff[30] = {0, };
|
||
|
u16 string_addr;
|
||
|
|
||
|
if (current_index < (info->sponge_dump_format * i))
|
||
|
string_addr = (info->sponge_dump_format * info->sponge_dump_event * dump_gain) + current_index - (info->sponge_dump_format * i);
|
||
|
else
|
||
|
string_addr = current_index - (info->sponge_dump_format * i);
|
||
|
|
||
|
if (string_addr < dump_start)
|
||
|
string_addr += (info->sponge_dump_format * info->sponge_dump_event * dump_gain);
|
||
|
|
||
|
addr = string_addr;
|
||
|
|
||
|
ret = info->fts_read_from_sponge(info, addr, string_data, info->sponge_dump_format);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: Failed to read from Sponge, addr=0x%X\n", __func__, addr);
|
||
|
snprintf(buf, SEC_CMD_BUF_SIZE,
|
||
|
"NG, Failed to read from Sponge, addr=0x%X", 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);
|
||
|
data4 = (string_data[9] & 0xFF) << 8 | (string_data[8] & 0xFF);
|
||
|
|
||
|
if (data0 || data1 || data2 || data3 || data4) {
|
||
|
if (info->sponge_dump_format == 10) {
|
||
|
snprintf(buff, sizeof(buff),
|
||
|
"%d: %04x%04x%04x%04x%04x\n",
|
||
|
string_addr, data0, data1, data2, data3, data4);
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff),
|
||
|
"%d: %04x%04x%04x%04x\n",
|
||
|
string_addr, data0, data1, data2, data3);
|
||
|
}
|
||
|
strlcat(buf, buff, PAGE_SIZE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (info->sponge_inf_dump) {
|
||
|
if (current_index >= info->sponge_dump_border) {
|
||
|
dump_cnt = ((current_index - (info->sponge_dump_border)) / info->sponge_dump_format) + 1;
|
||
|
dump_area = 1;
|
||
|
addr = info->sponge_dump_border;
|
||
|
} else {
|
||
|
dump_cnt = ((current_index - FTS_CMD_SPONGE_LP_DUMP_EVENT) / info->sponge_dump_format) + 1;
|
||
|
dump_area = 0;
|
||
|
addr = FTS_CMD_SPONGE_LP_DUMP_EVENT;
|
||
|
}
|
||
|
|
||
|
ret = info->fts_read_from_sponge(info, addr, sec_spg_dat, dump_cnt * info->sponge_dump_format);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: Failed to read sponge\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
for (i = 0 ; i <= dump_cnt ; i++) {
|
||
|
int e_offset = i * info->sponge_dump_format;
|
||
|
char ibuff[30] = {0, };
|
||
|
u16 edata[5];
|
||
|
|
||
|
edata[0] = (sec_spg_dat[1 + e_offset] & 0xFF) << 8 | (sec_spg_dat[0 + e_offset] & 0xFF);
|
||
|
edata[1] = (sec_spg_dat[3 + e_offset] & 0xFF) << 8 | (sec_spg_dat[2 + e_offset] & 0xFF);
|
||
|
edata[2] = (sec_spg_dat[5 + e_offset] & 0xFF) << 8 | (sec_spg_dat[4 + e_offset] & 0xFF);
|
||
|
edata[3] = (sec_spg_dat[7 + e_offset] & 0xFF) << 8 | (sec_spg_dat[6 + e_offset] & 0xFF);
|
||
|
edata[4] = (sec_spg_dat[9 + e_offset] & 0xFF) << 8 | (sec_spg_dat[8 + e_offset] & 0xFF);
|
||
|
|
||
|
if (edata[0] || edata[1] || edata[2] || edata[3] || edata[4]) {
|
||
|
snprintf(ibuff, sizeof(ibuff), "%03d: %04x%04x%04x%04x%04x\n",
|
||
|
i + (info->sponge_dump_event * dump_area),
|
||
|
edata[0], edata[1], edata[2], edata[3], edata[4]);
|
||
|
sec_tsp_sponge_log(ibuff);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
info->sponge_dump_delayed_flag = false;
|
||
|
ret = fts_write_to_sponge(info, FTS_CMD_SPONGE_DUMP_FLUSH,
|
||
|
&dump_clear_packet, 1);
|
||
|
if (ret < 0)
|
||
|
input_err(true, &info->client->dev, "%s: Failed to clear sponge dump\n", __func__);
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
vfree(sec_spg_dat);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
return strlen(buf);
|
||
|
}
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
static ssize_t prox_power_off_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__,
|
||
|
info->prox_power_off);
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", info->prox_power_off);
|
||
|
}
|
||
|
|
||
|
static ssize_t prox_power_off_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
int ret, data;
|
||
|
|
||
|
ret = kstrtoint(buf, 10, &data);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__, data);
|
||
|
|
||
|
info->prox_power_off = data;
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t protos_event_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__, info->hover_event);
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", info->hover_event != 3 ? 0 : 3);
|
||
|
}
|
||
|
|
||
|
static ssize_t protos_event_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
int ret;
|
||
|
u8 data[2];
|
||
|
|
||
|
ret = kstrtou8(buf, 8, &data[1]);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
data[0] = FTS_CMD_SET_EAR_DETECT;
|
||
|
|
||
|
ret = fts_write_reg(info, data, 2);
|
||
|
input_info(true, &info->client->dev, "%s: set %d: ret:%d\n", __func__, data[1], ret);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_fod_info_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
if (!info->board->support_fod) {
|
||
|
input_err(true, &info->client->dev, "%s: fod is not supported\n", __func__);
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "NG");
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: x:%d/%d y:%d/%d size:%d\n",
|
||
|
__func__, info->fod_x, info->ForceChannelLength,
|
||
|
info->fod_y, info->SenseChannelLength, info->fod_vi_size);
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d,%d,%d,%d,%d\n",
|
||
|
info->fod_x, info->fod_y, info->fod_vi_size,
|
||
|
info->ForceChannelLength, info->SenseChannelLength);
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_fod_position_show(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[3] = { 0 };
|
||
|
int i;
|
||
|
|
||
|
if (!info->board->support_fod) {
|
||
|
input_err(true, &info->client->dev, "%s: fod is not supported\n", __func__);
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "NG");
|
||
|
}
|
||
|
|
||
|
if (!info->fod_vi_size) {
|
||
|
input_err(true, &info->client->dev, "%s: fod vi size is 0\n", __func__);
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "NG");
|
||
|
}
|
||
|
|
||
|
if (!info->fod_vi_data) {
|
||
|
input_err(true, &info->client->dev, "%s: fod vi data is null\n", __func__);
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "NG");
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < info->fod_vi_size; i++) {
|
||
|
snprintf(buff, 3, "%02X", info->fod_vi_data[i]);
|
||
|
strlcat(buf, buff, SEC_CMD_BUF_SIZE);
|
||
|
}
|
||
|
|
||
|
return strlen(buf);
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_TOUCHSCREEN_DUAL_FOLDABLE
|
||
|
static ssize_t dualscreen_policy_store(struct device *dev,
|
||
|
struct device_attribute *attr,
|
||
|
const char *buf, size_t count)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
int ret, value;
|
||
|
|
||
|
if (!info->board->support_flex_mode)
|
||
|
return count;
|
||
|
|
||
|
ret = kstrtoint(buf, 10, &value);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: power_state[%d] %sfolding\n",
|
||
|
__func__, info->fts_power_state, info->flip_status_current ? "": "un");
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN && info->flip_status_current == FTS_STATUS_UNFOLDING) {
|
||
|
cancel_delayed_work(&info->switching_work);
|
||
|
schedule_work(&info->switching_work.work);
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static DEVICE_ATTR(hw_param, 0664, hardware_param_show, hardware_param_store);
|
||
|
static DEVICE_ATTR(read_ambient_info, 0444, read_ambient_info_show, NULL);
|
||
|
static DEVICE_ATTR(sensitivity_mode, 0664, sensitivity_mode_show, sensitivity_mode_store);
|
||
|
static DEVICE_ATTR(scrub_pos, 0444, fts_scrub_position, NULL);
|
||
|
static DEVICE_ATTR(support_feature, 0444, read_support_feature, NULL);
|
||
|
#ifdef FTS_SUPPORT_SPONGELIB
|
||
|
static DEVICE_ATTR(get_lp_dump, 0444, get_lp_dump, NULL);
|
||
|
#endif
|
||
|
static DEVICE_ATTR(prox_power_off, 0664, prox_power_off_show, prox_power_off_store);
|
||
|
static DEVICE_ATTR(virtual_prox, 0664, protos_event_show, protos_event_store);
|
||
|
static DEVICE_ATTR(fod_info, 0444, fts_fod_info_show, NULL);
|
||
|
static DEVICE_ATTR(fod_pos, 0444, fts_fod_position_show, NULL);
|
||
|
#ifdef CONFIG_TOUCHSCREEN_DUAL_FOLDABLE
|
||
|
static DEVICE_ATTR(dualscreen_policy, 0664, NULL, dualscreen_policy_store);
|
||
|
#endif
|
||
|
static struct attribute *sec_touch_facotry_attributes[] = {
|
||
|
&dev_attr_scrub_pos.attr,
|
||
|
&dev_attr_hw_param.attr,
|
||
|
&dev_attr_read_ambient_info.attr,
|
||
|
&dev_attr_sensitivity_mode.attr,
|
||
|
&dev_attr_support_feature.attr,
|
||
|
#ifdef FTS_SUPPORT_SPONGELIB
|
||
|
&dev_attr_get_lp_dump.attr,
|
||
|
#endif
|
||
|
&dev_attr_prox_power_off.attr,
|
||
|
&dev_attr_virtual_prox.attr,
|
||
|
&dev_attr_fod_info.attr,
|
||
|
&dev_attr_fod_pos.attr,
|
||
|
#ifdef CONFIG_TOUCHSCREEN_DUAL_FOLDABLE
|
||
|
&dev_attr_dualscreen_policy.attr,
|
||
|
#endif
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
static struct attribute_group sec_touch_factory_attr_group = {
|
||
|
.attrs = sec_touch_facotry_attributes,
|
||
|
};
|
||
|
|
||
|
static ssize_t fts_get_cmoffset_dump(struct fts_ts_info *info, char *buf, u8 position)
|
||
|
{
|
||
|
u8 regaddr[4] = { 0 };
|
||
|
u8 *rbuff;
|
||
|
int ret, i, j, size = info->SenseChannelLength * info->ForceChannelLength;
|
||
|
u32 signature;
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: Touch is stopped\n", __func__);
|
||
|
return -EPERM;
|
||
|
}
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
input_err(true, &info->client->dev, "%s: Touch is LP mode\n", __func__);
|
||
|
return -EPERM;
|
||
|
}
|
||
|
|
||
|
if (info->reset_is_on_going) {
|
||
|
input_err(true, &info->client->dev, "%s: Reset is ongoing!\n", __func__);
|
||
|
return -EPERM;
|
||
|
}
|
||
|
|
||
|
if (info->sec.cmd_is_running) {
|
||
|
input_err(true, &info->client->dev, "%s: cmd is running\n", __func__);
|
||
|
return -EBUSY;
|
||
|
}
|
||
|
|
||
|
rbuff = kzalloc(size, GFP_KERNEL);
|
||
|
if (!rbuff) {
|
||
|
input_err(true, &info->client->dev, "%s: alloc failed\n", __func__);
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
/* Request SEC factory debug data from flash */
|
||
|
regaddr[0] = 0xA4;
|
||
|
regaddr[1] = 0x06;
|
||
|
regaddr[2] = 0x92;
|
||
|
regaddr[3] = position;
|
||
|
ret = fts_fw_wait_for_echo_event(info, regaddr, 4, 0);
|
||
|
if (ret < 0) {
|
||
|
snprintf(buf, info->proc_cmoffset_size, "NG, failed to request data, %d", ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
/* read header info */
|
||
|
regaddr[0] = 0xA6;
|
||
|
regaddr[1] = 0x00;
|
||
|
regaddr[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, ®addr[0], 3, rbuff, 8);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: read header failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buf, info->proc_cmoffset_size, "NG, failed to read header, %d", ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
signature = rbuff[3] << 24 | rbuff[2] << 16 | rbuff[1] << 8 | rbuff[0];
|
||
|
input_info(true, &info->client->dev,
|
||
|
"%s: position:%d, signature:%08X (%X), validation:%X, try count:%X\n",
|
||
|
__func__, position, signature, SEC_OFFSET_SIGNATURE, rbuff[4], rbuff[5]);
|
||
|
|
||
|
if (signature != SEC_OFFSET_SIGNATURE) {
|
||
|
input_err(true, &info->client->dev, "%s: cmoffset[%d], signature is mismatched\n",
|
||
|
__func__, position);
|
||
|
snprintf(buf, info->proc_cmoffset_size, "signature mismatched %08X\n", signature);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
/* read history data */
|
||
|
regaddr[0] = 0xA6;
|
||
|
regaddr[1] = 0x00;
|
||
|
regaddr[2] = (u8)info->SenseChannelLength;
|
||
|
ret = info->fts_read_reg(info, ®addr[0], 3, rbuff, size);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: read data failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buf, info->proc_cmoffset_size, "NG, failed to read data %d", ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
memset(buf, 0x00, info->proc_cmoffset_size);
|
||
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
||
|
char buff[4] = { 0 };
|
||
|
|
||
|
for (j = 0; j < info->SenseChannelLength; j++) {
|
||
|
snprintf(buff, sizeof(buff), " %d", rbuff[i * info->SenseChannelLength + j]);
|
||
|
strlcat(buf, buff, info->proc_cmoffset_size);
|
||
|
}
|
||
|
snprintf(buff, sizeof(buff), "\n");
|
||
|
strlcat(buf, buff, info->proc_cmoffset_size);
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
input_err(true, &info->client->dev, "%s: pos:%d, buf size:%zu\n", __func__, position, strlen(buf));
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
kfree(rbuff);
|
||
|
return strlen(buf);
|
||
|
}
|
||
|
|
||
|
static void enter_factory_mode(struct fts_ts_info *info, bool fac_mode)
|
||
|
{
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN)
|
||
|
return;
|
||
|
|
||
|
info->fts_systemreset(info, 50);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
if (fac_mode) {
|
||
|
// Auto-Tune without saving
|
||
|
fts_execute_autotune(info, false);
|
||
|
|
||
|
fts_delay(50);
|
||
|
}
|
||
|
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_delay(50);
|
||
|
}
|
||
|
|
||
|
static int fts_check_index(struct fts_ts_info *info)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int node;
|
||
|
|
||
|
if (sec->cmd_param[0] < 0
|
||
|
|| sec->cmd_param[0] >= info->SenseChannelLength
|
||
|
|| sec->cmd_param[1] < 0
|
||
|
|| sec->cmd_param[1] >= info->ForceChannelLength) {
|
||
|
|
||
|
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_err(true, &info->client->dev, "%s: parameter error: %u,%u\n",
|
||
|
__func__, sec->cmd_param[0], sec->cmd_param[1]);
|
||
|
node = -1;
|
||
|
return node;
|
||
|
}
|
||
|
node = sec->cmd_param[1] * info->SenseChannelLength + sec->cmd_param[0];
|
||
|
input_info(true, &info->client->dev, "%s: node = %d\n", __func__, node);
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
static ssize_t fts_scrub_position(struct device *dev,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %d %d %d\n",
|
||
|
__func__, info->scrub_id, info->scrub_x, info->scrub_y);
|
||
|
snprintf(buff, sizeof(buff), "%d %d %d", info->scrub_id, info->scrub_x, info->scrub_y);
|
||
|
|
||
|
info->scrub_x = 0;
|
||
|
info->scrub_y = 0;
|
||
|
|
||
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buff);
|
||
|
}
|
||
|
|
||
|
static void not_support_cmd(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
snprintf(buff, sizeof(buff), "%s", "NA");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void fw_update(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[64] = { 0 };
|
||
|
int retval = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\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;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
retval = fts_fw_update_on_hidden_menu(info, sec->cmd_param[0]);
|
||
|
|
||
|
if (retval < 0) {
|
||
|
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_err(true, &info->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, &info->client->dev, "%s: success [%d]\n", __func__, retval);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int fts_get_channel_info(struct fts_ts_info *info)
|
||
|
{
|
||
|
int rc = -1;
|
||
|
u8 regAdd[1] = { FTS_READ_PANEL_INFO };
|
||
|
u8 data[FTS_EVENT_SIZE] = { 0 };
|
||
|
|
||
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
||
|
|
||
|
rc = info->fts_read_reg(info, regAdd, 1, data, 11);
|
||
|
if (rc < 0) {
|
||
|
info->ForceChannelLength = 0;
|
||
|
info->SenseChannelLength = 0;
|
||
|
input_err(true, &info->client->dev, "%s: Get channel info Read Fail!!\n", __func__);
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
info->ForceChannelLength = data[8]; // Number of TX CH
|
||
|
info->SenseChannelLength = data[9]; // Number of RX CH
|
||
|
|
||
|
if (!(info->ForceChannelLength > 0 && info->ForceChannelLength < FTS_MAX_NUM_FORCE &&
|
||
|
info->SenseChannelLength > 0 && info->SenseChannelLength < FTS_MAX_NUM_SENSE)) {
|
||
|
info->ForceChannelLength = FTS_MAX_NUM_FORCE;
|
||
|
info->SenseChannelLength = FTS_MAX_NUM_SENSE;
|
||
|
input_err(true, &info->client->dev, "%s: set channel num based on max value, check it!\n", __func__);
|
||
|
}
|
||
|
|
||
|
info->ICXResolution = (data[0] << 8) | data[1]; // X resolution of IC
|
||
|
info->ICYResolution = (data[2] << 8) | data[3]; // Y resolution of IC
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: RX:Sense(%02d) TX:Force(%02d) resolution:(IC)x:%d y:%d, (DT)x:%d,y:%d\n",
|
||
|
__func__, info->SenseChannelLength, info->ForceChannelLength,
|
||
|
info->ICXResolution, info->ICYResolution, info->board->max_x, info->board->max_y);
|
||
|
|
||
|
if (info->ICXResolution > 0 && info->ICXResolution < FTS_MAX_X_RESOLUTION &&
|
||
|
info->ICYResolution > 0 && info->ICYResolution < FTS_MAX_Y_RESOLUTION &&
|
||
|
info->board->max_x != info->ICXResolution && info->board->max_y != info->ICYResolution) {
|
||
|
info->board->max_x = info->ICXResolution;
|
||
|
info->board->max_y = info->ICYResolution;
|
||
|
input_err(true, &info->client->dev, "%s: set resolution based on ic value, check it!\n", __func__);
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
static void fts_print_channel(struct fts_ts_info *info, s16 *tx_data, s16 *rx_data)
|
||
|
{
|
||
|
unsigned char *pStr = NULL;
|
||
|
unsigned char pTmp[16] = { 0 };
|
||
|
int len, max_num = 0;
|
||
|
int i = 0, k = 0;
|
||
|
int tx_count = info->ForceChannelLength;
|
||
|
int rx_count = info->SenseChannelLength;
|
||
|
|
||
|
if (tx_count > 20)
|
||
|
max_num = 10;
|
||
|
else
|
||
|
max_num = tx_count;
|
||
|
|
||
|
if (!max_num)
|
||
|
return;
|
||
|
|
||
|
len = 7 * (max_num + 1);
|
||
|
pStr = vzalloc(len);
|
||
|
if (!pStr)
|
||
|
return;
|
||
|
|
||
|
/* Print TX channel */
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " TX");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
|
||
|
for (k = 0; k < max_num; k++) {
|
||
|
snprintf(pTmp, sizeof(pTmp), " %02d", k);
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " +");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
|
||
|
for (k = 0; k < max_num; k++) {
|
||
|
snprintf(pTmp, sizeof(pTmp), "------");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " | ");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
|
||
|
for (i = 0; i < tx_count; i++) {
|
||
|
if (i && i % max_num == 0) {
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " | ");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
|
||
|
snprintf(pTmp, sizeof(pTmp), " %5d", tx_data[i]);
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
/* Print RX channel */
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " RX");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
|
||
|
for (k = 0; k < max_num; k++) {
|
||
|
snprintf(pTmp, sizeof(pTmp), " %02d", k);
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " +");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
|
||
|
for (k = 0; k < max_num; k++) {
|
||
|
snprintf(pTmp, sizeof(pTmp), "------");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " | ");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
|
||
|
for (i = 0; i < rx_count; i++) {
|
||
|
if (i && i % max_num == 0) {
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
memset(pStr, 0x0, len);
|
||
|
snprintf(pTmp, sizeof(pTmp), " | ");
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
|
||
|
snprintf(pTmp, sizeof(pTmp), " %5d", rx_data[i]);
|
||
|
strlcat(pStr, pTmp, len);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
vfree(pStr);
|
||
|
}
|
||
|
|
||
|
void fts_print_frame(struct fts_ts_info *info, short *min, short *max)
|
||
|
{
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
u8 *pStr = NULL;
|
||
|
u8 pTmp[16] = { 0 };
|
||
|
|
||
|
pStr = kzalloc(BUFFER_MAX, GFP_KERNEL);
|
||
|
if (pStr == NULL)
|
||
|
return;
|
||
|
|
||
|
snprintf(pTmp, 4, " ");
|
||
|
strlcat(pStr, pTmp, BUFFER_MAX);
|
||
|
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
snprintf(pTmp, 6, "Rx%02d ", i);
|
||
|
strlcat(pStr, pTmp, BUFFER_MAX);
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
|
||
|
snprintf(pTmp, 2, " +");
|
||
|
strlcat(pStr, pTmp, BUFFER_MAX);
|
||
|
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
snprintf(pTmp, 6, "------");
|
||
|
strlcat(pStr, pTmp, BUFFER_MAX);
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
|
||
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
||
|
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
|
||
|
snprintf(pTmp, 7, "Tx%02d | ", i);
|
||
|
strlcat(pStr, pTmp, BUFFER_MAX);
|
||
|
|
||
|
for (j = 0; j < info->SenseChannelLength; j++) {
|
||
|
snprintf(pTmp, 6, "%5d ", info->pFrame[(i * info->SenseChannelLength) + j]);
|
||
|
strlcat(pStr, pTmp, BUFFER_MAX);
|
||
|
|
||
|
if (info->pFrame[(i * info->SenseChannelLength) + j] < *min) {
|
||
|
*min = info->pFrame[(i * info->SenseChannelLength) + j];
|
||
|
if (info->rawcap_lock) {
|
||
|
info->rawcap_min = *min;
|
||
|
info->rawcap_min_tx = i;
|
||
|
info->rawcap_min_rx = j;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (info->pFrame[(i * info->SenseChannelLength) + j] > *max) {
|
||
|
*max = info->pFrame[(i * info->SenseChannelLength) + j];
|
||
|
if (info->rawcap_lock) {
|
||
|
info->rawcap_max = *max;
|
||
|
info->rawcap_max_tx = i;
|
||
|
info->rawcap_max_rx = j;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s, min:%d, max:%d\n", __func__, *min, *max);
|
||
|
|
||
|
kfree(pStr);
|
||
|
}
|
||
|
|
||
|
int fts_read_frame(struct fts_ts_info *info, u8 type, short *min, short *max)
|
||
|
{
|
||
|
struct FTS_SyncFrameHeader *pSyncFrameHeader;
|
||
|
|
||
|
u8 regAdd[8] = { 0 };
|
||
|
|
||
|
unsigned int totalbytes = 0;
|
||
|
u8 *pRead;
|
||
|
int rc = 0;
|
||
|
int ret = 0;
|
||
|
int i = 0;
|
||
|
int retry = 10;
|
||
|
|
||
|
pRead = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 3 + 1, GFP_KERNEL);
|
||
|
if (!pRead)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
/* Request Data Type */
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = (u8)type;
|
||
|
info->fts_write_reg(info, ®Add[0], 3);
|
||
|
fts_delay(50);
|
||
|
|
||
|
do {
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &pRead[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
rc = -3;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
pSyncFrameHeader = (struct FTS_SyncFrameHeader *) &pRead[0];
|
||
|
|
||
|
if ((pSyncFrameHeader->header == 0xA5) && (pSyncFrameHeader->host_data_mem_id == type))
|
||
|
break;
|
||
|
|
||
|
fts_delay(100);
|
||
|
} while (retry--);
|
||
|
|
||
|
if (retry == 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: didn't match header or id. header = %02X, id = %02X\n",
|
||
|
__func__, pSyncFrameHeader->header, pSyncFrameHeader->host_data_mem_id);
|
||
|
rc = -4;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
totalbytes = (info->ForceChannelLength * info->SenseChannelLength * 2);
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = FTS_COMP_DATA_HEADER_SIZE + pSyncFrameHeader->dbg_frm_len;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &pRead[0], totalbytes);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
rc = -5;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < totalbytes / 2; i++)
|
||
|
info->pFrame[i] = (short)(pRead[i * 2] + (pRead[i * 2 + 1] << 8));
|
||
|
|
||
|
switch (type) {
|
||
|
case TYPE_RAW_DATA:
|
||
|
input_raw_info_d(true, &info->client->dev, "%s", "[Raw Data]\n");
|
||
|
break;
|
||
|
case TYPE_STRENGTH_DATA:
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: [Strength Data]\n", __func__);
|
||
|
break;
|
||
|
case TYPE_BASELINE_DATA:
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: [Baseline Data]\n", __func__);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
fts_print_frame(info, min, max);
|
||
|
|
||
|
ErrorExit:
|
||
|
kfree(pRead);
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
int fts_read_nonsync_frame(struct fts_ts_info *info, short *min, short *max)
|
||
|
{
|
||
|
struct FTS_SyncFrameHeader *pSyncFrameHeader;
|
||
|
|
||
|
u8 regAdd[8] = { 0 };
|
||
|
|
||
|
unsigned int totalbytes = 0;
|
||
|
u8 *pRead;
|
||
|
int rc = 0;
|
||
|
int ret = 0;
|
||
|
int i = 0;
|
||
|
int retry = 10;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
pRead = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 3 + 1, GFP_KERNEL);
|
||
|
if (!pRead)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
/* Request System Information */
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = 0x01;
|
||
|
info->fts_write_reg(info, ®Add[0], 3);
|
||
|
fts_delay(50);
|
||
|
|
||
|
do {
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &pRead[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
rc = -3;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
pSyncFrameHeader = (struct FTS_SyncFrameHeader *) &pRead[0];
|
||
|
|
||
|
if ((pSyncFrameHeader->header == 0xA5) && (pSyncFrameHeader->host_data_mem_id == 0x01))
|
||
|
break;
|
||
|
|
||
|
fts_delay(100);
|
||
|
} while (retry--);
|
||
|
|
||
|
if (retry == 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: didn't match header or id. header = %02X, id = %02X\n",
|
||
|
__func__, pSyncFrameHeader->header, pSyncFrameHeader->host_data_mem_id);
|
||
|
rc = -4;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x88; // ms screen rawdata
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &pRead[0], 2);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
rc = -5;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
totalbytes = (info->ForceChannelLength * info->SenseChannelLength * 2);
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)pRead[1];
|
||
|
regAdd[2] = (u8)pRead[0];
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &pRead[0], totalbytes);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
rc = -6;
|
||
|
goto ErrorExit;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < totalbytes / 2; i++)
|
||
|
info->pFrame[i] = (short)(pRead[i * 2] + (pRead[i * 2 + 1] << 8));
|
||
|
|
||
|
fts_print_frame(info, min, max);
|
||
|
|
||
|
ErrorExit:
|
||
|
kfree(pRead);
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
void fts_get_sec_ito_test_result(struct fts_ts_info *info)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
struct fts_sec_panel_test_result result[10];
|
||
|
u8 regAdd[3] = { 0 };
|
||
|
u8 data[sizeof(struct fts_sec_panel_test_result) * 10 + 2] = { 0 };
|
||
|
int ret, i, max_count = 0;
|
||
|
u8 length = sizeof(data);
|
||
|
u8 buff[100] = { 0 };
|
||
|
u8 pos_buf[6] = { 0 };
|
||
|
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = 0x94;
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regAdd, 3, 0);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to get echo, %d\n", __func__, ret);
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, regAdd, 3, data, length);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to read data, %d\n", __func__, ret);
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
memcpy(result, &data[2], length - 2);
|
||
|
memset(info->ito_result, 0x00, FTS_ITO_RESULT_PRINT_SIZE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%s: test count - sub:%d, main:%d\n", __func__, data[0], data[1]);
|
||
|
input_info(true, &info->client->dev, "%s", buff);
|
||
|
strlcat(info->ito_result, buff, FTS_ITO_RESULT_PRINT_SIZE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "ITO: / TX_GAP_MAX / RX_GAP_MAX\n");
|
||
|
input_info(true, &info->client->dev, "%s", buff);
|
||
|
strlcat(info->ito_result, buff, FTS_ITO_RESULT_PRINT_SIZE);
|
||
|
|
||
|
for (i = 0; i < 10; i++) {
|
||
|
switch (result[i].flag) {
|
||
|
case OFFSET_FAC_SUB:
|
||
|
snprintf(pos_buf, sizeof(pos_buf), "SUB ");
|
||
|
break;
|
||
|
case OFFSET_FAC_MAIN:
|
||
|
snprintf(pos_buf, sizeof(pos_buf), "MAIN");
|
||
|
break;
|
||
|
case OFFSET_FAC_NOSAVE:
|
||
|
default:
|
||
|
snprintf(pos_buf, sizeof(pos_buf), "NONE");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "ITO: [%3d] %d-%s / Tx%02d,Rx%02d: %3d / Tx%02d,Rx%02d: %3d\n",
|
||
|
result[i].num_of_test, result[i].flag, pos_buf,
|
||
|
result[i].tx_of_txmax_gap, result[i].rx_of_txmax_gap,
|
||
|
result[i].max_of_tx_gap,
|
||
|
result[i].tx_of_rxmax_gap, result[i].rx_of_rxmax_gap,
|
||
|
result[i].max_of_rx_gap);
|
||
|
input_info(true, &info->client->dev, "%s", buff);
|
||
|
strlcat(info->ito_result, buff, FTS_ITO_RESULT_PRINT_SIZE);
|
||
|
|
||
|
/* when count is over 200, it restart from 1 */
|
||
|
if (result[i].num_of_test > result[max_count].num_of_test + 100)
|
||
|
continue;
|
||
|
if (result[i].num_of_test > result[max_count].num_of_test)
|
||
|
max_count = i;
|
||
|
if (result[i].num_of_test == 1 && result[max_count].num_of_test == 200)
|
||
|
max_count = i;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: latest test is %d\n",
|
||
|
__func__, result[max_count].num_of_test);
|
||
|
|
||
|
done:
|
||
|
if (sec->cmd_all_factory_state != SEC_CMD_STATUS_RUNNING)
|
||
|
return;
|
||
|
|
||
|
if (ret < 0) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_X");
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_Y");
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "0,%d", result[max_count].max_of_rx_gap);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_X");
|
||
|
snprintf(buff, sizeof(buff), "0,%d", result[max_count].max_of_tx_gap);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_Y");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int fts_set_sec_ito_test_result(struct fts_ts_info *info)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
u8 regAdd[3] = { 0 };
|
||
|
int ret = -EINVAL;
|
||
|
u8 buff[10] = { 0 };
|
||
|
|
||
|
if (!info->factory_position) {
|
||
|
input_err(true, &info->client->dev, "%s: not save, factory level = %d\n",
|
||
|
__func__, info->factory_position);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = info->factory_position;
|
||
|
ret = info->fts_write_reg(info, regAdd, 3);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to write fac position, %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x05;
|
||
|
regAdd[2] = 0x04;
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regAdd, 3, 200);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to get echo, %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: position %d result is saved\n", __func__, info->factory_position);
|
||
|
return 0;
|
||
|
|
||
|
out:
|
||
|
if (sec->cmd_all_factory_state != SEC_CMD_STATUS_RUNNING)
|
||
|
return ret;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_X");
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_Y");
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int fts_fw_wait_for_jitter_result(struct fts_ts_info *info, u8 *reg, u8 count, s16 *ret1, s16 *ret2)
|
||
|
{
|
||
|
int rc = 0;
|
||
|
u8 regAdd;
|
||
|
u8 data[FTS_EVENT_SIZE];
|
||
|
int retry = 0;
|
||
|
|
||
|
mutex_lock(&info->wait_for);
|
||
|
|
||
|
rc = info->fts_write_reg(info, reg, count);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to write command\n", __func__);
|
||
|
mutex_unlock(&info->wait_for);
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
||
|
|
||
|
regAdd = FTS_READ_ONE_EVENT;
|
||
|
rc = -1;
|
||
|
while (info->fts_read_reg(info, ®Add, 1, (u8 *)data, FTS_EVENT_SIZE)) {
|
||
|
if (data[0] != 0x00)
|
||
|
input_info(true, &info->client->dev,
|
||
|
"%s: event %02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
|
||
|
|
||
|
if ((data[0] == FTS_EVENT_JITTER_RESULT) && (data[1] == 0x03)) { // Check Jitter result
|
||
|
if (data[2] == FTS_EVENT_JITTER_MUTUAL_MAX) {
|
||
|
*ret2 = (s16)((data[3] << 8) + data[4]);
|
||
|
input_info(true, &info->client->dev, "%s: Mutual max jitter Strength : %d, RX:%d, TX:%d\n",
|
||
|
__func__, *ret2, data[5], data[6]);
|
||
|
} else if (data[2] == FTS_EVENT_JITTER_MUTUAL_MIN){
|
||
|
*ret1 = (s16)((data[3] << 8) + data[4]);
|
||
|
input_info(true, &info->client->dev, "%s: Mutual min jitter Strength : %d, RX:%d, TX:%d\n",
|
||
|
__func__, *ret1, data[5], data[6]);
|
||
|
rc = 0;
|
||
|
break;
|
||
|
} else if (data[2] == FTS_EVENT_JITTER_SELF_TX_P2P){
|
||
|
*ret1 = (s16)((data[3] << 8) + data[4]);
|
||
|
input_info(true, &info->client->dev, "%s: Self TX P2P jitter Strength : %d, TX:%d\n",
|
||
|
__func__, *ret1, data[6]);
|
||
|
} else if (data[2] == FTS_EVENT_JITTER_SELF_RX_P2P){
|
||
|
*ret2 = (s16)((data[3] << 8) + data[4]);
|
||
|
input_info(true, &info->client->dev, "%s: Self RX P2P jitter Strength : %d, RX:%d\n",
|
||
|
__func__, *ret2, data[5]);
|
||
|
rc = 0;
|
||
|
break;
|
||
|
}
|
||
|
} else if (data[0] == FTS_EVENT_ERROR_REPORT) {
|
||
|
input_info(true, &info->client->dev, "%s: Error detected %02X,%02X,%02X,%02X,%02X,%02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3], data[4], data[5]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (retry++ > FTS_RETRY_COUNT * 10) {
|
||
|
rc = -1;
|
||
|
input_err(true, &info->client->dev, "%s: Time Over (%02X,%02X,%02X,%02X,%02X,%02X)\n",
|
||
|
__func__, data[0], data[1], data[2], data[3], data[4], data[5]);
|
||
|
break;
|
||
|
}
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
|
||
|
mutex_unlock(&info->wait_for);
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
static void run_jitter_test(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0 };
|
||
|
int ret;
|
||
|
s16 mutual_min = 0, mutual_max = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN ||
|
||
|
info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* lock active scan mode */
|
||
|
regAdd[0] = 0xA0;
|
||
|
regAdd[1] = 0x03;
|
||
|
regAdd[2] = 0x00;
|
||
|
info->fts_write_reg(info, ®Add[0], 3);
|
||
|
fts_delay(10);
|
||
|
|
||
|
// Mutual jitter.
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x08;
|
||
|
regAdd[2] = 0x64; //100 frame
|
||
|
regAdd[3] = 0x00;
|
||
|
|
||
|
ret = fts_fw_wait_for_jitter_result(info, regAdd, 4, &mutual_min, &mutual_max);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read Mutual jitter\n", __func__);
|
||
|
goto ERROR;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d", mutual_max);
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MUTUAL_JITTER");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
ERROR:
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MUTUAL_JITTER");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: Fail %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void run_mutual_jitter(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0 };
|
||
|
int ret;
|
||
|
s16 mutual_min = 0, mutual_max = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN ||
|
||
|
info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
//lock active scan mode.
|
||
|
fts_fix_active_mode(info, true);
|
||
|
|
||
|
// Mutual jitter.
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x08;
|
||
|
regAdd[2] = 0x64; //100 frame
|
||
|
regAdd[3] = 0x00;
|
||
|
|
||
|
ret = fts_fw_wait_for_jitter_result(info, regAdd, 4, &mutual_min, &mutual_max);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read Mutual jitter\n", __func__);
|
||
|
goto ERROR;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", mutual_min, mutual_max);
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MUTUAL_JITTER");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
ERROR:
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MUTUAL_JITTER");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: Fail %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void run_self_jitter(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0 };
|
||
|
int ret;
|
||
|
s16 tx_p2p = 0, rx_p2p = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN ||
|
||
|
info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* lock active scan mode */
|
||
|
regAdd[0] = 0xA0;
|
||
|
regAdd[1] = 0x03;
|
||
|
regAdd[2] = 0x00;
|
||
|
info->fts_write_reg(info, ®Add[0], 3);
|
||
|
fts_delay(10);
|
||
|
|
||
|
/* Self jitter */
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x0A;
|
||
|
regAdd[2] = 0x64; /* 100 frame */
|
||
|
regAdd[3] = 0x00;
|
||
|
|
||
|
ret = fts_fw_wait_for_jitter_result(info, regAdd, 4, &tx_p2p, &rx_p2p);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read Self jitter\n", __func__);
|
||
|
goto ERROR;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", tx_p2p, rx_p2p);
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "SELF_JITTER");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
ERROR:
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "SELF_JITTER");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: Fail %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
static void run_jitter_delta_test(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 reg[4] = { 0 };
|
||
|
int ret;
|
||
|
int result = -1;
|
||
|
int retry = 0;
|
||
|
u8 data[FTS_EVENT_SIZE];
|
||
|
s16 min_of_min = 0;
|
||
|
s16 max_of_min = 0;
|
||
|
s16 min_of_max = 0;
|
||
|
s16 max_of_max = 0;
|
||
|
s16 min_of_avg = 0;
|
||
|
s16 max_of_avg = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN ||
|
||
|
info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
goto OUT_JITTER_DELTA;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
mutex_lock(&info->wait_for);
|
||
|
|
||
|
/* lock active scan mode */
|
||
|
reg[0] = 0xA0;
|
||
|
reg[1] = 0x03;
|
||
|
reg[2] = 0x00;
|
||
|
ret = info->fts_write_reg(info, ®[0], 3);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to set active mode\n", __func__);
|
||
|
mutex_unlock(&info->wait_for);
|
||
|
goto OUT_JITTER_DELTA;
|
||
|
}
|
||
|
fts_delay(10);
|
||
|
|
||
|
/* jitter delta + 1000 frame*/
|
||
|
reg[0] = 0xC7;
|
||
|
reg[1] = 0x08;
|
||
|
reg[2] = 0xE8;
|
||
|
reg[3] = 0x03;
|
||
|
ret = info->fts_write_reg(info, ®[0], 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to write command\n", __func__);
|
||
|
mutex_unlock(&info->wait_for);
|
||
|
goto OUT_JITTER_DELTA;
|
||
|
}
|
||
|
|
||
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
||
|
|
||
|
reg[0] = FTS_READ_ONE_EVENT;
|
||
|
while (info->fts_read_reg(info, ®[0], 1, data, FTS_EVENT_SIZE)) {
|
||
|
if ((data[0] == FTS_EVENT_JITTER_RESULT) && (data[1] == 0x03)) {
|
||
|
if (data[2] == FTS_EVENT_JITTER_MUTUAL_MAX) {
|
||
|
min_of_max = data[3] << 8 | data[4];
|
||
|
max_of_max = data[8] << 8 | data[9];
|
||
|
input_info(true, &info->client->dev, "%s: MAX: min:%d, max:%d\n", __func__, min_of_max, max_of_max);
|
||
|
} else if (data[2] == FTS_EVENT_JITTER_MUTUAL_MIN) {
|
||
|
min_of_min = data[3] << 8 | data[4];
|
||
|
max_of_min = data[8] << 8 | data[9];
|
||
|
input_info(true, &info->client->dev, "%s: MIN: min:%d, max:%d\n", __func__, min_of_min, max_of_min);
|
||
|
} else if (data[2] == FTS_EVENT_JITTER_MUTUAL_AVG) {
|
||
|
min_of_avg = data[3] << 8 | data[4];
|
||
|
max_of_avg = data[8] << 8 | data[9];
|
||
|
input_info(true, &info->client->dev, "%s: AVG: min:%d, max:%d\n", __func__, min_of_avg, max_of_avg);
|
||
|
result = 0;
|
||
|
break;
|
||
|
}
|
||
|
} else if (data[0] == FTS_EVENT_ERROR_REPORT) {
|
||
|
input_info(true, &info->client->dev, "%s: Error detected %02X,%02X,%02X,%02X,%02X,%02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3], data[4], data[5]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* waiting 10 seconds */
|
||
|
if (retry++ > FTS_RETRY_COUNT * 50) {
|
||
|
input_err(true, &info->client->dev, "%s: Time Over (%02X,%02X,%02X,%02X,%02X,%02X)\n",
|
||
|
__func__, data[0], data[1], data[2], data[3], data[4], data[5]);
|
||
|
break;
|
||
|
}
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
mutex_unlock(&info->wait_for);
|
||
|
|
||
|
OUT_JITTER_DELTA:
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
if (result < 0)
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
else
|
||
|
snprintf(buff, sizeof(buff), "%d,%d,%d,%d,%d,%d", min_of_min, max_of_min, min_of_max, max_of_max, min_of_avg, max_of_avg);
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
char buffer[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
snprintf(buffer, sizeof(buffer), "%d,%d", min_of_min, max_of_min);
|
||
|
sec_cmd_set_cmd_result_all(sec, buffer, strnlen(buffer, sizeof(buffer)), "JITTER_DELTA_MIN");
|
||
|
|
||
|
memset(buffer, 0x00, sizeof(buffer));
|
||
|
snprintf(buffer, sizeof(buffer), "%d,%d", min_of_max, max_of_max);
|
||
|
sec_cmd_set_cmd_result_all(sec, buffer, strnlen(buffer, sizeof(buffer)), "JITTER_DELTA_MAX");
|
||
|
|
||
|
memset(buffer, 0x00, sizeof(buffer));
|
||
|
snprintf(buffer, sizeof(buffer), "%d,%d", min_of_avg, max_of_avg);
|
||
|
sec_cmd_set_cmd_result_all(sec, buffer, strnlen(buffer, sizeof(buffer)), "JITTER_DELTA_AVG");
|
||
|
}
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
void fts_checking_miscal(struct fts_ts_info *info)
|
||
|
{
|
||
|
u8 regAdd[3] = { 0 };
|
||
|
u8 data[2] = { 0 };
|
||
|
u16 miscal_thd = 0;
|
||
|
int ret;
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
info->miscal_result = MISCAL_PASS;
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
/* get the raw data after C7 02 : mis cal test */
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x02;
|
||
|
|
||
|
info->fts_write_reg(info, ®Add[0], 2);
|
||
|
msleep(300);
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: [miscal diff data]\n", __func__);
|
||
|
fts_read_nonsync_frame(info, &min, &max);
|
||
|
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x0B;
|
||
|
ret = info->fts_read_reg(info, regAdd, 2, data, 2);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: failed to read miscal threshold\n", __func__);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
miscal_thd = data[0] << 8 | data[1];
|
||
|
|
||
|
if (max > miscal_thd)
|
||
|
info->miscal_result = MISCAL_FAIL;
|
||
|
|
||
|
if (min < -miscal_thd)
|
||
|
info->miscal_result = MISCAL_FAIL;
|
||
|
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: mis cal threshold:%d/%d, min/max :%d/%d, miscal:%s\n",
|
||
|
__func__, miscal_thd, -miscal_thd, min, max, info->miscal_result == MISCAL_PASS ? "PASS" : "FAIL");
|
||
|
}
|
||
|
|
||
|
int fts_panel_ito_test(struct fts_ts_info *info, int testmode)
|
||
|
{
|
||
|
u8 cmd = FTS_READ_ONE_EVENT;
|
||
|
u8 regAdd[4] = { 0 };
|
||
|
u8 data[FTS_EVENT_SIZE];
|
||
|
int i;
|
||
|
bool matched = false;
|
||
|
int retry = 0;
|
||
|
int result = 0;
|
||
|
|
||
|
result = info->fts_systemreset(info, 0);
|
||
|
if (result < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: fts_systemreset fail (%d)\n", __func__, result);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x04;
|
||
|
switch (testmode) {
|
||
|
case OPEN_TEST:
|
||
|
regAdd[2] = 0x00;
|
||
|
regAdd[3] = 0x30;
|
||
|
break;
|
||
|
|
||
|
case OPEN_SHORT_CRACK_TEST:
|
||
|
case SAVE_MISCAL_REF_RAW:
|
||
|
default:
|
||
|
regAdd[2] = 0xFF;
|
||
|
regAdd[3] = 0x01;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
info->fts_write_reg(info, ®Add[0], 4); // ITO test command
|
||
|
fts_delay(100);
|
||
|
|
||
|
memset(info->ito_test, 0x0, 4);
|
||
|
|
||
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
||
|
while (info->fts_read_reg(info, &cmd, 1, (u8 *)data, FTS_EVENT_SIZE)) {
|
||
|
if ((data[0] == FTS_EVENT_STATUS_REPORT) && (data[1] == 0x01)) { // Check command ECHO - finished
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
if (data[i + 2] != regAdd[i]) {
|
||
|
matched = false;
|
||
|
break;
|
||
|
}
|
||
|
matched = true;
|
||
|
}
|
||
|
|
||
|
if (matched == true)
|
||
|
break;
|
||
|
} else if (data[0] == FTS_EVENT_ERROR_REPORT) {
|
||
|
info->ito_test[0] = data[0];
|
||
|
info->ito_test[1] = data[1];
|
||
|
info->ito_test[2] = data[2];
|
||
|
info->ito_test[3] = 0x00;
|
||
|
result = -ITO_FAIL;
|
||
|
|
||
|
switch (data[1]) {
|
||
|
case ITO_FORCE_SHRT_GND:
|
||
|
input_info(true, &info->client->dev, "%s: Force channel [%d] short to GND\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
|
||
|
case ITO_SENSE_SHRT_GND:
|
||
|
input_info(true, &info->client->dev, "%s: Sense channel [%d] short to GND\n",
|
||
|
__func__, data[2]);
|
||
|
result = ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
|
||
|
case ITO_FORCE_SHRT_VDD:
|
||
|
input_info(true, &info->client->dev, "%s: Force channel [%d] short to VDD\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
|
||
|
case ITO_SENSE_SHRT_VDD:
|
||
|
input_info(true, &info->client->dev, "%s: Sense channel [%d] short to VDD\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
|
||
|
case ITO_FORCE_SHRT_FORCE:
|
||
|
input_info(true, &info->client->dev, "%s: Force channel [%d] short to force\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
|
||
|
case ITO_SENSE_SHRT_SENSE:
|
||
|
input_info(true, &info->client->dev, "%s: Sennse channel [%d] short to sense\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
|
||
|
case ITO_FORCE_OPEN:
|
||
|
input_info(true, &info->client->dev, "%s: Force channel [%d] open\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_OPEN;
|
||
|
break;
|
||
|
|
||
|
case ITO_SENSE_OPEN:
|
||
|
input_info(true, &info->client->dev, "%s: Sense channel [%d] open\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_OPEN;
|
||
|
break;
|
||
|
|
||
|
case ITO_KEY_OPEN:
|
||
|
input_info(true, &info->client->dev, "%s: Key channel [%d] open\n",
|
||
|
__func__, data[2]);
|
||
|
result = -ITO_FAIL_OPEN;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
input_info(true, &info->client->dev, "%s: unknown event %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||
|
__func__, data[0], data[1], data[2], data[3],
|
||
|
data[4], data[5], data[6], data[7]);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (retry++ > 50) {
|
||
|
result = -ITO_FAIL;
|
||
|
input_err(true, &info->client->dev, "%s: Time over - wait for result of ITO test\n", __func__);
|
||
|
break;
|
||
|
}
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
|
||
|
if (fts_set_sec_ito_test_result(info) >= 0)
|
||
|
fts_get_sec_ito_test_result(info);
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
if (info->flip_enable) {
|
||
|
fts_set_cover_type(info, true);
|
||
|
} else {
|
||
|
info->touch_functions = (info->touch_functions & (~FTS_TOUCHTYPE_BIT_COVER)) |
|
||
|
FTS_TOUCHTYPE_DEFAULT_ENABLE;
|
||
|
#ifdef CONFIG_GLOVE_TOUCH
|
||
|
if (info->glove_enabled)
|
||
|
info->touch_functions = info->touch_functions | FTS_TOUCHTYPE_BIT_GLOVE;
|
||
|
else
|
||
|
info->touch_functions = info->touch_functions & (~FTS_TOUCHTYPE_BIT_GLOVE);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
regAdd[0] = FTS_CMD_SET_GET_TOUCHTYPE;
|
||
|
regAdd[1] = (u8)(info->touch_functions & 0xFF);
|
||
|
regAdd[2] = (u8)(info->touch_functions >> 8);
|
||
|
fts_write_reg(info, ®Add[0], 3);
|
||
|
fts_delay(10);
|
||
|
|
||
|
#ifdef FTS_SUPPORT_TA_MODE
|
||
|
if (info->TA_Pluged) {
|
||
|
u8 wiredCharger;
|
||
|
|
||
|
regAdd[0] = FTS_CMD_SET_GET_CHARGER_MODE;
|
||
|
fts_read_reg(info, ®Add[0], 1, &data[0], 1);
|
||
|
wiredCharger = data[0] | FTS_BIT_CHARGER_MODE_WIRE_CHARGER;
|
||
|
regAdd[1] = { wiredCharger };
|
||
|
fts_write_reg(info, ®Add[0], 2);
|
||
|
fts_delay(10);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
info->touch_count = 0;
|
||
|
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: mode:%d [%s] %02X %02X %02X %02X\n",
|
||
|
__func__, testmode, result < 0 ? "FAIL" : "PASS",
|
||
|
info->ito_test[0], info->ito_test[1],
|
||
|
info->ito_test[2], info->ito_test[3]);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static void get_fw_ver_bin(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "ST%02X%02X%02X%02X",
|
||
|
info->ic_name_of_bin,
|
||
|
info->project_id_of_bin,
|
||
|
info->module_version_of_bin,
|
||
|
info->fw_main_version_of_bin & 0xFF);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_VER_BIN");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
char model_ver[7] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_VER_IC");
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_MODEL");
|
||
|
}
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_get_version_info(info);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "ST%02X%02X%02X%02X",
|
||
|
info->ic_name_of_ic,
|
||
|
info->project_id_of_ic,
|
||
|
info->module_version_of_ic,
|
||
|
info->fw_main_version_of_ic & 0xFF);
|
||
|
snprintf(model_ver, sizeof(model_ver), "ST%02X%02X",
|
||
|
info->ic_name_of_ic,
|
||
|
info->project_id_of_ic);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_VER_IC");
|
||
|
sec_cmd_set_cmd_result_all(sec, model_ver, strnlen(model_ver, sizeof(model_ver)), "FW_MODEL");
|
||
|
}
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_config_ver(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[20] = { 0 };
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "ST_%04X",
|
||
|
info->config_version_of_ic);
|
||
|
|
||
|
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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_threshold(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
u8 regAdd[2];
|
||
|
u8 buff[16] = { 0 };
|
||
|
u8 data[5] = { 0 };
|
||
|
u16 finger_threshold = 0;
|
||
|
int rc;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
|
||
|
|
||
|
regAdd[0] = FTS_CMD_SET_GET_TOUCH_MODE_FOR_THRESHOLD;
|
||
|
regAdd[1] = 0x00;
|
||
|
info->fts_write_reg(info, ®Add[0], 2);
|
||
|
fts_delay(50);
|
||
|
|
||
|
regAdd[0] = FTS_CMD_SET_GET_TOUCH_THRESHOLD;
|
||
|
rc = info->fts_read_reg(info, ®Add[0], 1, data, 2);
|
||
|
if (rc <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: Get threshold Read Fail!! [Data : %2X%2X]\n",
|
||
|
__func__, data[0], data[1]);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
finger_threshold = (u16)(data[0] << 8 | data[1]);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d", finger_threshold);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void module_off_master(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[3] = { 0 };
|
||
|
int ret = 0;
|
||
|
|
||
|
ret = fts_stop_device(info);
|
||
|
|
||
|
if (ret == 0)
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
else
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void module_on_master(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[3] = { 0 };
|
||
|
int ret = 0;
|
||
|
|
||
|
ret = fts_start_device(info);
|
||
|
|
||
|
if (ret == 0)
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
else
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_chip_vendor(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "STM");
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "IC_VENDOR");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
|
||
|
if (info->firmware_name)
|
||
|
memcpy(buff, info->firmware_name + 8, 9);
|
||
|
else
|
||
|
snprintf(buff, 10, "FTS");
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "IC_NAME");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_wet_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[3] = { 0 };
|
||
|
u8 data[2] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "WET_MODE");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x03;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 2, &data[0], 1);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] failed to read\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "WET_MODE");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d", data[0]);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "WET_MODE");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_x_num(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
snprintf(buff, sizeof(buff), "%d", info->ForceChannelLength);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
snprintf(buff, sizeof(buff), "%d", info->SenseChannelLength);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
int rc;
|
||
|
u32 checksum_data;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
rc = info->fts_get_sysinfo_data(info, FTS_SI_CONFIG_CHECKSUM, 4, (u8 *)&checksum_data);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: Get checksum data Read Fail!! [Data : %08X]\n",
|
||
|
__func__, checksum_data);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
fts_reinit(info, false);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%08X", checksum_data);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void check_fw_corruption(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[16] = { 0 };
|
||
|
int rc;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fw_corruption) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
rc = fts_fw_corruption_check(info);
|
||
|
if (rc == -FTS_ERROR_FW_CORRUPTION) {
|
||
|
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;
|
||
|
fts_reinit(info, false);
|
||
|
}
|
||
|
}
|
||
|
info->fw_corruption = false;
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_reference_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_read_frame(info, TYPE_BASELINE_DATA, &min, &max);
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_reference(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short val = 0;
|
||
|
int node = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
node = fts_check_index(info);
|
||
|
if (node < 0)
|
||
|
return;
|
||
|
|
||
|
val = info->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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_rawcap_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_read_frame(info, TYPE_RAW_DATA, &min, &max);
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_rawcap_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
char *all_strbuff;
|
||
|
int i, j;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
all_strbuff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 7 + 1, GFP_KERNEL);
|
||
|
if (!all_strbuff) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
fts_read_frame(info, TYPE_RAW_DATA, &min, &max);
|
||
|
|
||
|
for (j = 0; j < info->ForceChannelLength; j++) {
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
snprintf(buff, sizeof(buff), "%d,", info->pFrame[j * info->SenseChannelLength + i]);
|
||
|
strlcat(all_strbuff, buff, info->ForceChannelLength * info->SenseChannelLength * 7);
|
||
|
}
|
||
|
}
|
||
|
enter_factory_mode(info, false);
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, all_strbuff, strlen(all_strbuff));
|
||
|
input_info(true, &info->client->dev, "%s: %ld\n", __func__, strlen(all_strbuff));
|
||
|
kfree(all_strbuff);
|
||
|
}
|
||
|
|
||
|
static void run_nonsync_rawcap_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
fts_read_nonsync_frame(info, &min, &max);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void run_nonsync_rawcap_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
char *all_strbuff;
|
||
|
int i, j;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
all_strbuff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 7 + 1, GFP_KERNEL);
|
||
|
if (!all_strbuff) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// enter_factory_mode(info, true);
|
||
|
// fts_read_frame(info, TYPE_RAW_DATA, &min, &max);
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
fts_read_nonsync_frame(info, &min, &max);
|
||
|
|
||
|
for (j = 0; j < info->ForceChannelLength; j++) {
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
snprintf(buff, sizeof(buff), "%d,", info->pFrame[j * info->SenseChannelLength + i]);
|
||
|
strlcat(all_strbuff, buff, info->ForceChannelLength * info->SenseChannelLength * 7);
|
||
|
}
|
||
|
}
|
||
|
enter_factory_mode(info, false);
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, all_strbuff, strlen(all_strbuff));
|
||
|
input_info(true, &info->client->dev, "%s: %ld\n", __func__, strlen(all_strbuff));
|
||
|
kfree(all_strbuff);
|
||
|
}
|
||
|
|
||
|
static void get_rawcap(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short val = 0;
|
||
|
int node = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
node = fts_check_index(info);
|
||
|
if (node < 0)
|
||
|
return;
|
||
|
|
||
|
val = info->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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
static void get_rawcap_gap_data(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int rx_max = 0, tx_max = 0, ii;
|
||
|
|
||
|
for (ii = 0; ii < (info->SenseChannelLength * info->ForceChannelLength); ii++) {
|
||
|
/* rx(x) rawcap gap max */
|
||
|
if ((ii + 1) % (info->SenseChannelLength) != 0)
|
||
|
rx_max = max(rx_max, (int)abs(info->pFrame[ii + 1] - info->pFrame[ii]));
|
||
|
|
||
|
/* tx(y) rawcap gap max */
|
||
|
if (ii < (info->ForceChannelLength - 1) * info->SenseChannelLength)
|
||
|
tx_max = max(tx_max, (int)abs(info->pFrame[ii + info->SenseChannelLength] - info->pFrame[ii]));
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: rx max:%d, tx max:%d\n", __func__, rx_max, tx_max);
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", 0, rx_max);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, SEC_CMD_STR_LEN, "RAW_DATA_GAP_RX");
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", 0, tx_max);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, SEC_CMD_STR_LEN, "RAW_DATA_GAP_TX");
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void run_lp_single_ended_rawcap_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regaddr[4] = { 0xA4, 0x0A, 0x01, 0x00 };
|
||
|
int ret;
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* Request to Prepare single ended raw data from flash */
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regaddr, 4, 0);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout, ret: %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
// run_nonsync_rawcap_read(sec);
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
fts_read_nonsync_frame(info, &min, &max);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MUTUAL_RAW");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MUTUAL_RAW");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
input_info(true, &info->client->dev, "%s: fail : %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void run_lp_single_ended_rawcap_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regaddr[4] = { 0xA4, 0x0A, 0x01, 0x00 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
fts_delay(30);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* Request to Prepare single ended raw data from flash */
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regaddr, 4, 0);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout, ret: %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
// run_rawcap_read_all(sec);
|
||
|
run_nonsync_rawcap_read_all(sec);
|
||
|
|
||
|
// enter_factory_mode(info, false);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
// enter_factory_mode(info, false);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
}
|
||
|
|
||
|
// Micro Short Test
|
||
|
static void run_low_frequency_rawcap_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0xA4, 0x04, 0x00, 0xC0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
fts_delay(30);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* Request to Prepare Hight Frequency(ITO) raw data from flash */
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regAdd, 4, 30);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout, ret: %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
run_nonsync_rawcap_read(sec);
|
||
|
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
}
|
||
|
|
||
|
static void run_low_frequency_rawcap_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0xA4, 0x04, 0x00, 0xC0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
fts_delay(30);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* Request to Prepare Hight Frequency(ITO) raw data from flash */
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regAdd, 4, 30);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout, ret: %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
// run_rawcap_read_all(sec);
|
||
|
run_nonsync_rawcap_read_all(sec);
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
}
|
||
|
|
||
|
static void run_high_frequency_rawcap_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0xA4, 0x04, 0xFF, 0x01 };
|
||
|
int ret;
|
||
|
int i, j;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
fts_delay(30);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* Request to Prepare Hight Frequency(ITO) raw data from flash */
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regAdd, 4, 100);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout, ret: %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
run_nonsync_rawcap_read(sec);
|
||
|
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
pr_info("sec_input: %s - correlation\n", __func__);
|
||
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
||
|
pr_info("sec_input: [%2d] ", i);
|
||
|
for (j = 0; j < info->SenseChannelLength; j++)
|
||
|
pr_cont("%d, ", info->pFrame[(i * info->SenseChannelLength) + j]);
|
||
|
pr_cont("\n");
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
}
|
||
|
|
||
|
static void run_high_frequency_rawcap_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[4] = { 0xA4, 0x04, 0xFF, 0x01 };
|
||
|
int ret;
|
||
|
int i, j;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
fts_delay(30);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
/* Request to Prepare Hight Frequency(ITO) raw data from flash */
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, regAdd, 4, 100);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout, ret: %d\n", __func__, ret);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
// run_rawcap_read_all(sec);
|
||
|
run_nonsync_rawcap_read_all(sec);
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
pr_info("sec_input: %s - correlation\n", __func__);
|
||
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
||
|
pr_info("sec_input: [%2d] ", i);
|
||
|
for (j = 0; j < info->SenseChannelLength; j++)
|
||
|
pr_cont("%d, ", info->pFrame[(i * info->SenseChannelLength) + j]);
|
||
|
pr_cont("\n");
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
}
|
||
|
|
||
|
static void run_delta_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_prox_intensity_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
u8 reg[2];
|
||
|
u8 thd_data[4];
|
||
|
u8 sum_data[4];
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memset(thd_data, 0x00, 4);
|
||
|
memset(sum_data, 0x00, 4);
|
||
|
|
||
|
/* Threshold */
|
||
|
reg[0] = 0xC7;
|
||
|
reg[1] = 0x0C;
|
||
|
ret = info->fts_read_reg(info, ®[0], 2, &thd_data[0], 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to read thd_data\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Sum */
|
||
|
reg[0] = 0xC7;
|
||
|
reg[1] = 0x0D;
|
||
|
ret = info->fts_read_reg(info, ®[0], 2, &sum_data[0], 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to read sum_data\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "SUM_X:%d THD_X:%d SUM_Y:%d THD_Y:%d",
|
||
|
(sum_data[0] << 8) + sum_data[1], (sum_data[2] << 8) + sum_data[3],
|
||
|
(thd_data[0] << 8) + thd_data[1], (thd_data[2] << 8) + thd_data[3]);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
}
|
||
|
|
||
|
static void get_strength_all_data(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
char *all_strbuff;
|
||
|
int i, j;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
all_strbuff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 7 + 1, GFP_KERNEL);
|
||
|
if (!all_strbuff) {
|
||
|
input_err(true, &info->client->dev, "%s: alloc failed\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
|
||
|
|
||
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
||
|
for (j = 0; j < info->SenseChannelLength; j++) {
|
||
|
snprintf(buff, sizeof(buff), "%d,", info->pFrame[(i * info->SenseChannelLength) + j]);
|
||
|
strlcat(all_strbuff, buff, info->ForceChannelLength * info->SenseChannelLength * 7);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, all_strbuff, strlen(all_strbuff));
|
||
|
input_info(true, &info->client->dev, "%s: %ld\n", __func__, strlen(all_strbuff));
|
||
|
kfree(all_strbuff);
|
||
|
}
|
||
|
|
||
|
static void get_delta(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short val = 0;
|
||
|
int node = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
node = fts_check_index(info);
|
||
|
if (node < 0)
|
||
|
return;
|
||
|
|
||
|
val = info->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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
int fts_get_hf_data(struct fts_ts_info *info)
|
||
|
{
|
||
|
u8 regAdd[4] = { 0 };
|
||
|
int ret;
|
||
|
short min = 0x7FFF;
|
||
|
short max = 0x8000;
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x04;
|
||
|
regAdd[2] = 0xFF;
|
||
|
regAdd[3] = 0x01;
|
||
|
ret = fts_fw_wait_for_echo_event(info, ®Add[0], 4, 100);
|
||
|
if (ret < 0)
|
||
|
goto out;
|
||
|
|
||
|
ret = fts_read_frame(info, TYPE_RAW_DATA, &min, &max);
|
||
|
if (ret < 0)
|
||
|
input_err(true, &info->client->dev, "%s: failed to get rawdata\n", __func__);
|
||
|
|
||
|
out:
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
fts_set_cover_type(info, info->flip_enable);
|
||
|
|
||
|
fts_delay(10);
|
||
|
|
||
|
if (info->charger_mode) {
|
||
|
fts_wirelesscharger_mode(info);
|
||
|
fts_delay(10);
|
||
|
}
|
||
|
|
||
|
if (!info->flip_enable)
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
else
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void run_rawdata_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
#ifdef CONFIG_TOUCHSCREEN_DUAL_FOLDABLE
|
||
|
input_raw_data_clear(MAIN_TOUCH);
|
||
|
#endif
|
||
|
info->rawdata_read_lock = true;
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev,
|
||
|
"%s: start (noise:%d, wet:%d, tc:%d, folding:%s)##\n",
|
||
|
__func__, info->touch_noise_status, info->wet_mode,
|
||
|
info->touch_count, info->flip_status_current ? "close" : "open");
|
||
|
|
||
|
run_rawcap_read(sec);
|
||
|
run_self_raw_read(sec);
|
||
|
fts_checking_miscal(info);
|
||
|
run_cx_data_read(sec);
|
||
|
run_ix_data_read(sec);
|
||
|
fts_panel_ito_test(info, OPEN_SHORT_CRACK_TEST);
|
||
|
fts_get_hf_data(info);
|
||
|
run_mutual_jitter(sec);
|
||
|
|
||
|
info->rawdata_read_lock = false;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
void fts_run_rawdata_read_all(struct fts_ts_info *info)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
|
||
|
run_rawdata_read_all(sec);
|
||
|
}
|
||
|
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
static void get_pat_information(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[50] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
#ifdef CONFIG_SEC_FACTORY
|
||
|
if (info->factory_position == 1) {
|
||
|
sec_tclm_initialize(info->tdata);
|
||
|
fts_tclm_data_read(info->client, SEC_TCLM_NVM_ALL_DATA);
|
||
|
}
|
||
|
#endif
|
||
|
/* fixed tune version will be saved at excute autotune */
|
||
|
snprintf(buff, sizeof(buff), "C%02XT%04X.%4s%s%c%d%c%d%c%d",
|
||
|
info->tdata->nvdata.cal_count, info->tdata->nvdata.tune_fix_ver,
|
||
|
info->tdata->tclm_string[info->tdata->nvdata.cal_position].f_name,
|
||
|
(info->tdata->tclm_level == TCLM_LEVEL_LOCKDOWN) ? ".L " : " ",
|
||
|
info->tdata->cal_pos_hist_last3[0], info->tdata->cal_pos_hist_last3[1],
|
||
|
info->tdata->cal_pos_hist_last3[2], info->tdata->cal_pos_hist_last3[3],
|
||
|
info->tdata->cal_pos_hist_last3[4], info->tdata->cal_pos_hist_last3[5]);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
info->tdata->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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void fts_read_ix_data(struct fts_ts_info *info, bool allnode)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int rc;
|
||
|
u16 max_tx_ix_sum = 0;
|
||
|
u16 min_tx_ix_sum = 0xFFFF;
|
||
|
u16 max_rx_ix_sum = 0;
|
||
|
u16 min_rx_ix_sum = 0xFFFF;
|
||
|
u8 *data;
|
||
|
u8 regAdd[FTS_EVENT_SIZE];
|
||
|
u8 dataID;
|
||
|
u16 force_ix_data[100];
|
||
|
u16 sense_ix_data[100];
|
||
|
|
||
|
int buff_size, j;
|
||
|
char *mbuff = NULL;
|
||
|
int num, n, a, fzero;
|
||
|
char cnum;
|
||
|
int i = 0;
|
||
|
u16 comp_start_tx_addr, comp_start_rx_addr;
|
||
|
unsigned int rx_num, tx_num;
|
||
|
|
||
|
data = kzalloc((info->ForceChannelLength + info->SenseChannelLength) * 2 + 1, GFP_KERNEL);
|
||
|
if (!data)
|
||
|
return;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true); // Clear FIFO
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
// Request compensation data type
|
||
|
dataID = 0x52;
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = dataID; // SS - CX total
|
||
|
rc = fts_fw_wait_for_echo_event(info, ®Add[0], 3, 0);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to request data\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
// Read Header
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
rc = info->fts_read_reg(info, ®Add[0], 3, &data[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to read header\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
if ((data[0] != 0xA5) && (data[1] != dataID)) {
|
||
|
input_err(true, &info->client->dev, "%s: header mismatch\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
tx_num = data[4];
|
||
|
rx_num = data[5];
|
||
|
|
||
|
/* Read TX IX data */
|
||
|
comp_start_tx_addr = (u16)FTS_COMP_DATA_HEADER_SIZE;
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)(comp_start_tx_addr >> 8);
|
||
|
regAdd[2] = (u8)(comp_start_tx_addr & 0xFF);
|
||
|
rc = info->fts_read_reg(info, ®Add[0], 3, &data[0], tx_num * 2);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to read TX IX data\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < tx_num; i++) {
|
||
|
force_ix_data[i] = data[2 * i] | data[2 * i + 1] << 8;
|
||
|
|
||
|
if (max_tx_ix_sum < force_ix_data[i])
|
||
|
max_tx_ix_sum = force_ix_data[i];
|
||
|
if (min_tx_ix_sum > force_ix_data[i])
|
||
|
min_tx_ix_sum = force_ix_data[i];
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Read RX IX data */
|
||
|
comp_start_rx_addr = (u16)(FTS_COMP_DATA_HEADER_SIZE + (tx_num * 2));
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)(comp_start_rx_addr >> 8);
|
||
|
regAdd[2] = (u8)(comp_start_rx_addr & 0xFF);
|
||
|
rc = info->fts_read_reg(info, ®Add[0], 3, &data[0], rx_num * 2);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to read RX IX\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < rx_num; i++) {
|
||
|
sense_ix_data[i] = data[2 * i] | data[2 * i + 1] << 8;
|
||
|
|
||
|
if (max_rx_ix_sum < sense_ix_data[i])
|
||
|
max_rx_ix_sum = sense_ix_data[i];
|
||
|
if (min_rx_ix_sum > sense_ix_data[i])
|
||
|
min_rx_ix_sum = sense_ix_data[i];
|
||
|
}
|
||
|
|
||
|
fts_print_channel(info, force_ix_data, sense_ix_data);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: MIN_TX_IX_SUM : %d MAX_TX_IX_SUM : %d\n",
|
||
|
__func__, min_tx_ix_sum, max_tx_ix_sum);
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: MIN_RX_IX_SUM : %d MAX_RX_IX_SUM : %d\n",
|
||
|
__func__, min_rx_ix_sum, max_rx_ix_sum);
|
||
|
|
||
|
if (allnode == true) {
|
||
|
buff_size = (info->ForceChannelLength + info->SenseChannelLength + 2) * 5;
|
||
|
mbuff = kzalloc(buff_size, GFP_KERNEL);
|
||
|
}
|
||
|
if (mbuff != NULL) {
|
||
|
char *pBuf = mbuff;
|
||
|
|
||
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
||
|
num = force_ix_data[i];
|
||
|
n = 100000;
|
||
|
fzero = 0;
|
||
|
for (j = 5; j > 0; j--) {
|
||
|
n = n / 10;
|
||
|
a = num / n;
|
||
|
if (a)
|
||
|
fzero = 1;
|
||
|
cnum = a + '0';
|
||
|
num = num - a*n;
|
||
|
if (fzero)
|
||
|
*pBuf++ = cnum;
|
||
|
}
|
||
|
if (!fzero)
|
||
|
*pBuf++ = '0';
|
||
|
*pBuf++ = ',';
|
||
|
}
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
num = sense_ix_data[i];
|
||
|
n = 100000;
|
||
|
fzero = 0;
|
||
|
for (j = 5; j > 0; j--) {
|
||
|
n = n / 10;
|
||
|
a = num / n;
|
||
|
if (a)
|
||
|
fzero = 1;
|
||
|
cnum = a + '0';
|
||
|
num = num - a * n;
|
||
|
if (fzero)
|
||
|
*pBuf++ = cnum;
|
||
|
}
|
||
|
if (!fzero)
|
||
|
*pBuf++ = '0';
|
||
|
if (i < (info->SenseChannelLength - 1))
|
||
|
*pBuf++ = ',';
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, mbuff, buff_size);
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
kfree(mbuff);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (allnode == true) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "%d,%d,%d,%d",
|
||
|
min_tx_ix_sum, max_tx_ix_sum, min_rx_ix_sum, max_rx_ix_sum);
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
kfree(data);
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
char ret_buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", min_rx_ix_sum, max_rx_ix_sum);
|
||
|
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "IX_DATA_X");
|
||
|
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", min_tx_ix_sum, max_tx_ix_sum);
|
||
|
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "IX_DATA_Y");
|
||
|
}
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_ix_data_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
fts_read_ix_data(info, false);
|
||
|
}
|
||
|
|
||
|
static void run_ix_data_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
fts_read_ix_data(info, true);
|
||
|
enter_factory_mode(info, false);
|
||
|
}
|
||
|
|
||
|
static void fts_read_self_raw_frame(struct fts_ts_info *info, bool allnode)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
struct FTS_SyncFrameHeader *pSyncFrameHeader;
|
||
|
u8 regAdd[FTS_EVENT_SIZE] = {0};
|
||
|
u8 *data;
|
||
|
s16 self_force_raw_data[100];
|
||
|
s16 self_sense_raw_data[100];
|
||
|
int Offset = 0;
|
||
|
u8 count = 0;
|
||
|
int i;
|
||
|
int ret;
|
||
|
int totalbytes;
|
||
|
int retry = 10;
|
||
|
s16 min_tx_self_raw_data = S16_MAX;
|
||
|
s16 max_tx_self_raw_data = S16_MIN;
|
||
|
s16 min_rx_self_raw_data = S16_MAX;
|
||
|
s16 max_rx_self_raw_data = S16_MIN;
|
||
|
|
||
|
data = kzalloc((info->ForceChannelLength + info->SenseChannelLength) * 2 + 1, GFP_KERNEL);
|
||
|
if (!data)
|
||
|
return;
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
// Request Data Type
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = TYPE_RAW_DATA;
|
||
|
info->fts_write_reg(info, ®Add[0], 3);
|
||
|
|
||
|
do {
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &data[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
pSyncFrameHeader = (struct FTS_SyncFrameHeader *) &data[0];
|
||
|
|
||
|
if ((pSyncFrameHeader->header == 0xA5) && (pSyncFrameHeader->host_data_mem_id == TYPE_RAW_DATA))
|
||
|
break;
|
||
|
|
||
|
fts_delay(100);
|
||
|
} while (retry--);
|
||
|
|
||
|
if (retry == 0) {
|
||
|
input_err(true, &info->client->dev, "%s: didn't match header or id. header = %02X, id = %02X\n",
|
||
|
__func__, pSyncFrameHeader->header, pSyncFrameHeader->host_data_mem_id);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
Offset = FTS_COMP_DATA_HEADER_SIZE + pSyncFrameHeader->dbg_frm_len +
|
||
|
(pSyncFrameHeader->ms_force_len * pSyncFrameHeader->ms_sense_len * 2);
|
||
|
|
||
|
totalbytes = (pSyncFrameHeader->ss_force_len + pSyncFrameHeader->ss_sense_len) * 2;
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)(Offset >> 8);
|
||
|
regAdd[2] = (u8)(Offset & 0xFF);
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &data[0], totalbytes);
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
Offset = 0;
|
||
|
for (count = 0; count < (info->ForceChannelLength); count++) {
|
||
|
self_force_raw_data[count] = (s16)(data[count * 2 + Offset] + (data[count * 2 + 1 + Offset] << 8));
|
||
|
|
||
|
if (max_tx_self_raw_data < self_force_raw_data[count])
|
||
|
max_tx_self_raw_data = self_force_raw_data[count];
|
||
|
if (min_tx_self_raw_data > self_force_raw_data[count])
|
||
|
min_tx_self_raw_data = self_force_raw_data[count];
|
||
|
}
|
||
|
|
||
|
Offset = (info->ForceChannelLength * 2);
|
||
|
for (count = 0; count < info->SenseChannelLength; count++) {
|
||
|
self_sense_raw_data[count] = (s16)(data[count * 2 + Offset] + (data[count * 2 + 1 + Offset] << 8));
|
||
|
|
||
|
if (max_rx_self_raw_data < self_sense_raw_data[count])
|
||
|
max_rx_self_raw_data = self_sense_raw_data[count];
|
||
|
if (min_rx_self_raw_data > self_sense_raw_data[count])
|
||
|
min_rx_self_raw_data = self_sense_raw_data[count];
|
||
|
}
|
||
|
|
||
|
fts_print_channel(info, self_force_raw_data, self_sense_raw_data);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: MIN_TX_SELF_RAW: %d MAX_TX_SELF_RAW : %d\n",
|
||
|
__func__, (s16)min_tx_self_raw_data, (s16)max_tx_self_raw_data);
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: MIN_RX_SELF_RAW : %d MIN_RX_SELF_RAW : %d\n",
|
||
|
__func__, (s16)min_rx_self_raw_data, (s16)max_rx_self_raw_data);
|
||
|
|
||
|
if (allnode == true) {
|
||
|
char *mbuff;
|
||
|
char temp[10] = { 0 };
|
||
|
|
||
|
mbuff = kzalloc((info->ForceChannelLength + info->SenseChannelLength + 2) * 10, GFP_KERNEL);
|
||
|
if (!mbuff)
|
||
|
goto out;
|
||
|
for (i = 0; i < (info->ForceChannelLength); i++) {
|
||
|
snprintf(temp, sizeof(temp), "%d,", (s16)self_force_raw_data[i]);
|
||
|
strlcat(mbuff, temp, sizeof(mbuff));
|
||
|
}
|
||
|
for (i = 0; i < (info->SenseChannelLength); i++) {
|
||
|
snprintf(temp, sizeof(temp), "%d,", (s16)self_sense_raw_data[i]);
|
||
|
strlcat(mbuff, temp, sizeof(mbuff));
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, mbuff, sizeof(mbuff));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
kfree(mbuff);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d,%d,%d,%d",
|
||
|
(s16)min_tx_self_raw_data, (s16)max_tx_self_raw_data,
|
||
|
(s16)min_rx_self_raw_data, (s16)max_rx_self_raw_data);
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
out:
|
||
|
kfree(data);
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
char ret_buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", (s16)min_rx_self_raw_data, (s16)max_rx_self_raw_data);
|
||
|
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "SELF_RAW_DATA_X");
|
||
|
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", (s16)min_tx_self_raw_data, (s16)max_tx_self_raw_data);
|
||
|
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "SELF_RAW_DATA_Y");
|
||
|
}
|
||
|
sec_cmd_set_cmd_result(sec, &buff[0], strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_self_raw_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
fts_read_self_raw_frame(info, false);
|
||
|
}
|
||
|
|
||
|
static void run_self_raw_read_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
fts_read_self_raw_frame(info, true);
|
||
|
enter_factory_mode(info, false);
|
||
|
}
|
||
|
|
||
|
static void run_factory_miscalibration(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN];
|
||
|
char data[FTS_EVENT_SIZE];
|
||
|
char echo;
|
||
|
int ret;
|
||
|
int retry = 200;
|
||
|
short min, max;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
memset(data, 0x00, sizeof(data));
|
||
|
memset(buff, 0x00, sizeof(buff));
|
||
|
|
||
|
data[0] = 0xC7;
|
||
|
data[1] = 0x02;
|
||
|
|
||
|
ret = info->fts_write_reg(info, data, 2);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: write failed: %d\n", __func__, ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/* maximum timeout 2sec ? */
|
||
|
while (retry-- >= 0) {
|
||
|
memset(data, 0x00, sizeof(data));
|
||
|
echo = FTS_READ_ONE_EVENT;
|
||
|
ret = info->fts_read_reg(info, &echo, 1, data, FTS_EVENT_SIZE);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed: %d\n", __func__, ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3],
|
||
|
data[4], data[5], data[6], data[7]);
|
||
|
fts_delay(10);
|
||
|
|
||
|
if (data[0] == 0x03 || data[0] == 0xF3) {
|
||
|
max = data[3] << 8 | data[2];
|
||
|
min = data[5] << 8 | data[4];
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
if (retry == 0)
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MIS_CAL");
|
||
|
} else {
|
||
|
if (data[0] == 0x03) {
|
||
|
snprintf(buff, sizeof(buff), "OK,%d,%d", min, max);
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "NG,%d,%d", min, max);
|
||
|
}
|
||
|
}
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
fts_reinit(info, false);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
return;
|
||
|
|
||
|
error:
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
fts_reinit(info, false);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
}
|
||
|
|
||
|
static void run_miscalibration(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN];
|
||
|
char data[FTS_EVENT_SIZE];
|
||
|
char echo;
|
||
|
int ret;
|
||
|
int retry = 200;
|
||
|
short min, max;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
memset(data, 0x00, sizeof(data));
|
||
|
memset(buff, 0x00, sizeof(buff));
|
||
|
|
||
|
data[0] = 0xA4;
|
||
|
data[1] = 0x0B;
|
||
|
data[2] = 0x00;
|
||
|
data[3] = 0xC0;
|
||
|
|
||
|
ret = info->fts_write_reg(info, data, 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: write failed: %d\n", __func__, ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/* maximum timeout 2sec ? */
|
||
|
while (retry-- >= 0) {
|
||
|
memset(data, 0x00, sizeof(data));
|
||
|
echo = FTS_READ_ONE_EVENT;
|
||
|
ret = info->fts_read_reg(info, &echo, 1, data, FTS_EVENT_SIZE);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: read failed: %d\n", __func__, ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3],
|
||
|
data[4], data[5], data[6], data[7]);
|
||
|
fts_delay(10);
|
||
|
|
||
|
if (data[0] == 0x03 || data[0] == 0xF3) {
|
||
|
max = data[3] << 8 | data[2];
|
||
|
min = data[5] << 8 | data[4];
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
if (retry == 0)
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if (data[0] == 0x03) {
|
||
|
snprintf(buff, sizeof(buff), "OK,%d,%d", min, max);
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "NG,%d,%d", min, max);
|
||
|
}
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
fts_reinit(info, false);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
return;
|
||
|
error:
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
fts_reinit(info, false);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
}
|
||
|
|
||
|
int fts_panel_test_result(struct fts_ts_info *info, int type)
|
||
|
{
|
||
|
u8 data[FTS_EVENT_SIZE];
|
||
|
u8 cmd = FTS_READ_ONE_EVENT;
|
||
|
uint8_t regAdd[4] = { 0 };
|
||
|
bool matched = false;
|
||
|
int retry = 0;
|
||
|
int i = 0;
|
||
|
int result = 0;
|
||
|
short temp_min = 32767, temp_max = -32768;
|
||
|
|
||
|
bool cheked_short_to_gnd = false;
|
||
|
bool cheked_short_to_vdd = false;
|
||
|
bool cheked_short = false;
|
||
|
bool cheked_open = false;
|
||
|
char tempv[25] = {0};
|
||
|
char temph[30] = {0};
|
||
|
struct sec_cmd_data *sec = &info->sec;
|
||
|
|
||
|
char buff[SEC_CMD_STR_LEN] = {0};
|
||
|
u8 *result_buff = NULL;
|
||
|
int size = 4095;
|
||
|
|
||
|
result_buff = kzalloc(size, GFP_KERNEL);
|
||
|
if (!result_buff) {
|
||
|
input_err(true, &info->client->dev, "%s: result_buff kzalloc fail!\n", __func__);
|
||
|
goto alloc_fail;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x04;
|
||
|
regAdd[2] = 0xFC;
|
||
|
regAdd[3] = 0x09;
|
||
|
|
||
|
info->fts_write_reg(info, ®Add[0], 4);
|
||
|
fts_delay(100);
|
||
|
|
||
|
memset(info->ito_test, 0x0, 4);
|
||
|
|
||
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
||
|
while (info->fts_read_reg(info, &cmd, 1, (u8 *)data, FTS_EVENT_SIZE)) {
|
||
|
memset(tempv, 0x00, 25);
|
||
|
memset(temph, 0x00, 30);
|
||
|
if ((data[0] == FTS_EVENT_STATUS_REPORT) && (data[1] == 0x01)) {
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
if (data[i + 2] != regAdd[i]) {
|
||
|
matched = false;
|
||
|
break;
|
||
|
}
|
||
|
matched = true;
|
||
|
}
|
||
|
if (matched == true)
|
||
|
break;
|
||
|
|
||
|
} else if (data[0] == FTS_EVENT_ERROR_REPORT) {
|
||
|
info->ito_test[0] = data[0];
|
||
|
info->ito_test[1] = data[1];
|
||
|
info->ito_test[2] = data[2];
|
||
|
info->ito_test[3] = 0x00;
|
||
|
|
||
|
switch (data[1]) {
|
||
|
case ITO_FORCE_SHRT_GND:
|
||
|
case ITO_SENSE_SHRT_GND:
|
||
|
input_info(true, &info->client->dev, "%s: TX/RX_SHORT_TO_GND:%cX[%d]\n",
|
||
|
__func__, data[1] == ITO_FORCE_SHRT_VDD ? 'T' : 'R', data[2]);
|
||
|
if (type != SHORT_TEST)
|
||
|
break;
|
||
|
if (!cheked_short_to_gnd) {
|
||
|
snprintf(temph, 30, "TX/RX_SHORT_TO_GND:");
|
||
|
strlcat(result_buff, temph, size);
|
||
|
cheked_short_to_gnd = true;
|
||
|
}
|
||
|
snprintf(tempv, sizeof(tempv), "%c%d,", data[1] == ITO_FORCE_SHRT_GND ? 'T' : 'R', data[2]);
|
||
|
strlcat(result_buff, tempv, size);
|
||
|
result = ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
case ITO_FORCE_SHRT_VDD:
|
||
|
case ITO_SENSE_SHRT_VDD:
|
||
|
input_info(true, &info->client->dev, "%s: TX/RX_SHORT_TO_VDD:%cX[%d]\n",
|
||
|
__func__, data[1] == ITO_FORCE_SHRT_VDD ? 'T' : 'R', data[2]);
|
||
|
if (type != SHORT_TEST)
|
||
|
break;
|
||
|
if (!cheked_short_to_vdd) {
|
||
|
snprintf(temph, 30, "TX/RX_SHORT_TO_VDD:");
|
||
|
strlcat(result_buff, temph, size);
|
||
|
cheked_short_to_vdd = true;
|
||
|
}
|
||
|
snprintf(tempv, sizeof(tempv), "%c%d,", data[1] == ITO_FORCE_SHRT_VDD ? 'T' : 'R', data[2]);
|
||
|
strlcat(result_buff, tempv, size);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
case ITO_FORCE_SHRT_FORCE:
|
||
|
case ITO_SENSE_SHRT_SENSE:
|
||
|
input_info(true, &info->client->dev, "%s: TX/RX_SHORT:%cX[%d]\n",
|
||
|
__func__, data[1] == ITO_FORCE_SHRT_FORCE ? 'T' : 'R', data[2]);
|
||
|
if (type != SHORT_TEST)
|
||
|
break;
|
||
|
if (!cheked_short) {
|
||
|
snprintf(temph, 30, "TX/RX_SHORT:");
|
||
|
strlcat(result_buff, temph, size);
|
||
|
cheked_short = true;
|
||
|
}
|
||
|
snprintf(tempv, sizeof(tempv), "%c%d,", data[1] == ITO_FORCE_SHRT_FORCE ? 'T' : 'R', data[2]);
|
||
|
strlcat(result_buff, tempv, size);
|
||
|
result = -ITO_FAIL_SHORT;
|
||
|
break;
|
||
|
case ITO_FORCE_OPEN:
|
||
|
case ITO_SENSE_OPEN:
|
||
|
input_info(true, &info->client->dev, "%s: TX/RX_OPEN:%cX[%d]\n",
|
||
|
__func__, data[1] == ITO_FORCE_OPEN ? 'T' : 'R', data[2]);
|
||
|
if (type != OPEN_TEST)
|
||
|
break;
|
||
|
if (!cheked_open) {
|
||
|
snprintf(temph, 30, "TX/RX_OPEN:");
|
||
|
strlcat(result_buff, temph, size);
|
||
|
cheked_open = true;
|
||
|
}
|
||
|
snprintf(tempv, sizeof(tempv), "%c%d,", data[1] == ITO_FORCE_OPEN ? 'T' : 'R', data[2]);
|
||
|
strlcat(result_buff, tempv, size);
|
||
|
result = -ITO_FAIL_OPEN;
|
||
|
break;
|
||
|
default:
|
||
|
input_info(true, &info->client->dev, "%s: unknown event %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||
|
__func__, data[0], data[1], data[2], data[3],
|
||
|
data[4], data[5], data[6], data[7]);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (retry++ > 50) {
|
||
|
input_err(true, &info->client->dev, "%s: Time over - wait for result of ITO test\n", __func__);
|
||
|
goto test_fail;
|
||
|
}
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
|
||
|
/* read rawdata */
|
||
|
// fts_read_frame(info, TYPE_RAW_DATA, &temp_min, &temp_max);
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
fts_read_nonsync_frame(info, &temp_min, &temp_max);
|
||
|
|
||
|
if (type == OPEN_TEST && result == -ITO_FAIL_OPEN) {
|
||
|
snprintf(result_buff, sizeof(result_buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, result_buff, strnlen(result_buff, sizeof(result_buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
} else if (type == SHORT_TEST && result == -ITO_FAIL_SHORT) {
|
||
|
snprintf(result_buff, sizeof(result_buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, result_buff, strnlen(result_buff, sizeof(result_buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
} else {
|
||
|
snprintf(result_buff, sizeof(result_buff), "OK");
|
||
|
sec_cmd_set_cmd_result(sec, result_buff, strnlen(result_buff, sizeof(result_buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, result_buff);
|
||
|
kfree(result_buff);
|
||
|
|
||
|
return result;
|
||
|
|
||
|
test_fail:
|
||
|
kfree(result_buff);
|
||
|
alloc_fail:
|
||
|
snprintf(buff, 30, "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
return -ITO_FAIL;
|
||
|
}
|
||
|
|
||
|
static void run_trx_short_test(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int result = 0;
|
||
|
int type = 0;
|
||
|
char test[32];
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is lp mode\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: %s: seperate cm1 test open / short test result\n", __func__, buff);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%s", "CONT");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 1) {
|
||
|
type = OPEN_TEST;
|
||
|
} else if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 2) {
|
||
|
type = SHORT_TEST;
|
||
|
} else if (sec->cmd_param[0] > 1) {
|
||
|
u8 result_buff[10];
|
||
|
|
||
|
snprintf(result_buff, sizeof(result_buff), "NA");
|
||
|
sec_cmd_set_cmd_result(sec, result_buff, strnlen(result_buff, sizeof(result_buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s : not supported test case\n", __func__);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s : CM%d factory_position[%d]\n",
|
||
|
__func__, sec->cmd_param[0], info->factory_position);
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
result = fts_panel_test_result(info, type);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
/* reinit */
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_reinit(info, false);
|
||
|
|
||
|
info->touch_count = 0;
|
||
|
|
||
|
if (sec->cmd_param[1])
|
||
|
snprintf(test, sizeof(test), "TEST=%d,%d", sec->cmd_param[0], sec->cmd_param[1]);
|
||
|
else
|
||
|
snprintf(test, sizeof(test), "TEST=%d", sec->cmd_param[0]);
|
||
|
|
||
|
if (result == 0)
|
||
|
sec_cmd_send_event_to_user(sec, test, "RESULT=PASS");
|
||
|
else
|
||
|
sec_cmd_send_event_to_user(sec, test, "RESULT=FAIL");
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s : test done\n", __func__);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
static void check_connection(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = fts_panel_ito_test(info, OPEN_TEST);
|
||
|
if (ret == 0)
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
else
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_cx_data(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
short val = 0;
|
||
|
int node = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
node = fts_check_index(info);
|
||
|
if (node < 0)
|
||
|
return;
|
||
|
|
||
|
if (info->cx_data)
|
||
|
val = info->cx_data[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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
}
|
||
|
|
||
|
static int read_ms_cx_data(struct fts_ts_info *info, u8 *cx_min, u8 *cx_max)
|
||
|
{
|
||
|
u8 *rdata;
|
||
|
u8 regAdd[FTS_EVENT_SIZE] = { 0 };
|
||
|
u8 dataID;
|
||
|
u16 comp_start_addr;
|
||
|
int txnum, rxnum, i, j, ret = 0;
|
||
|
u8 *pStr = NULL;
|
||
|
u8 pTmp[16] = { 0 };
|
||
|
|
||
|
pStr = kzalloc(7 * (info->SenseChannelLength + 1), GFP_KERNEL);
|
||
|
if (pStr == NULL)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
rdata = kzalloc(info->ForceChannelLength * info->SenseChannelLength, GFP_KERNEL);
|
||
|
if (!rdata)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true); // Clear FIFO
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
fts_delay(20);
|
||
|
|
||
|
// Request compensation data type
|
||
|
dataID = 0x11; // MS - LP
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = dataID;
|
||
|
ret = fts_fw_wait_for_echo_event(info, ®Add[0], 3, 0);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to request data\n", __func__);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
// Read Header
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &rdata[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read header\n", __func__);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
if ((rdata[0] != 0xA5) && (rdata[1] != dataID)) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read signature data of header.\n", __func__);
|
||
|
ret = -EIO;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
txnum = rdata[4];
|
||
|
rxnum = rdata[5];
|
||
|
|
||
|
comp_start_addr = (u16)FTS_COMP_DATA_HEADER_SIZE;
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)(comp_start_addr >> 8);
|
||
|
regAdd[2] = (u8)(comp_start_addr & 0xFF);
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &rdata[0], txnum * rxnum);
|
||
|
if (ret < 0) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read data\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
*cx_min = *cx_max = rdata[0];
|
||
|
for (j = 0; j < info->ForceChannelLength; j++) {
|
||
|
memset(pStr, 0x0, 7 * (info->SenseChannelLength + 1));
|
||
|
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
|
||
|
strlcat(pStr, pTmp, 7 * (info->SenseChannelLength + 1));
|
||
|
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
snprintf(pTmp, sizeof(pTmp), "%3d", rdata[j * info->SenseChannelLength + i]);
|
||
|
strlcat(pStr, pTmp, 7 * (info->SenseChannelLength + 1));
|
||
|
*cx_min = min(*cx_min, rdata[j * info->SenseChannelLength + i]);
|
||
|
*cx_max = max(*cx_max, rdata[j * info->SenseChannelLength + i]);
|
||
|
}
|
||
|
input_raw_info(true, &info->client->dev, "%s\n", pStr);
|
||
|
}
|
||
|
input_raw_info(true, &info->client->dev, "cx min:%d, cx max:%d\n", *cx_min, *cx_max);
|
||
|
|
||
|
if (info->cx_data)
|
||
|
memcpy(&info->cx_data[0], &rdata[0], info->ForceChannelLength * info->SenseChannelLength);
|
||
|
|
||
|
out:
|
||
|
kfree(rdata);
|
||
|
kfree(pStr);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#define NORMAL_CX2 0 /* single driving */
|
||
|
#define ACTIVE_CX2 1 /* multi driving */
|
||
|
|
||
|
static int read_ms_cx2_data(struct fts_ts_info *info, u8 active, s8 *cx_min, s8 *cx_max)
|
||
|
{
|
||
|
s8 *rdata = NULL;
|
||
|
u8 cdata[FTS_COMP_DATA_HEADER_SIZE];
|
||
|
u8 regAdd[FTS_EVENT_SIZE] = { 0 };
|
||
|
u8 dataID = 0;
|
||
|
u16 comp_start_addr;
|
||
|
int txnum, rxnum, i, j, ret = 0;
|
||
|
u8 *pStr = NULL;
|
||
|
u8 pTmp[16] = { 0 };
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true); // Clear FIFO
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
fts_delay(20);
|
||
|
|
||
|
// Request compensation data type
|
||
|
if (active == NORMAL_CX2)
|
||
|
dataID = 0x11; // MS - LP
|
||
|
else if (active == ACTIVE_CX2)
|
||
|
dataID = 0x10; // MS - ACTIVE
|
||
|
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = dataID;
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, ®Add[0], 3, 0);
|
||
|
if (ret < 0) {
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
// Read Header
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &cdata[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
if (ret < 0) {
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
return ret;
|
||
|
}
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
if ((cdata[0] != 0xA5) && (cdata[1] != dataID)) {
|
||
|
input_info(true, &info->client->dev, "%s: failed to read signature data of header.\n", __func__);
|
||
|
ret = -EIO;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
txnum = cdata[4];
|
||
|
rxnum = cdata[5];
|
||
|
|
||
|
rdata = kzalloc(txnum * rxnum, GFP_KERNEL);
|
||
|
if (!rdata)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
comp_start_addr = (u16)FTS_COMP_DATA_HEADER_SIZE;
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)(comp_start_addr >> 8);
|
||
|
regAdd[2] = (u8)(comp_start_addr & 0xFF);
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &rdata[0], txnum * rxnum);
|
||
|
if (ret < 0)
|
||
|
goto out;
|
||
|
|
||
|
pStr = kzalloc(7 * (rxnum + 1), GFP_KERNEL);
|
||
|
if (!pStr) {
|
||
|
ret = -ENOMEM;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
*cx_min = *cx_max = rdata[0];
|
||
|
for (i = 0; i < txnum; i++) {
|
||
|
memset(pStr, 0x0, 7 * (rxnum + 1));
|
||
|
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", i);
|
||
|
strlcat(pStr, pTmp, 7 * (rxnum + 1));
|
||
|
|
||
|
for (j = 0; j < rxnum; j++) {
|
||
|
snprintf(pTmp, sizeof(pTmp), "%4d", rdata[i * rxnum + j]);
|
||
|
strlcat(pStr, pTmp, 7 * (rxnum + 1));
|
||
|
|
||
|
*cx_min = min(*cx_min, rdata[i * rxnum + j]);
|
||
|
*cx_max = max(*cx_max, rdata[i * rxnum + j]);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", pStr);
|
||
|
}
|
||
|
input_raw_info_d(true, &info->client->dev, "cx min:%d, cx max:%d\n", *cx_min, *cx_max);
|
||
|
|
||
|
/* info->cx_data length: Force * Sense */
|
||
|
if (info->cx_data && active == NORMAL_CX2)
|
||
|
memcpy(&info->cx_data[0], &rdata[0], info->ForceChannelLength * info->SenseChannelLength);
|
||
|
|
||
|
kfree(pStr);
|
||
|
out:
|
||
|
kfree(rdata);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void run_active_cx_data_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
char buff_minmax[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int rc;
|
||
|
s8 cx_min, cx_max;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "ACTIVE_CX2_DATA");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: start\n", __func__);
|
||
|
|
||
|
rc = read_ms_cx2_data(info, ACTIVE_CX2, &cx_min, &cx_max);
|
||
|
if (rc < 0) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
snprintf(buff_minmax, sizeof(buff_minmax), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
snprintf(buff_minmax, sizeof(buff_minmax), "%d,%d", cx_min, cx_max);
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff_minmax, strnlen(buff_minmax, sizeof(buff_minmax)), "ACTIVE_CX2_DATA");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_multi_mutual_cx_data_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[FTS_EVENT_SIZE] = { 0 };
|
||
|
u8 *data;
|
||
|
u8 dataID;
|
||
|
u16 sense_cx_data[100];
|
||
|
u16 comp_start_rx_addr;
|
||
|
unsigned int rx_num, tx_num;
|
||
|
int rc, i, ret;
|
||
|
|
||
|
u16 max_sense_cx = 0;
|
||
|
u16 min_sense_cx = 0xFFFF;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
// Request compensation data type
|
||
|
dataID = 0x56;
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = dataID; // Multi Mutual CX data
|
||
|
|
||
|
rc = fts_fw_wait_for_echo_event(info, ®Add[0], 3, 0);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
if (rc < 0)
|
||
|
goto out;
|
||
|
|
||
|
data = kzalloc((info->ForceChannelLength + info->SenseChannelLength) * 2 + 1, GFP_KERNEL);
|
||
|
if (!data) {
|
||
|
input_err(true, &info->client->dev, "%s: data kzalloc fail!\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
// Read Header
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = 0x00;
|
||
|
info->fts_read_reg(info, ®Add[0], 3, &data[0], FTS_COMP_DATA_HEADER_SIZE);
|
||
|
|
||
|
if ((data[0] != 0xA5) && (data[1] != dataID)) {
|
||
|
kfree(data);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
tx_num = data[4];
|
||
|
rx_num = data[5];
|
||
|
|
||
|
/* Read Multi Mutual CX - RX data */
|
||
|
comp_start_rx_addr = FTS_COMP_DATA_HEADER_SIZE + (((tx_num * 2) + rx_num) * 2);
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = (u8)(comp_start_rx_addr >> 8);
|
||
|
regAdd[2] = (u8)(comp_start_rx_addr & 0xFF);
|
||
|
ret = info->fts_read_reg(info, ®Add[0], 3, &data[0], rx_num * 2);
|
||
|
if (ret < 0) {
|
||
|
kfree(data);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < rx_num; i++) {
|
||
|
sense_cx_data[i] = data[2 * i] | data[2 * i + 1] << 8;
|
||
|
|
||
|
if (max_sense_cx < sense_cx_data[i])
|
||
|
max_sense_cx = sense_cx_data[i];
|
||
|
if (min_sense_cx > sense_cx_data[i])
|
||
|
min_sense_cx = sense_cx_data[i];
|
||
|
}
|
||
|
|
||
|
kfree(data);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d,%d", min_sense_cx, max_sense_cx);
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MULTI_MUTUAL_CX");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MULTI_MUTUAL_CX");
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_cx_data_read(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
char buff_minmax[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int rc;
|
||
|
u8 cx_min, cx_max;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CX_DATA");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: start\n", __func__);
|
||
|
|
||
|
rc = read_ms_cx_data(info, &cx_min, &cx_max);
|
||
|
if (rc < 0) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
snprintf(buff_minmax, sizeof(buff_minmax), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
snprintf(buff_minmax, sizeof(buff_minmax), "%d,%d", cx_min, cx_max);
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff_minmax, strnlen(buff_minmax, sizeof(buff_minmax)), "CX_DATA");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_cx_all_data(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int rc, i, j;
|
||
|
u8 cx_min, cx_max;
|
||
|
char *all_strbuff;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: start\n", __func__);
|
||
|
|
||
|
rc = read_ms_cx_data(info, &cx_min, &cx_max);
|
||
|
|
||
|
/* do not systemreset in COB type */
|
||
|
if (info->board->chip_on_board)
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
else
|
||
|
enter_factory_mode(info, false);
|
||
|
if (rc < 0) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
all_strbuff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 4 + 1, GFP_KERNEL);
|
||
|
if (!all_strbuff) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Read compensation data */
|
||
|
if (info->cx_data) {
|
||
|
for (j = 0; j < info->ForceChannelLength; j++) {
|
||
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
||
|
snprintf(buff, sizeof(buff), "%d,", info->cx_data[j * info->SenseChannelLength + i]);
|
||
|
strlcat(all_strbuff, buff, info->ForceChannelLength * info->SenseChannelLength * 4 + 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, all_strbuff, strlen(all_strbuff));
|
||
|
input_info(true, &info->client->dev, "%s: %ld\n", __func__, strlen(all_strbuff));
|
||
|
kfree(all_strbuff);
|
||
|
}
|
||
|
|
||
|
static void get_cx_gap_data(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int rx_max = 0, tx_max = 0, ii;
|
||
|
|
||
|
for (ii = 0; ii < (info->SenseChannelLength * info->ForceChannelLength); ii++) {
|
||
|
/* rx(x) gap max */
|
||
|
if ((ii + 1) % (info->SenseChannelLength) != 0)
|
||
|
rx_max = max(rx_max, (int)abs(info->cx_data[ii + 1] - info->cx_data[ii]));
|
||
|
|
||
|
/* tx(y) gap max */
|
||
|
if (ii < (info->ForceChannelLength - 1) * info->SenseChannelLength)
|
||
|
tx_max = max(tx_max, (int)abs(info->cx_data[ii + info->SenseChannelLength] - info->cx_data[ii]));
|
||
|
}
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: max: rx:%d, tx:%d\n", __func__, rx_max, tx_max);
|
||
|
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
||
|
snprintf(buff, sizeof(buff), "0,%d", rx_max);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, SEC_CMD_STR_LEN, "CX_DATA_GAP_X");
|
||
|
snprintf(buff, sizeof(buff), "0,%d", tx_max);
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, SEC_CMD_STR_LEN, "CX_DATA_GAP_Y");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void run_cx_gap_data_x_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char *buff = NULL;
|
||
|
int ii, jj;
|
||
|
char temp[5] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
buff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 5, GFP_KERNEL);
|
||
|
if (!buff) {
|
||
|
snprintf(temp, sizeof(temp), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, temp, strnlen(temp, sizeof(temp)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (ii = 0; ii < info->ForceChannelLength; ii++) {
|
||
|
for (jj = 0; jj < info->SenseChannelLength - 1; jj++) {
|
||
|
snprintf(temp, sizeof(temp), "%d,",
|
||
|
abs(info->cx_data[(ii * info->SenseChannelLength) + jj + 1] -
|
||
|
info->cx_data[(ii * info->SenseChannelLength) + jj]));
|
||
|
strlcat(buff, temp, info->ForceChannelLength * info->SenseChannelLength * 5);
|
||
|
memset(temp, 0x00, 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, info->ForceChannelLength * info->SenseChannelLength * 5));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
kfree(buff);
|
||
|
}
|
||
|
|
||
|
static void run_cx_gap_data_y_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char *buff = NULL;
|
||
|
int ii, jj;
|
||
|
char temp[5] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
buff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 5, GFP_KERNEL);
|
||
|
if (!buff) {
|
||
|
snprintf(temp, sizeof(temp), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, temp, strnlen(temp, sizeof(temp)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (ii = 0; ii < info->ForceChannelLength - 1; ii++) {
|
||
|
for (jj = 0; jj < info->SenseChannelLength; jj++) {
|
||
|
snprintf(temp, sizeof(temp), "%d,",
|
||
|
abs(info->cx_data[((ii + 1) * info->SenseChannelLength) + jj] -
|
||
|
info->cx_data[(ii * info->SenseChannelLength)+ jj]));
|
||
|
strlcat(buff, temp, info->ForceChannelLength * info->SenseChannelLength * 5);
|
||
|
memset(temp, 0x00, 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, info->ForceChannelLength * info->SenseChannelLength * 5));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
kfree(buff);
|
||
|
}
|
||
|
|
||
|
static void run_rawdata_gap_data_rx_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char *buff = NULL;
|
||
|
int ii;
|
||
|
char temp[5] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
buff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 5, GFP_KERNEL);
|
||
|
if (!buff) {
|
||
|
snprintf(temp, sizeof(temp), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, temp, strnlen(temp, sizeof(temp)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (ii = 0; ii < (info->SenseChannelLength * info->ForceChannelLength); ii++) {
|
||
|
if ((ii + 1) % (info->SenseChannelLength) != 0) {
|
||
|
snprintf(temp, sizeof(temp), "%d,", (int)abs(info->pFrame[ii + 1] - info->pFrame[ii]));
|
||
|
strlcat(buff, temp, info->ForceChannelLength * info->SenseChannelLength * 5);
|
||
|
memset(temp, 0x00, 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, info->ForceChannelLength * info->SenseChannelLength * 5));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
kfree(buff);
|
||
|
}
|
||
|
|
||
|
static void run_rawdata_gap_data_tx_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char *buff = NULL;
|
||
|
int ii;
|
||
|
char temp[5] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
buff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 5, GFP_KERNEL);
|
||
|
if (!buff) {
|
||
|
snprintf(temp, sizeof(temp), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, temp, strnlen(temp, sizeof(temp)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (ii = 0; ii < (info->SenseChannelLength * info->ForceChannelLength); ii++) {
|
||
|
if (ii < (info->ForceChannelLength - 1) * info->SenseChannelLength) {
|
||
|
snprintf(temp, sizeof(temp), "%d,",
|
||
|
(int)abs(info->pFrame[ii + info->SenseChannelLength] - info->pFrame[ii]));
|
||
|
strlcat(buff, temp, info->ForceChannelLength * info->SenseChannelLength * 5);
|
||
|
memset(temp, 0x00, 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, info->ForceChannelLength * info->SenseChannelLength * 5));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
kfree(buff);
|
||
|
}
|
||
|
|
||
|
static void factory_cmd_result_all(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
sec->item_count = 0;
|
||
|
memset(sec->cmd_result_all, 0x00, SEC_CMD_RESULT_STR_LEN);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_RUNNING;
|
||
|
|
||
|
get_chip_vendor(sec);
|
||
|
get_chip_name(sec);
|
||
|
get_fw_ver_bin(sec);
|
||
|
get_fw_ver_ic(sec);
|
||
|
|
||
|
enter_factory_mode(info, true);
|
||
|
|
||
|
// run_lp_single_ended_rawcap_read(sec); /* Mutual raw */
|
||
|
run_rawcap_read(sec);
|
||
|
run_self_raw_read(sec);
|
||
|
|
||
|
fts_set_scanmode(info, FTS_SCAN_MODE_SCAN_OFF);
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
// have to check items
|
||
|
// get_strength_all_data(sec); /* jitter data */
|
||
|
// run_high_frequency_rawcap_read(sec); /* micro_open */
|
||
|
// get_rawcap_gap_data(sec); /* micro_open rawcap gap */
|
||
|
// run_low_frequency_rawcap_read(sec); /* micro_short gap diff */
|
||
|
|
||
|
// run_active_cx_data_read(sec);
|
||
|
run_cx_data_read(sec);
|
||
|
get_cx_gap_data(sec);
|
||
|
run_ix_data_read(sec);
|
||
|
|
||
|
get_wet_mode(sec);
|
||
|
|
||
|
/* do not systemreset in COB type */
|
||
|
if (info->board->chip_on_board)
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
else
|
||
|
enter_factory_mode(info, false);
|
||
|
|
||
|
run_mutual_jitter(sec);
|
||
|
run_self_jitter(sec);
|
||
|
run_factory_miscalibration(sec);
|
||
|
|
||
|
if (info->board->support_sram_test )
|
||
|
run_sram_test(sec);
|
||
|
|
||
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
out:
|
||
|
input_info(true, &info->client->dev, "%s: %d%s\n", __func__, sec->item_count, sec->cmd_result_all);
|
||
|
}
|
||
|
|
||
|
static void factory_cmd_result_all_imagetest(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
|
||
|
sec->item_count = 0;
|
||
|
memset(sec->cmd_result_all, 0x00, SEC_CMD_RESULT_STR_LEN);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_RUNNING;
|
||
|
|
||
|
run_jitter_delta_test(sec);
|
||
|
|
||
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
out:
|
||
|
input_info(true, &info->client->dev, "%s: %d%s\n", __func__, sec->item_count, sec->cmd_result_all);
|
||
|
}
|
||
|
|
||
|
static void set_factory_level(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: Touch is stopped!\n", __func__);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] < OFFSET_FAC_SUB || sec->cmd_param[0] > OFFSET_FAC_MAIN) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: cmd data is abnormal, %d\n", __func__, sec->cmd_param[0]);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
info->factory_position = sec->cmd_param[0];
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__, info->factory_position);
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
return;
|
||
|
|
||
|
NG:
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
}
|
||
|
|
||
|
int fts_get_tsp_test_result(struct fts_ts_info *info)
|
||
|
{
|
||
|
u8 data;
|
||
|
int ret;
|
||
|
|
||
|
ret = get_nvm_data(info, FTS_NVM_OFFSET_FAC_RESULT, &data);
|
||
|
if (ret < 0)
|
||
|
goto err_read;
|
||
|
|
||
|
if (data == 0xFF)
|
||
|
data = 0;
|
||
|
|
||
|
info->test_result.data[0] = data;
|
||
|
|
||
|
err_read:
|
||
|
return ret;
|
||
|
}
|
||
|
EXPORT_SYMBOL(fts_get_tsp_test_result);
|
||
|
|
||
|
static void get_tsp_test_result(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = fts_get_tsp_test_result(info);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: get failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "M:%s, M:%d, A:%s, A:%d",
|
||
|
info->test_result.module_result == 0 ? "NONE" :
|
||
|
info->test_result.module_result == 1 ? "FAIL" :
|
||
|
info->test_result.module_result == 2 ? "PASS" : "A",
|
||
|
info->test_result.module_count,
|
||
|
info->test_result.assy_result == 0 ? "NONE" :
|
||
|
info->test_result.assy_result == 1 ? "FAIL" :
|
||
|
info->test_result.assy_result == 2 ? "PASS" : "A",
|
||
|
info->test_result.assy_count);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strlen(buff));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* FACTORY TEST RESULT SAVING FUNCTION
|
||
|
* bit 3 ~ 0 : OCTA Assy
|
||
|
* bit 7 ~ 4 : OCTA module
|
||
|
* param[0] : OCTA module(1) / OCTA Assy(2)
|
||
|
* param[1] : TEST NONE(0) / TEST FAIL(1) / TEST PASS(2) : 2 bit
|
||
|
*/
|
||
|
static void set_tsp_test_result(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = fts_get_tsp_test_result(info);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: get failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
|
||
|
|
||
|
if (sec->cmd_param[0] == TEST_OCTA_ASSAY) {
|
||
|
info->test_result.assy_result = sec->cmd_param[1];
|
||
|
if (info->test_result.assy_count < 3)
|
||
|
info->test_result.assy_count++;
|
||
|
|
||
|
} else if (sec->cmd_param[0] == TEST_OCTA_MODULE) {
|
||
|
info->test_result.module_result = sec->cmd_param[1];
|
||
|
if (info->test_result.module_count < 3)
|
||
|
info->test_result.module_count++;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: [0x%X] M:%s, M:%d, A:%s, A:%d\n",
|
||
|
__func__, info->test_result.data[0],
|
||
|
info->test_result.module_result == 0 ? "NONE" :
|
||
|
info->test_result.module_result == 1 ? "FAIL" :
|
||
|
info->test_result.module_result == 2 ? "PASS" : "A",
|
||
|
info->test_result.module_count,
|
||
|
info->test_result.assy_result == 0 ? "NONE" :
|
||
|
info->test_result.assy_result == 1 ? "FAIL" :
|
||
|
info->test_result.assy_result == 2 ? "PASS" : "A",
|
||
|
info->test_result.assy_count);
|
||
|
|
||
|
ret = set_nvm_data(info, FTS_NVM_OFFSET_FAC_RESULT, info->test_result.data);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: set failed. ret: %d\n", __func__, ret);
|
||
|
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, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
int fts_get_disassemble_count(struct fts_ts_info *info)
|
||
|
{
|
||
|
u8 data;
|
||
|
int ret;
|
||
|
|
||
|
ret = get_nvm_data(info, FTS_NVM_OFFSET_DISASSEMBLE_COUNT, &data);
|
||
|
if (ret < 0)
|
||
|
goto err_read;
|
||
|
|
||
|
if (data == 0xFF)
|
||
|
data = 0;
|
||
|
|
||
|
info->disassemble_count = data;
|
||
|
|
||
|
err_read:
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void increase_disassemble_count(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = fts_get_disassemble_count(info);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: get failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
|
||
|
|
||
|
if (info->disassemble_count < 0xFE)
|
||
|
info->disassemble_count++;
|
||
|
|
||
|
ret = set_nvm_data(info, FTS_NVM_OFFSET_DISASSEMBLE_COUNT, &info->disassemble_count);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: set failed. ret: %d\n", __func__, ret);
|
||
|
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, strnlen(buff, sizeof(buff)));
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_disassemble_count(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = fts_get_disassemble_count(info);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: get failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "%d", info->disassemble_count);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strlen(buff));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void get_osc_trim_error(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = info->fts_systemreset(info, 0);
|
||
|
if (ret == -FTS_ERROR_BROKEN_OSC_TRIM) {
|
||
|
snprintf(buff, sizeof(buff), "1");
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "0");
|
||
|
}
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "OSC_TRIM_ERR");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void get_osc_trim_info(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
unsigned char data[4];
|
||
|
unsigned char regAdd[3];
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ret = info->fts_get_sysinfo_data(info, FTS_SI_OSC_TRIM_INFO, 2, data);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: system info read failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = data[1];
|
||
|
regAdd[2] = data[0];
|
||
|
|
||
|
memset(data, 0x00, 4);
|
||
|
ret = info->fts_read_reg(info, regAdd, 3, data, 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: osc trim info read failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%02X%02X%02X%02X", data[0], data[1], data[2], data[3]);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "OSC_TRIM_INFO");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_snr_non_touched(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 address[5] = { 0 };
|
||
|
u16 status;
|
||
|
int ret = 0;
|
||
|
int wait_time = 0;
|
||
|
int retry_cnt = 0;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
goto out_init;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] < 1 || sec->cmd_param[0] > 1000) {
|
||
|
input_err(true, &info->client->dev, "%s: strange value frame:%d\n",
|
||
|
__func__, sec->cmd_param[0]);
|
||
|
goto out_init;
|
||
|
}
|
||
|
|
||
|
fts_fix_active_mode(info, true);
|
||
|
|
||
|
/* enter SNR mode */
|
||
|
address[0] = 0x70;
|
||
|
address[1] = 0x25;
|
||
|
ret = info->fts_write_reg(info, &address[0], 2);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: i2c_write failed\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
/* start Non-touched Peak Noise */
|
||
|
address[0] = 0xC7;
|
||
|
address[1] = 0x09;
|
||
|
address[2] = 0x01;
|
||
|
address[3] = (u8)(sec->cmd_param[0] & 0xff);
|
||
|
address[4] = (u8)(sec->cmd_param[0] >> 8);
|
||
|
ret = info->fts_write_reg(info, &address[0], 5);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: i2c_write failed\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
|
||
|
wait_time = (sec->cmd_param[0] * 1000) / 120 + (sec->cmd_param[0] * 1000) % 120;
|
||
|
|
||
|
fts_delay(wait_time);
|
||
|
|
||
|
retry_cnt = 50;
|
||
|
address[0] = 0x72;
|
||
|
while ((info->fts_read_reg(info, &address[0], 1, (u8 *)&status, 2) > 0) && (retry_cnt-- > 0)) {
|
||
|
if (status == 1)
|
||
|
break;
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
|
||
|
if (status == 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed non-touched status:%d\n", __func__, status);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
/* EXIT SNR mode */
|
||
|
address[0] = 0x70;
|
||
|
address[1] = 0x00;
|
||
|
info->fts_write_reg(info, &address[0], 2);
|
||
|
fts_fix_active_mode(info, false);
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
|
||
|
out:
|
||
|
address[0] = 0x70;
|
||
|
address[1] = 0x00;
|
||
|
info->fts_write_reg(info, &address[0], 2);
|
||
|
fts_fix_active_mode(info, false);
|
||
|
|
||
|
out_init:
|
||
|
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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_snr_touched(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
struct stm_ts_snr_result_cmd snr_cmd_result;
|
||
|
struct stm_ts_snr_result snr_result;
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
char tbuff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 address[5] = { 0 };
|
||
|
int ret = 0;
|
||
|
int wait_time = 0;
|
||
|
int retry_cnt = 0;
|
||
|
int i = 0;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s\n", __func__);
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
memset(&snr_result, 0, sizeof(struct stm_ts_snr_result));
|
||
|
memset(&snr_cmd_result, 0, sizeof(struct stm_ts_snr_result_cmd));
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
goto out_init;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] < 1 || sec->cmd_param[0] > 1000) {
|
||
|
input_err(true, &info->client->dev, "%s: strange value frame:%d\n",
|
||
|
__func__, sec->cmd_param[0]);
|
||
|
goto out_init;
|
||
|
}
|
||
|
|
||
|
fts_fix_active_mode(info, true);
|
||
|
|
||
|
/* enter SNR mode */
|
||
|
address[0] = 0x70;
|
||
|
address[1] = 0x25;
|
||
|
ret = info->fts_write_reg(info, &address[0], 2);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: i2c_write failed\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
/* start touched Peak Noise */
|
||
|
address[0] = 0xC7;
|
||
|
address[1] = 0x09;
|
||
|
address[2] = 0x02;
|
||
|
address[3] = (u8)(sec->cmd_param[0] & 0xff);
|
||
|
address[4] = (u8)(sec->cmd_param[0] >> 8);
|
||
|
ret = info->fts_write_reg(info, &address[0], 5);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: i2c_write failed\n", __func__);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
wait_time = (sec->cmd_param[0] * 1000) / 120 + (sec->cmd_param[0] * 1000) % 120;
|
||
|
|
||
|
fts_delay(wait_time);
|
||
|
|
||
|
retry_cnt = 50;
|
||
|
address[0] = 0x72;
|
||
|
while ((info->fts_read_reg(info, &address[0], 1, (u8 *)&snr_cmd_result, 6) > 0) && (retry_cnt-- > 0)) {
|
||
|
if (snr_cmd_result.status == 1)
|
||
|
break;
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
|
||
|
if (snr_cmd_result.status == 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed non-touched status:%d\n", __func__, snr_cmd_result.status);
|
||
|
goto out;
|
||
|
} else {
|
||
|
input_info(true, &info->client->dev, "%s: status:%d, point:%d, average:%d\n", __func__,
|
||
|
snr_cmd_result.status, snr_cmd_result.point, snr_cmd_result.average);
|
||
|
}
|
||
|
|
||
|
address[0] = 0x72;
|
||
|
ret = info->fts_read_reg(info, &address[0], 1, (u8 *)&snr_result, sizeof(struct stm_ts_snr_result));
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: i2c_write failed size:%d\n", __func__, sizeof(struct stm_ts_snr_result));
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < 9; i++) {
|
||
|
input_info(true, &info->client->dev, "%s: average:%d, snr1:%d, snr2:%d\n", __func__,
|
||
|
snr_result.result[i].average, snr_result.result[i].snr1, snr_result.result[i].snr2);
|
||
|
snprintf(tbuff, sizeof(tbuff), "%d,%d,%d,",
|
||
|
snr_result.result[i].average,
|
||
|
snr_result.result[i].snr1,
|
||
|
snr_result.result[i].snr2);
|
||
|
strlcat(buff, tbuff, sizeof(buff));
|
||
|
}
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
|
||
|
/* EXIT SNR mode */
|
||
|
address[0] = 0x70;
|
||
|
address[1] = 0x00;
|
||
|
info->fts_write_reg(info, &address[0], 2);
|
||
|
fts_fix_active_mode(info, false);
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
|
||
|
return;
|
||
|
out:
|
||
|
address[0] = 0x70;
|
||
|
address[1] = 0x00;
|
||
|
info->fts_write_reg(info, &address[0], 2);
|
||
|
fts_fix_active_mode(info, false);
|
||
|
out_init:
|
||
|
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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
static void run_elvss_test(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
u8 data[FTS_EVENT_SIZE + 1];
|
||
|
int retry = 10;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
memset(data, 0x00, 8);
|
||
|
|
||
|
data[0] = 0xA4;
|
||
|
data[1] = 0x04;
|
||
|
data[2] = 0x00;
|
||
|
data[3] = 0x04;
|
||
|
|
||
|
ret = info->fts_write_reg(info, data, 4);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: write failed. ret: %d\n", __func__, ret);
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
fts_reinit(info, false);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memset(data, 0x00, FTS_EVENT_SIZE);
|
||
|
data[0] = FTS_READ_ONE_EVENT;
|
||
|
while (info->fts_read_reg(info, &data[0], 1, &data[1], FTS_EVENT_SIZE) > 0) {
|
||
|
input_info(true, &info->client->dev,
|
||
|
"%s: %02X: %02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
|
||
|
data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
|
||
|
|
||
|
if (data[1] == FTS_EVENT_ERROR_REPORT) {
|
||
|
break;
|
||
|
} else if (data[1] == 0x03) {
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
break;
|
||
|
} else if (retry < 0) {
|
||
|
break;
|
||
|
}
|
||
|
retry--;
|
||
|
fts_delay(50);
|
||
|
|
||
|
}
|
||
|
|
||
|
fts_reinit(info, false);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
*/
|
||
|
int set_nvm_data_by_size(struct fts_ts_info *info, u8 offset, int length, u8 *buf)
|
||
|
{
|
||
|
u8 regAdd[256] = { 0 };
|
||
|
u8 remaining, index, sendinglength;
|
||
|
int ret;
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true); // Clear FIFO
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
remaining = length;
|
||
|
index = 0;
|
||
|
sendinglength = 0;
|
||
|
|
||
|
while (remaining) {
|
||
|
regAdd[0] = 0xC7;
|
||
|
regAdd[1] = 0x01;
|
||
|
regAdd[2] = offset + index;
|
||
|
|
||
|
// write data up to 12 bytes available
|
||
|
if (remaining < 13) {
|
||
|
memcpy(®Add[3], &buf[index], remaining);
|
||
|
sendinglength = remaining;
|
||
|
} else {
|
||
|
memcpy(®Add[3], &buf[index], 12);
|
||
|
index += 12;
|
||
|
sendinglength = 12;
|
||
|
}
|
||
|
|
||
|
ret = fts_write_reg(info, ®Add[0], sendinglength + 3);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: write failed. ret: %d\n", __func__, ret);
|
||
|
return ret;
|
||
|
}
|
||
|
remaining -= sendinglength;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
// Save to flash
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x05;
|
||
|
regAdd[2] = 0x04; // panel configuration area
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, ®Add[0], 3, 200);
|
||
|
if (ret < 0)
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: failed to get echo. ret: %d\n", __func__, ret);
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int set_nvm_data(struct fts_ts_info *info, u8 type, u8 *buf)
|
||
|
{
|
||
|
return set_nvm_data_by_size(info, nvm_data[type].offset, nvm_data[type].length, buf);
|
||
|
}
|
||
|
|
||
|
int get_nvm_data_by_size(struct fts_ts_info *info, u8 offset, int length, u8 *nvdata)
|
||
|
{
|
||
|
u8 regAdd[3] = {0};
|
||
|
u8 data[128] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
info->fts_command(info, FTS_CMD_CLEAR_ALL_EVENT, true); // Clear FIFO
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
|
||
|
// Request SEC factory debug data from flash
|
||
|
regAdd[0] = 0xA4;
|
||
|
regAdd[1] = 0x06;
|
||
|
regAdd[2] = 0x90;
|
||
|
|
||
|
ret = fts_fw_wait_for_echo_event(info, ®Add[0], 3, 0);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: timeout. ret: %d\n", __func__, ret);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
|
||
|
regAdd[0] = 0xA6;
|
||
|
regAdd[1] = 0x00;
|
||
|
regAdd[2] = offset;
|
||
|
|
||
|
ret = fts_read_reg(info, ®Add[0], 3, data, length + 1);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: read failed. ret: %d\n", __func__, ret);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
memcpy(nvdata, &data[0], length);
|
||
|
|
||
|
input_raw_info_d(true, &info->client->dev, "%s: offset [%d], length [%d]\n",
|
||
|
__func__, offset, length);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int get_nvm_data(struct fts_ts_info *info, int type, u8 *nvdata)
|
||
|
{
|
||
|
int size = sizeof(nvm_data) / sizeof(struct fts_nvm_data_map);
|
||
|
|
||
|
if (type >= size)
|
||
|
return -EINVAL;
|
||
|
|
||
|
return get_nvm_data_by_size(info, nvm_data[type].offset, nvm_data[type].length, nvdata);
|
||
|
}
|
||
|
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
int fts_tclm_data_read(struct i2c_client *client, int address)
|
||
|
{
|
||
|
struct fts_ts_info *info = i2c_get_clientdata(client);
|
||
|
int ret = 0;
|
||
|
int i = 0;
|
||
|
u8 nbuff[FTS_NVM_OFFSET_ALL];
|
||
|
u16 ic_version;
|
||
|
|
||
|
switch (address) {
|
||
|
case SEC_TCLM_NVM_OFFSET_IC_FIRMWARE_VER:
|
||
|
ret = info->fts_get_version_info(info);
|
||
|
ic_version = (info->module_version_of_ic << 8) | (info->fw_main_version_of_ic & 0xFF);
|
||
|
return ic_version;
|
||
|
case SEC_TCLM_NVM_ALL_DATA:
|
||
|
ret = get_nvm_data_by_size(info, nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset,
|
||
|
FTS_NVM_OFFSET_ALL, nbuff);
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
info->tdata->nvdata.cal_count = nbuff[nvm_data[FTS_NVM_OFFSET_CAL_COUNT].offset];
|
||
|
info->tdata->nvdata.tune_fix_ver = (nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset] << 8) |
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset + 1];
|
||
|
info->tdata->nvdata.cal_position = nbuff[nvm_data[FTS_NVM_OFFSET_CAL_POSITION].offset];
|
||
|
info->tdata->nvdata.cal_pos_hist_cnt = nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT].offset];
|
||
|
info->tdata->nvdata.cal_pos_hist_lastp = nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP].offset];
|
||
|
for (i = nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset;
|
||
|
i < nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset +
|
||
|
nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].length; i++)
|
||
|
info->tdata->nvdata.cal_pos_hist_queue[i - nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset] = nbuff[i];
|
||
|
|
||
|
info->tdata->nvdata.cal_fail_falg = nbuff[nvm_data[FTS_NVM_OFFSET_CAL_FAIL_FLAG].offset];
|
||
|
info->tdata->nvdata.cal_fail_cnt= nbuff[nvm_data[FTS_NVM_OFFSET_CAL_FAIL_COUNT].offset];
|
||
|
info->fac_nv = nbuff[nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset];
|
||
|
info->disassemble_count = nbuff[nvm_data[FTS_NVM_OFFSET_DISASSEMBLE_COUNT].offset];
|
||
|
return ret;
|
||
|
case SEC_TCLM_NVM_TEST:
|
||
|
input_info(true, &info->client->dev, "%s: dt: tclm_level [%d] afe_base [%04X]\n",
|
||
|
__func__, info->tdata->tclm_level, info->tdata->afe_base);
|
||
|
ret = get_nvm_data_by_size(info, FTS_NVM_OFFSET_ALL + SEC_TCLM_NVM_OFFSET,
|
||
|
SEC_TCLM_NVM_OFFSET_LENGTH, info->tdata->tclm);
|
||
|
if (info->tdata->tclm[0] != 0xFF) {
|
||
|
info->tdata->tclm_level = info->tdata->tclm[0];
|
||
|
info->tdata->afe_base = (info->tdata->tclm[1] << 8) | info->tdata->tclm[2];
|
||
|
input_info(true, &info->client->dev, "%s: nv: tclm_level [%d] afe_base [%04X]\n",
|
||
|
__func__, info->tdata->tclm_level, info->tdata->afe_base);
|
||
|
}
|
||
|
return ret;
|
||
|
default:
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int fts_tclm_data_write(struct i2c_client *client, int address)
|
||
|
{
|
||
|
struct fts_ts_info *info = i2c_get_clientdata(client);
|
||
|
int ret = 1;
|
||
|
int i = 0;
|
||
|
u8 nbuff[FTS_NVM_OFFSET_ALL];
|
||
|
|
||
|
switch (address) {
|
||
|
case SEC_TCLM_NVM_ALL_DATA:
|
||
|
memset(nbuff, 0x00, FTS_NVM_OFFSET_ALL);
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset] = info->fac_nv;
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_DISASSEMBLE_COUNT].offset] = info->disassemble_count;
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_CAL_COUNT].offset] = info->tdata->nvdata.cal_count;
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset] = (u8)(info->tdata->nvdata.tune_fix_ver >> 8);
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset + 1] = (u8)(0xff & info->tdata->nvdata.tune_fix_ver);
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_CAL_POSITION].offset] = info->tdata->nvdata.cal_position;
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT].offset] = info->tdata->nvdata.cal_pos_hist_cnt;
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP].offset] = info->tdata->nvdata.cal_pos_hist_lastp;
|
||
|
for (i = nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset;
|
||
|
i < nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset +
|
||
|
nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].length; i++)
|
||
|
nbuff[i] = info->tdata->nvdata.cal_pos_hist_queue[i - nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset];
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_CAL_FAIL_FLAG].offset] = info->tdata->nvdata.cal_fail_falg;
|
||
|
nbuff[nvm_data[FTS_NVM_OFFSET_CAL_FAIL_COUNT].offset] = info->tdata->nvdata.cal_fail_cnt;
|
||
|
ret = set_nvm_data_by_size(info, nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset, FTS_NVM_OFFSET_ALL, nbuff);
|
||
|
return ret;
|
||
|
case SEC_TCLM_NVM_TEST:
|
||
|
ret = set_nvm_data_by_size(info, FTS_NVM_OFFSET_ALL + SEC_TCLM_NVM_OFFSET,
|
||
|
SEC_TCLM_NVM_OFFSET_LENGTH, info->tdata->tclm);
|
||
|
return ret;
|
||
|
default:
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void tclm_test_cmd(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
struct sec_tclm_data *data = info->tdata;
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (!info->tdata->support_tclm_test)
|
||
|
goto not_support;
|
||
|
|
||
|
ret = tclm_test_command(data, sec->cmd_param[0], sec->cmd_param[1], sec->cmd_param[2], buff);
|
||
|
if (ret < 0)
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
else
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
return;
|
||
|
|
||
|
not_support:
|
||
|
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)));
|
||
|
}
|
||
|
|
||
|
static void get_calibration(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (!info->tdata->support_tclm_test)
|
||
|
goto not_support;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "%d", info->is_cal_done);
|
||
|
|
||
|
info->is_cal_done = false;
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
return;
|
||
|
|
||
|
not_support:
|
||
|
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)));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef CONFIG_GLOVE_TOUCH
|
||
|
static void glove_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[3] = {0};
|
||
|
|
||
|
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 {
|
||
|
info->glove_enabled = sec->cmd_param[0];
|
||
|
|
||
|
if (info->fts_power_state != FTS_POWER_STATE_POWERDOWN && info->reinit_done) {
|
||
|
if (info->glove_enabled)
|
||
|
info->touch_functions = info->touch_functions | FTS_TOUCHTYPE_BIT_GLOVE |
|
||
|
FTS_TOUCHTYPE_DEFAULT_ENABLE;
|
||
|
else
|
||
|
info->touch_functions = (info->touch_functions & (~FTS_TOUCHTYPE_BIT_GLOVE)) |
|
||
|
FTS_TOUCHTYPE_DEFAULT_ENABLE;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = FTS_CMD_SET_GET_TOUCHTYPE;
|
||
|
regAdd[1] = (u8)(info->touch_functions & 0xFF);
|
||
|
regAdd[2] = (u8)(info->touch_functions >> 8);
|
||
|
fts_write_reg(info, ®Add[0], 3);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void clear_cover_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
if (sec->cmd_param[0] > 1) {
|
||
|
info->flip_enable = true;
|
||
|
info->cover_type = sec->cmd_param[1];
|
||
|
} else {
|
||
|
info->flip_enable = false;
|
||
|
}
|
||
|
|
||
|
if (info->fts_power_state != FTS_POWER_STATE_POWERDOWN && info->reinit_done) {
|
||
|
if (info->flip_enable)
|
||
|
fts_set_cover_type(info, true);
|
||
|
else
|
||
|
fts_set_cover_type(info, false);
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
};
|
||
|
|
||
|
static void report_rate(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 scan_rate;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 255) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
|
||
|
scan_rate = sec->cmd_param[0];
|
||
|
fts_change_scan_rate(info, scan_rate);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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;
|
||
|
|
||
|
out:
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
||
|
static void interrupt_control(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
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 enables = sec->cmd_param[0];
|
||
|
|
||
|
if (enables)
|
||
|
fts_irq_enable(info, true);
|
||
|
else
|
||
|
fts_irq_enable(info, false);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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;
|
||
|
|
||
|
out:
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void set_wirelesscharger_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
info->charger_mode = sec->cmd_param[0];
|
||
|
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
info->charger_mode = sec->cmd_param[0];
|
||
|
|
||
|
fts_wirelesscharger_mode(info);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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;
|
||
|
|
||
|
out:
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
};
|
||
|
|
||
|
/*********************************************************************
|
||
|
* 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
|
||
|
* 0x00, FFF (y start), FFF (y end), FF(direction)
|
||
|
* 0x01, FFFF (edge zone)
|
||
|
* 0x02, FF (up x), FF (down x), FFFF (y)
|
||
|
* 0x03, FF (mode), FFF (edge), FFF (dead zone)
|
||
|
* case
|
||
|
* edge handler set : 0x00....
|
||
|
* booting time : 0x00... + 0x01...
|
||
|
* normal mode : 0x02... (+0x01...)
|
||
|
* landscape mode : 0x03...
|
||
|
* landscape -> normal (if same with old data) : 0x03, 0
|
||
|
* landscape -> normal (etc) : 0x02.... + 0x03, 0
|
||
|
*********************************************************************/
|
||
|
|
||
|
void fts_set_grip_data_to_ic(struct fts_ts_info *info, u8 flag)
|
||
|
{
|
||
|
u8 data[4] = { 0 };
|
||
|
u8 regAdd[11] = {FTS_CMD_SET_FUNCTION_ONOFF, };
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: flag: %02X (clr,lan,nor,edg,han)\n", __func__, flag);
|
||
|
|
||
|
memset(®Add[1], 0x00, 10);
|
||
|
|
||
|
if (flag & G_SET_EDGE_HANDLER) {
|
||
|
if (info->grip_edgehandler_direction == 0) {
|
||
|
data[0] = 0x0;
|
||
|
data[1] = 0x0;
|
||
|
data[2] = 0x0;
|
||
|
data[3] = 0x0;
|
||
|
} else {
|
||
|
data[0] = (info->grip_edgehandler_start_y >> 4) & 0xFF;
|
||
|
data[1] = (info->grip_edgehandler_start_y << 4 & 0xF0) |
|
||
|
((info->grip_edgehandler_end_y >> 8) & 0xF);
|
||
|
data[2] = info->grip_edgehandler_end_y & 0xFF;
|
||
|
data[3] = info->grip_edgehandler_direction & 0x3;
|
||
|
}
|
||
|
|
||
|
regAdd[1] = FTS_FUNCTION_EDGE_HANDLER;
|
||
|
regAdd[2] = data[0];
|
||
|
regAdd[3] = data[1];
|
||
|
regAdd[4] = data[2];
|
||
|
regAdd[5] = data[3];
|
||
|
|
||
|
fts_write_reg(info, regAdd, 6);
|
||
|
}
|
||
|
|
||
|
if (flag & G_SET_EDGE_ZONE) {
|
||
|
/* ex) C1 07 00 3E 00 3E
|
||
|
* - 0x003E(60) px : Grip Right zone
|
||
|
* - 0x003E(60) px : Grip Left zone
|
||
|
*/
|
||
|
regAdd[1] = FTS_FUNCTION_EDGE_AREA;
|
||
|
regAdd[2] = (info->grip_edge_range >> 8) & 0xFF;
|
||
|
regAdd[3] = info->grip_edge_range & 0xFF;
|
||
|
regAdd[4] = (info->grip_edge_range >> 8) & 0xFF;
|
||
|
regAdd[5] = info->grip_edge_range & 0xFF;
|
||
|
|
||
|
fts_write_reg(info, regAdd, 6);
|
||
|
}
|
||
|
|
||
|
if (flag & G_SET_NORMAL_MODE) {
|
||
|
/* ex) C1 08 1E 1E 00 00
|
||
|
* - 0x1E (30) px : upper X range
|
||
|
* - 0x1E (30) px : lower X range
|
||
|
* - 0x0000 (0) px : division Y
|
||
|
*/
|
||
|
regAdd[1] = FTS_FUNCTION_DEAD_ZONE;
|
||
|
regAdd[2] = info->grip_deadzone_up_x & 0xFF;
|
||
|
regAdd[3] = info->grip_deadzone_dn_x & 0xFF;
|
||
|
regAdd[4] = (info->grip_deadzone_y >> 8) & 0xFF;
|
||
|
regAdd[5] = info->grip_deadzone_y & 0xFF;
|
||
|
|
||
|
fts_write_reg(info, regAdd, 6);
|
||
|
}
|
||
|
|
||
|
if (flag & G_SET_LANDSCAPE_MODE) {
|
||
|
/* ex) C1 09 01 00 3C 00 3C 00 1E
|
||
|
* - 0x01 : horizontal mode
|
||
|
* - 0x03C (60) px : Grip zone range (Right)
|
||
|
* - 0x03C (60) px : Grip zone range (Left)
|
||
|
* - 0x01E (30) px : Reject zone range (Left/Right)
|
||
|
*/
|
||
|
regAdd[1] = FTS_FUNCTION_LANDSCAPE_MODE;
|
||
|
regAdd[2] = info->grip_landscape_mode;
|
||
|
regAdd[3] = (info->grip_landscape_edge >> 8) & 0xFF;
|
||
|
regAdd[4] = info->grip_landscape_edge & 0xFF;
|
||
|
regAdd[5] = (info->grip_landscape_edge >> 8) & 0xFF;
|
||
|
regAdd[6] = info->grip_landscape_edge & 0xFF;
|
||
|
regAdd[7] = (info->grip_landscape_deadzone >> 8) & 0xFF;
|
||
|
regAdd[8] = info->grip_landscape_deadzone & 0xFF;
|
||
|
|
||
|
fts_write_reg(info, regAdd, 9);
|
||
|
|
||
|
/*ex) C1 0A 01 00 3C 00 3C 00 1E 00 1E
|
||
|
* - 0x01(1) : Enable function
|
||
|
* - 0x003C (60) px : Grip Top zone range
|
||
|
* - 0x001E (60) px : Grip Bottom zone range
|
||
|
* - 0x001E (30) px : Reject Top zone range
|
||
|
* - 0x001E (30) px : Reject Bottom zone range
|
||
|
*/
|
||
|
regAdd[1] = FTS_FUNCTION_LANDSCAPE_TOP_BOTTOM;
|
||
|
regAdd[2] = info->grip_landscape_mode;
|
||
|
regAdd[3] = (info->grip_landscape_top_gripzone >> 8)& 0xFF;
|
||
|
regAdd[4] = info->grip_landscape_top_gripzone & 0xFF;
|
||
|
regAdd[5] = (info->grip_landscape_bottom_gripzone >> 8)& 0xFF;
|
||
|
regAdd[6] = info->grip_landscape_bottom_gripzone & 0xFF;
|
||
|
regAdd[7] = (info->grip_landscape_top_deadzone >> 8)& 0xFF;
|
||
|
regAdd[8] = info->grip_landscape_top_deadzone & 0xFF;
|
||
|
regAdd[9] = (info->grip_landscape_bottom_deadzone >> 8)& 0xFF;
|
||
|
regAdd[10] = info->grip_landscape_bottom_deadzone & 0xFF;
|
||
|
|
||
|
fts_write_reg(info, regAdd, 11);
|
||
|
}
|
||
|
|
||
|
if (flag & G_CLR_LANDSCAPE_MODE) {
|
||
|
memset(®Add[1], 0x00, 10);
|
||
|
|
||
|
/* ex) C1 09 00 00 00 00 00 00 00
|
||
|
* - 0x00 : Apply previous vertical mode value for grip zone and reject zone range
|
||
|
*/
|
||
|
regAdd[1] = FTS_FUNCTION_LANDSCAPE_MODE;
|
||
|
regAdd[2] = info->grip_landscape_mode;
|
||
|
|
||
|
fts_write_reg(info, regAdd, 9);
|
||
|
|
||
|
/*ex) C1 0A 00 00 00 00 00 00 00 00 00
|
||
|
* - Disable function
|
||
|
*/
|
||
|
regAdd[1] = FTS_FUNCTION_LANDSCAPE_TOP_BOTTOM;
|
||
|
|
||
|
fts_write_reg(info, regAdd, 11);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* 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), X (dead zone top y), X (dead zone bottom y)
|
||
|
* ex) echo set_grip_data,2,1,200,100,120,0 > 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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 mode = G_NONE;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
memset(buff, 0, sizeof(buff));
|
||
|
|
||
|
mutex_lock(&info->device_mutex);
|
||
|
|
||
|
if (sec->cmd_param[0] == 0) { // edge handler
|
||
|
if (sec->cmd_param[1] == 0) { // clear
|
||
|
info->grip_edgehandler_direction = 0;
|
||
|
} else if (sec->cmd_param[1] < 3) {
|
||
|
info->grip_edgehandler_direction = sec->cmd_param[1];
|
||
|
info->grip_edgehandler_start_y = sec->cmd_param[2];
|
||
|
info->grip_edgehandler_end_y = sec->cmd_param[3];
|
||
|
} else {
|
||
|
input_err(true, &info->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;
|
||
|
fts_set_grip_data_to_ic(info, mode);
|
||
|
} else if (sec->cmd_param[0] == 1) { // normal mode
|
||
|
if (info->grip_edge_range != sec->cmd_param[1])
|
||
|
mode = mode | G_SET_EDGE_ZONE;
|
||
|
|
||
|
info->grip_edge_range = sec->cmd_param[1];
|
||
|
info->grip_deadzone_up_x = sec->cmd_param[2];
|
||
|
info->grip_deadzone_dn_x = sec->cmd_param[3];
|
||
|
info->grip_deadzone_y = sec->cmd_param[4];
|
||
|
mode = mode | G_SET_NORMAL_MODE;
|
||
|
|
||
|
if (info->grip_landscape_mode == 1) {
|
||
|
info->grip_landscape_mode = 0;
|
||
|
mode = mode | G_CLR_LANDSCAPE_MODE;
|
||
|
}
|
||
|
|
||
|
fts_set_grip_data_to_ic(info, mode);
|
||
|
} else if (sec->cmd_param[0] == 2) { // landscape mode
|
||
|
if (sec->cmd_param[1] == 0) { // normal mode
|
||
|
info->grip_landscape_mode = 0;
|
||
|
mode = mode | G_CLR_LANDSCAPE_MODE;
|
||
|
} else if (sec->cmd_param[1] == 1) {
|
||
|
info->grip_landscape_mode = 1;
|
||
|
info->grip_landscape_edge = sec->cmd_param[2];
|
||
|
info->grip_landscape_deadzone = sec->cmd_param[3];
|
||
|
info->grip_landscape_top_deadzone = sec->cmd_param[4];
|
||
|
info->grip_landscape_bottom_deadzone = sec->cmd_param[5];
|
||
|
info->grip_landscape_top_gripzone = sec->cmd_param[6];
|
||
|
info->grip_landscape_bottom_gripzone = sec->cmd_param[7];
|
||
|
mode = mode | G_SET_LANDSCAPE_MODE;
|
||
|
} else {
|
||
|
input_err(true, &info->client->dev, "%s: cmd1 is abnormal, %d (%d)\n",
|
||
|
__func__, sec->cmd_param[1], __LINE__);
|
||
|
goto err_grip_data;
|
||
|
}
|
||
|
|
||
|
fts_set_grip_data_to_ic(info, mode);
|
||
|
} else {
|
||
|
input_err(true, &info->client->dev, "%s: cmd0 is abnormal, %d", __func__, sec->cmd_param[0]);
|
||
|
goto err_grip_data;
|
||
|
}
|
||
|
|
||
|
mutex_unlock(&info->device_mutex);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
return;
|
||
|
|
||
|
err_grip_data:
|
||
|
mutex_unlock(&info->device_mutex);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
}
|
||
|
|
||
|
static void dead_zone_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[3] = {FTS_CMD_SET_FUNCTION_ONOFF, FTS_FUNCTION_ENABLE_DEAD_ZONE, 0x00};
|
||
|
int ret;
|
||
|
|
||
|
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 {
|
||
|
if (sec->cmd_param[0] == 0)
|
||
|
regAdd[2] = 0x01; /* dead zone disable */
|
||
|
else
|
||
|
regAdd[2] = 0x00; /* dead zone enable */
|
||
|
|
||
|
ret = info->fts_write_reg(info, regAdd, 3);
|
||
|
if (ret < 0)
|
||
|
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
|
||
|
else
|
||
|
input_info(true, &info->client->dev, "%s: reg:%d, ret: %d\n", __func__, sec->cmd_param[0], ret);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void drawing_test_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void spay_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0])
|
||
|
info->lowpower_flag |= FTS_MODE_SPAY;
|
||
|
else
|
||
|
info->lowpower_flag &= ~FTS_MODE_SPAY;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void aot_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0])
|
||
|
info->lowpower_flag |= FTS_MODE_DOUBLETAP_WAKEUP;
|
||
|
else
|
||
|
info->lowpower_flag &= ~FTS_MODE_DOUBLETAP_WAKEUP;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__, sec->cmd_param[0]);
|
||
|
}
|
||
|
|
||
|
static void aod_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0])
|
||
|
info->lowpower_flag |= FTS_MODE_AOD;
|
||
|
else
|
||
|
info->lowpower_flag &= ~FTS_MODE_AOD;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__, sec->cmd_param[0]);
|
||
|
}
|
||
|
|
||
|
static void singletap_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0])
|
||
|
info->lowpower_flag |= FTS_MODE_SINGLETAP;
|
||
|
else
|
||
|
info->lowpower_flag &= ~FTS_MODE_SINGLETAP;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
input_info(true, &info->client->dev, "%s: %d\n", __func__, sec->cmd_param[0]);
|
||
|
}
|
||
|
|
||
|
static void set_aod_rect(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 data[8] = {0, };
|
||
|
int i, ret = -1;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
||
|
input_info(true, &info->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]);
|
||
|
#endif
|
||
|
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
data[i * 2] = sec->cmd_param[i] & 0xFF;
|
||
|
data[i * 2 + 1] = (sec->cmd_param[i] >> 8) & 0xFF;
|
||
|
info->rect_data[i] = sec->cmd_param[i];
|
||
|
}
|
||
|
|
||
|
#ifdef FTS_SUPPORT_SPONGELIB
|
||
|
if (!info->use_sponge)
|
||
|
goto NG;
|
||
|
|
||
|
ret = info->fts_write_to_sponge(info, FTS_CMD_SPONGE_OFFSET_AOD_RECT, data, sizeof(data));
|
||
|
#endif
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_LOWPOWER) {
|
||
|
if (sec->cmd_param[0] == 0 && sec->cmd_param[1] == 0 &&
|
||
|
sec->cmd_param[2] == 0 && sec->cmd_param[3] == 0) {
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: sync -> async base scan\n", __func__);
|
||
|
ret = fts_set_hsync_scanmode(info, FTS_CMD_LPM_ASYNC_SCAN);
|
||
|
} else {
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: sync base scan\n", __func__);
|
||
|
ret = fts_set_hsync_scanmode(info, FTS_CMD_LPM_SYNC_SCAN);
|
||
|
}
|
||
|
|
||
|
if (ret <= 0) {
|
||
|
input_err(true, &info->client->dev, "%s: Failed to send command!", __func__);
|
||
|
goto NG;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
return;
|
||
|
NG:
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
}
|
||
|
|
||
|
static void get_aod_rect(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 data[8] = {0, };
|
||
|
u16 rect_data[4] = {0, };
|
||
|
int i, ret = -1;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
#ifdef FTS_SUPPORT_SPONGELIB
|
||
|
if (!info->use_sponge)
|
||
|
goto NG;
|
||
|
|
||
|
ret = info->fts_read_from_sponge(info, FTS_CMD_SPONGE_OFFSET_AOD_RECT, data, sizeof(data));
|
||
|
#endif
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < 4; i++)
|
||
|
rect_data[i] = (data[i * 2 + 1] & 0xFF) << 8 | (data[i * 2] & 0xFF);
|
||
|
|
||
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
||
|
input_info(true, &info->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]);
|
||
|
#endif
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
return;
|
||
|
NG:
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
}
|
||
|
|
||
|
static void fod_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
int ret = 0;
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0])
|
||
|
info->lowpower_flag |= FTS_MODE_PRESS;
|
||
|
else
|
||
|
info->lowpower_flag &= ~FTS_MODE_PRESS;
|
||
|
|
||
|
info->press_prop = !!sec->cmd_param[1];
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s, fast:%d, 0x%02X\n",
|
||
|
__func__, sec->cmd_param[0] ? "on" : "off",
|
||
|
info->press_prop, info->lowpower_flag);
|
||
|
|
||
|
ret = info->fts_write_to_sponge(info, FTS_CMD_SPONGE_OFFSET_MODE,
|
||
|
&info->lowpower_flag, sizeof(info->lowpower_flag));
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: failed. ret: %d\n", __func__, ret);
|
||
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
fts_set_press_property(info);
|
||
|
fts_set_fod_finger_merge(info);
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
}
|
||
|
|
||
|
int fts_set_fod_rect(struct fts_ts_info *info)
|
||
|
{
|
||
|
int i, ret;
|
||
|
u8 data[8];
|
||
|
u32 sum = 0;
|
||
|
|
||
|
for (i = 0; i < 4; i++) {
|
||
|
data[i * 2] = info->fod_rect_data[i] & 0xFF;
|
||
|
data[i * 2 + 1] = (info->fod_rect_data[i] >> 8) & 0xFF;
|
||
|
sum += info->fod_rect_data[i];
|
||
|
}
|
||
|
|
||
|
if (!sum) /* no data */
|
||
|
return 0;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: l:%d, t:%d, r:%d, b:%d\n",
|
||
|
__func__, info->fod_rect_data[0], info->fod_rect_data[1],
|
||
|
info->fod_rect_data[2], info->fod_rect_data[3]);
|
||
|
|
||
|
ret = info->fts_write_to_sponge(info, FTS_CMD_SPONGE_FOD_RECT, data, sizeof(data));
|
||
|
if (ret < 0)
|
||
|
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void set_fod_rect(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int i, ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0] > info->board->max_x
|
||
|
|| sec->cmd_param[1] > info->board->max_y
|
||
|
|| sec->cmd_param[2] > info->board->max_x
|
||
|
|| sec->cmd_param[3] > info->board->max_y) {
|
||
|
input_err(true, &info->client->dev, "%s: Abnormal fod_rect data\n", __func__);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: l:%d, t:%d, r:%d, b:%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++)
|
||
|
info->fod_rect_data[i] = sec->cmd_param[i];
|
||
|
|
||
|
ret = fts_set_fod_rect(info);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
return;
|
||
|
NG:
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Enable or disable external_noise_mode
|
||
|
*
|
||
|
* If mode has EXT_NOISE_MODE_MAX,
|
||
|
* then write enable cmd for all enabled mode. (set as ts->external_noise_mode bit value)
|
||
|
* This routine need after IC power reset. TSP IC need to be re-wrote all enabled modes.
|
||
|
*
|
||
|
* Else if mode has specific value like EXT_NOISE_MODE_MONITOR,
|
||
|
* then write enable/disable cmd about for that mode's latest setting value.
|
||
|
*
|
||
|
* If you want to add new mode,
|
||
|
* please define new enum value like EXT_NOISE_MODE_MONITOR,
|
||
|
* then set cmd for that mode like below. (it is in this function)
|
||
|
* noise_mode_cmd[EXT_NOISE_MODE_MONITOR] = SEC_TS_CMD_SET_MONITOR_NOISE_MODE;
|
||
|
*/
|
||
|
int fts_set_external_noise_mode(struct fts_ts_info *info, u8 mode)
|
||
|
{
|
||
|
int i, ret, fail_count = 0;
|
||
|
u8 mode_bit_to_set, check_bit, mode_enable;
|
||
|
u8 noise_mode_cmd[EXT_NOISE_MODE_MAX] = { 0 };
|
||
|
u8 regAdd[3] = {FTS_CMD_SET_FUNCTION_ONOFF, 0x00, 0x00};
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: Touch is stopped!\n", __func__);
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
|
||
|
if (mode == EXT_NOISE_MODE_MAX) {
|
||
|
/* write all enabled mode */
|
||
|
mode_bit_to_set = info->external_noise_mode;
|
||
|
} else {
|
||
|
/* make enable or disable the specific mode */
|
||
|
mode_bit_to_set = 1 << mode;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %sable %d\n", __func__,
|
||
|
info->external_noise_mode & mode_bit_to_set ? "en" : "dis", mode_bit_to_set);
|
||
|
|
||
|
/* set cmd for each mode */
|
||
|
noise_mode_cmd[EXT_NOISE_MODE_MONITOR] = FTS_FUNCTION_SET_MONITOR_NOISE_MODE;
|
||
|
|
||
|
/* write mode */
|
||
|
for (i = EXT_NOISE_MODE_NONE + 1; i < EXT_NOISE_MODE_MAX; i++) {
|
||
|
check_bit = 1 << i;
|
||
|
if (mode_bit_to_set & check_bit) {
|
||
|
mode_enable = !!(info->external_noise_mode & check_bit);
|
||
|
regAdd[1] = noise_mode_cmd[i];
|
||
|
regAdd[2] = mode_enable;
|
||
|
|
||
|
ret = info->fts_write_reg(info, regAdd, 3);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to set %02X %02X %02X\n",
|
||
|
__func__, regAdd[0], regAdd[1], regAdd[2]);
|
||
|
fail_count++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fail_count != 0)
|
||
|
return -EIO;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Enable or disable specific external_noise_mode (sec_cmd)
|
||
|
*
|
||
|
* This cmd has 2 params.
|
||
|
* param 0 : the mode that you want to change.
|
||
|
* param 1 : enable or disable the mode.
|
||
|
*
|
||
|
* For example,
|
||
|
* enable EXT_NOISE_MODE_MONITOR mode,
|
||
|
* write external_noise_mode,1,1
|
||
|
* disable EXT_NOISE_MODE_MONITOR mode,
|
||
|
* write external_noise_mode,1,0
|
||
|
*/
|
||
|
static void external_noise_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0] <= EXT_NOISE_MODE_NONE || sec->cmd_param[0] >= EXT_NOISE_MODE_MAX ||
|
||
|
sec->cmd_param[1] < 0 || sec->cmd_param[1] > 1) {
|
||
|
input_err(true, &info->client->dev, "%s: not support param\n", __func__);
|
||
|
goto NG;
|
||
|
}
|
||
|
|
||
|
if (sec->cmd_param[1] == 1)
|
||
|
info->external_noise_mode |= 1 << sec->cmd_param[0];
|
||
|
else
|
||
|
info->external_noise_mode &= ~(1 << sec->cmd_param[0]);
|
||
|
|
||
|
ret = fts_set_external_noise_mode(info, sec->cmd_param[0]);
|
||
|
if (ret < 0)
|
||
|
goto NG;
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
return;
|
||
|
|
||
|
NG:
|
||
|
snprintf(buff, sizeof(buff), "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);
|
||
|
}
|
||
|
|
||
|
static void brush_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[3] = {FTS_CMD_SET_FUNCTION_ONOFF, FTS_FUNCTION_ENABLE_BRUSH_MODE, 0x00};
|
||
|
int ret;
|
||
|
|
||
|
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;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
info->brush_mode = sec->cmd_param[0];
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev,
|
||
|
"%s: set brush mode %s\n", __func__, info->brush_mode ? "enable" : "disable");
|
||
|
|
||
|
if (info->brush_mode == 0)
|
||
|
regAdd[2] = 0x00; /* 0: Disable Artcanvas min phi mode */
|
||
|
else
|
||
|
regAdd[2] = 0x01; /* 1: Enable Artcanvas min phi mode */
|
||
|
|
||
|
ret = info->fts_write_reg(info, ®Add[0], 3);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: failed to set brush mode\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void set_touchable_area(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[3] = {FTS_CMD_SET_FUNCTION_ONOFF, FTS_FUNCTION_SET_TOUCHABLE_AREA, 0x00};
|
||
|
int ret;
|
||
|
|
||
|
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;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
info->touchable_area = sec->cmd_param[0];
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
input_info(true, &info->client->dev,
|
||
|
"%s: set 16:9 mode %s\n", __func__, info->touchable_area ? "enable" : "disable");
|
||
|
|
||
|
if (info->touchable_area == 0)
|
||
|
regAdd[2] = 0x00; /* 0: Disable 16:9 mode */
|
||
|
else
|
||
|
regAdd[2] = 0x01; /* 1: Enable 16:9 mode */
|
||
|
|
||
|
ret = info->fts_write_reg(info, ®Add[0], 3);
|
||
|
if (ret < 0) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: failed to set 16:9 mode\n", __func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void debug(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
info->debug_string = sec->cmd_param[0];
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: command is %d\n", __func__, info->debug_string);
|
||
|
|
||
|
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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_force_calibration(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
bool touch_on = false;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
|
||
|
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
||
|
__func__);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
info->tdata->external_factory = false;
|
||
|
#endif
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (info->rawdata_read_lock == 1) {
|
||
|
input_err(true, &info->client->dev, "%s: ramdump mode is running, %d\n",
|
||
|
__func__, info->rawdata_read_lock);
|
||
|
goto autotune_fail;
|
||
|
}
|
||
|
|
||
|
if (info->touch_count > 0) {
|
||
|
touch_on = true;
|
||
|
input_err(true, &info->client->dev, "%s: finger on touch(%d)\n", __func__, info->touch_count);
|
||
|
}
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
fts_release_all_finger(info);
|
||
|
|
||
|
if (touch_on) {
|
||
|
input_err(true, &info->client->dev, "%s: finger! do not run autotune\n", __func__);
|
||
|
} else {
|
||
|
input_info(true, &info->client->dev, "%s: run autotune\n", __func__);
|
||
|
|
||
|
input_err(true, &info->client->dev, "%s: RUN OFFSET CALIBRATION\n", __func__);
|
||
|
if (fts_execute_autotune(info, true) < 0) {
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
goto autotune_fail;
|
||
|
}
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
/* devide tclm case */
|
||
|
sec_tclm_case(info->tdata, sec->cmd_param[0]);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: param, %d, %c, %d\n", __func__,
|
||
|
sec->cmd_param[0], sec->cmd_param[0], info->tdata->root_of_calibration);
|
||
|
|
||
|
if (sec_execute_tclm_package(info->tdata, 1) < 0)
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: sec_execute_tclm_package\n", __func__);
|
||
|
|
||
|
sec_tclm_root_of_cal(info->tdata, CALPOSITION_NONE);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
fts_set_scanmode(info, info->scan_mode);
|
||
|
|
||
|
if (touch_on) {
|
||
|
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, strnlen(buff, sizeof(buff)));
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
info->tdata->external_factory = false;
|
||
|
#endif
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
return;
|
||
|
|
||
|
autotune_fail:
|
||
|
#ifdef TCLM_CONCEPT
|
||
|
info->tdata->external_factory = false;
|
||
|
#endif
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void fix_active_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
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 {
|
||
|
if (info->fts_power_state == FTS_POWER_STATE_ACTIVE)
|
||
|
fts_fix_active_mode(info, !!sec->cmd_param[0]);
|
||
|
info->fix_active_mode = !!sec->cmd_param[0];
|
||
|
}
|
||
|
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void touch_aging_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
char regAdd[3];
|
||
|
|
||
|
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 {
|
||
|
info->touch_aging_mode = sec->cmd_param[0];
|
||
|
|
||
|
if (info->touch_aging_mode) {
|
||
|
regAdd[0] = 0xA0;
|
||
|
regAdd[1] = 0x03;
|
||
|
regAdd[2] = 0x20;
|
||
|
|
||
|
info->fts_write_reg(info, ®Add[0], 3);
|
||
|
} else {
|
||
|
fts_reinit(info, false);
|
||
|
}
|
||
|
}
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void run_sram_test(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN];
|
||
|
u8 regAdd;
|
||
|
u8 data[FTS_EVENT_SIZE];
|
||
|
int rc, retry = 0;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
info->fts_systemreset(info, 0);
|
||
|
|
||
|
fts_interrupt_set(info, INT_DISABLE);
|
||
|
mutex_lock(&info->wait_for);
|
||
|
|
||
|
regAdd = FTS_CMD_RUN_SRAM_TEST;
|
||
|
rc = info->fts_write_reg(info, ®Add, 1);
|
||
|
if (rc < 0) {
|
||
|
input_err(true, &info->client->dev, "%s: failed to write cmd\n", __func__);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
fts_delay(300);
|
||
|
|
||
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
||
|
rc = -EIO;
|
||
|
regAdd = FTS_READ_ONE_EVENT;
|
||
|
while (info->fts_read_reg(info, ®Add, 1, data, FTS_EVENT_SIZE) > 0) {
|
||
|
if (data[0] != 0x00)
|
||
|
input_info(true, &info->client->dev,
|
||
|
"%s: event %02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n",
|
||
|
__func__, data[0], data[1], data[2], data[3],
|
||
|
data[4], data[5], data[6], data[7]);
|
||
|
|
||
|
if (data[0] == FTS_EVENT_PASS_REPORT && data[1] == FTS_EVENT_SRAM_TEST_RESULT) {
|
||
|
rc = 0; /* PASS */
|
||
|
break;
|
||
|
} else if (data[0] == FTS_EVENT_ERROR_REPORT && data[1] == FTS_EVENT_SRAM_TEST_RESULT) {
|
||
|
rc = 1; /* FAIL */
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (retry++ > FTS_RETRY_COUNT * 25) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: Time Over (%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X)\n",
|
||
|
__func__, data[0], data[1], data[2], data[3],
|
||
|
data[4], data[5], data[6], data[7]);
|
||
|
break;
|
||
|
}
|
||
|
fts_delay(20);
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
mutex_unlock(&info->wait_for);
|
||
|
|
||
|
if (rc < 0) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
snprintf(buff, sizeof(buff), "%d", rc);
|
||
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||
|
}
|
||
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
||
|
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "SRAM");
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
|
||
|
fts_reinit(info, false);
|
||
|
fts_interrupt_set(info, INT_ENABLE);
|
||
|
}
|
||
|
|
||
|
static void set_rear_selfie_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
|
||
|
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 {
|
||
|
info->rear_selfie_mode = sec->cmd_param[0];
|
||
|
snprintf(buff, sizeof(buff), "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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void ear_detect_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 data[2];
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (!info->board->support_ear_detect || sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
info->ed_enable = sec->cmd_param[0];
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
|
||
|
data[0] = FTS_CMD_SET_EAR_DETECT;
|
||
|
data[1] = info->ed_enable;
|
||
|
|
||
|
ret = fts_write_reg(info, data, 2);
|
||
|
input_info(true, &info->client->dev, "%s: %s, ret = %d\n",
|
||
|
__func__, info->ed_enable ? "enable" : "disable", ret);
|
||
|
}
|
||
|
|
||
|
if (info->board->hw_i2c_reset) {
|
||
|
cancel_delayed_work_sync(&info->fw_reset_work);
|
||
|
if (info->ed_enable == 3) {
|
||
|
info->fw_reset_cmd = 0x01;
|
||
|
} else {
|
||
|
info->fw_reset_cmd = 0x00;
|
||
|
}
|
||
|
schedule_work(&info->fw_reset_work.work);
|
||
|
}
|
||
|
|
||
|
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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void pocket_mode_enable(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 data[2];
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (!info->board->support_ear_detect || sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
} else {
|
||
|
info->pocket_mode = sec->cmd_param[0];
|
||
|
snprintf(buff, sizeof(buff), "OK");
|
||
|
|
||
|
data[0] = FTS_CMD_SET_POCKET_MODE;
|
||
|
data[1] = info->pocket_mode;
|
||
|
|
||
|
ret = fts_write_reg(info, data, 2);
|
||
|
input_info(true, &info->client->dev, "%s: %s, ret = %d\n",
|
||
|
__func__, info->pocket_mode ? "enable" : "disable", ret);
|
||
|
}
|
||
|
|
||
|
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, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void set_sip_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
|
||
|
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 {
|
||
|
ret = fts_set_sip_mode(info, (u8)sec->cmd_param[0]);
|
||
|
if (ret < 0) {
|
||
|
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, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
|
||
|
static void set_note_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
u8 regAdd[3];
|
||
|
int ret;
|
||
|
|
||
|
sec_cmd_set_default_result(sec);
|
||
|
|
||
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
||
|
input_err(true, &info->client->dev,
|
||
|
"%s: wrong param %d\n", __func__, sec->cmd_param[0]);
|
||
|
snprintf(buff, sizeof(buff), "NG");
|
||
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
regAdd[0] = FTS_CMD_SET_FUNCTION_ONOFF;
|
||
|
regAdd[1] = FTS_FUNCTION_SET_NOTE_MODE;
|
||
|
regAdd[2] = sec->cmd_param[0] & 0xFF;
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n",
|
||
|
__func__, sec->cmd_param[0] ? "enable" : "disable");
|
||
|
|
||
|
ret = fts_write_reg(info, regAdd, 3);
|
||
|
if (ret < 0) {
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
out:
|
||
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
}
|
||
|
|
||
|
static void set_game_mode(void *device_data)
|
||
|
{
|
||
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||
|
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
|
||
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
||
|
int ret;
|
||
|
u8 reg[3] = { 0 };
|
||
|
|
||
|
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 {
|
||
|
reg[0] = FTS_CMD_SET_FUNCTION_ONOFF;
|
||
|
reg[1] = FTS_FUNCTION_SET_GAME_MODE;
|
||
|
reg[2] = sec->cmd_param[0];
|
||
|
ret = fts_write_reg(info, reg, 3);
|
||
|
if (ret < 0) {
|
||
|
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, strnlen(buff, sizeof(buff)));
|
||
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
||
|
sec_cmd_set_cmd_exit(sec);
|
||
|
|
||
|
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
||
|
}
|
||
|
#endif
|
||
|
|