4997 lines
146 KiB
C
4997 lines
146 KiB
C
#ifdef SEC_TSP_FACTORY_TEST
|
|
|
|
#define BUFFER_MAX ((256 * 1024) - 16)
|
|
#define READ_CHUNK_SIZE 128 // (2 * 1024) - 16
|
|
|
|
enum {
|
|
TYPE_RAW_DATA = 0,
|
|
TYPE_FILTERED_DATA = 2,
|
|
TYPE_STRENGTH_DATA = 4,
|
|
TYPE_BASELINE_DATA = 6
|
|
};
|
|
|
|
enum {
|
|
BUILT_IN = 0,
|
|
UMS,
|
|
};
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
enum {
|
|
TYPE_TOUCHKEY_RAW = 0x34,
|
|
TYPE_TOUCHKEY_STRENGTH = 0x36,
|
|
TYPE_TOUCHKEY_THRESHOLD = 0x48,
|
|
};
|
|
#endif
|
|
|
|
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 get_x_num(void *device_data);
|
|
static void get_y_num(void *device_data);
|
|
static void get_checksum_data(void *device_data);
|
|
static void run_reference_read(void *device_data);
|
|
static void get_reference(void *device_data);
|
|
static void get_reference_all_data(void *device_data);
|
|
static void run_rawcap_read(void *device_data);
|
|
static void get_rawcap(void *device_data);
|
|
static void get_rawcap_all_data(void *device_data);
|
|
static void run_strength_read(void *device_data);
|
|
static void get_strength(void *device_data);
|
|
static void get_strength_all_data(void *device_data);
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
static void run_abscap_read(void *device_data);
|
|
static void run_absdelta_read(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_self_raw_read_all(void *device_data);
|
|
static void run_wtr_cx_data_read(void *device_data);
|
|
static void run_wtr_cx_data_read_all(void *device_data);
|
|
static void run_trx_short_test(void *device_data);
|
|
static void run_cx_data_read(void *device_data);
|
|
static void get_cx_data(void *device_data);
|
|
static void get_cx_all_data(void *device_data);
|
|
static void set_tsp_test_result(void *device_data);
|
|
static void get_tsp_test_result(void *device_data);
|
|
#ifdef FTS_SUPPORT_PARTIAL_DOWNLOAD
|
|
static void set_status_pureautotune(void *device_data);
|
|
static void get_status_pureautotune(void *device_data);
|
|
static void get_status_afe(void *device_data);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
static void hover_enable(void *device_data);
|
|
/* static void hover_no_sleep_enable(void *device_data); */
|
|
#endif
|
|
#ifdef CONFIG_GLOVE_TOUCH
|
|
static void glove_mode(void *device_data);
|
|
static void get_glove_sensitivity(void *device_data);
|
|
static void fast_glove_mode(void *device_data);
|
|
#endif
|
|
static void clear_cover_mode(void *device_data);
|
|
#ifdef USE_STYLUS_PEN
|
|
static void stylus_enable(void *device_data);
|
|
#endif
|
|
static void report_rate(void *device_data);
|
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
|
static void interrupt_control(void *device_data);
|
|
#endif
|
|
static void set_lowpower_mode(void *device_data);
|
|
static void set_deepsleep_mode(void *device_data);
|
|
static void active_sleep_enable(void *device_data);
|
|
static void set_wirelesscharger_mode(void *device_data);
|
|
#if defined(TSP_BOOSTER) && !defined(INPUT_BOOSTER_SYSFS)
|
|
static void boost_level(void *device_data);
|
|
#endif
|
|
static void second_screen_enable(void *device_data);
|
|
static void set_longpress_enable(void *device_data);
|
|
static void set_grip_detection(void *device_data);
|
|
static void set_sidescreen_x_length(void *device_data);
|
|
static void set_dead_zone(void *device_data);
|
|
static void dead_zone_enable(void *device_data);
|
|
static void select_wakeful_edge(void *device_data);
|
|
#ifdef SMARTCOVER_COVER
|
|
static void smartcover_cmd(void *device_data);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_MAINSCREEN_DISBLE
|
|
static void set_mainscreen_disable(void *device_data);
|
|
#endif
|
|
static void scrub_enable(void *device_data);
|
|
static void spay_enable(void *device_data);
|
|
static void aod_enable(void *device_data);
|
|
static void delay(void *device_data);
|
|
static void debug(void *device_data);
|
|
static void run_force_calibration(void *device_data);
|
|
static void set_rotation_status(void *device_data);
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
static void run_key_cx_data_read(void *device_data);
|
|
static void run_key_cm_data_read(void *device_data);
|
|
static void run_key_rawcap_read(void *device_data);
|
|
#endif
|
|
static void not_support_cmd(void *device_data);
|
|
|
|
static ssize_t fts_scrub_position(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
#ifdef FTS_SUPPORT_EDGE_POSITION
|
|
static ssize_t fts_edge_x_position(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
#endif
|
|
|
|
static struct sec_cmd stm_ft_cmds[] = {
|
|
{SEC_CMD("fw_update", fw_update),},
|
|
{SEC_CMD("get_fw_ver_bin", get_fw_ver_bin),},
|
|
{SEC_CMD("get_fw_ver_ic", get_fw_ver_ic),},
|
|
{SEC_CMD("get_config_ver", get_config_ver),},
|
|
{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("get_x_num", get_x_num),},
|
|
{SEC_CMD("get_y_num", get_y_num),},
|
|
{SEC_CMD("get_checksum_data", get_checksum_data),},
|
|
{SEC_CMD("run_reference_read", run_reference_read),},
|
|
{SEC_CMD("get_reference", get_reference),},
|
|
{SEC_CMD("get_reference_all_data", get_reference_all_data),},
|
|
{SEC_CMD("run_rawcap_read", run_rawcap_read),},
|
|
{SEC_CMD("get_rawcap", get_rawcap),},
|
|
{SEC_CMD("get_rawcap_all_data", get_rawcap_all_data),},
|
|
{SEC_CMD("run_strength_read", run_strength_read),},
|
|
{SEC_CMD("get_strength", get_strength),},
|
|
{SEC_CMD("get_strength_all_data", get_strength_all_data),},
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
{SEC_CMD("run_abscap_read" , run_abscap_read),},
|
|
{SEC_CMD("run_absdelta_read", run_absdelta_read),},
|
|
#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("get_ix_all_data", 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("get_self_raw_all_data", run_self_raw_read_all),},
|
|
{SEC_CMD("run_wtr_cx_data_read", run_wtr_cx_data_read),},
|
|
{SEC_CMD("run_wtr_cx_data_read_all", run_wtr_cx_data_read_all),},
|
|
{SEC_CMD("get_wtr_cx_all_data", run_wtr_cx_data_read_all),},
|
|
{SEC_CMD("run_trx_short_test", run_trx_short_test),},
|
|
{SEC_CMD("run_cx_data_read", run_cx_data_read),},
|
|
{SEC_CMD("get_cx_data", get_cx_data),},
|
|
{SEC_CMD("get_cx_all_data", get_cx_all_data),},
|
|
{SEC_CMD("set_tsp_test_result", set_tsp_test_result),},
|
|
{SEC_CMD("get_tsp_test_result", get_tsp_test_result),},
|
|
#ifdef FTS_SUPPORT_PARTIAL_DOWNLOAD
|
|
{SEC_CMD("set_status_pureautotune", set_status_pureautotune),},
|
|
{SEC_CMD("get_status_pureautotune", get_status_pureautotune),},
|
|
{SEC_CMD("get_status_afe", get_status_afe),},
|
|
#endif
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
{SEC_CMD("hover_enable", hover_enable),},
|
|
#endif
|
|
#ifdef CONFIG_GLOVE_TOUCH
|
|
{SEC_CMD("glove_mode", glove_mode),},
|
|
{SEC_CMD("get_glove_sensitivity", get_glove_sensitivity),},
|
|
{SEC_CMD("fast_glove_mode", fast_glove_mode),},
|
|
#endif
|
|
{SEC_CMD("clear_cover_mode", clear_cover_mode),},
|
|
#ifdef USE_STYLUS_PEN
|
|
{SEC_CMD("stylus_enable", stylus_enable),},
|
|
#endif
|
|
{SEC_CMD("report_rate", report_rate),},
|
|
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
|
{SEC_CMD("interrupt_control", interrupt_control),},
|
|
#endif
|
|
{SEC_CMD("set_lowpower_mode", set_lowpower_mode),},
|
|
{SEC_CMD("set_deepsleep_mode", set_deepsleep_mode),},
|
|
{SEC_CMD("active_sleep_enable", active_sleep_enable),},
|
|
{SEC_CMD("set_wirelesscharger_mode", set_wirelesscharger_mode),},
|
|
{SEC_CMD("select_wakeful_edge", select_wakeful_edge),},
|
|
#if defined(TSP_BOOSTER) && !defined(INPUT_BOOSTER_SYSFS)
|
|
{SEC_CMD("boost_level", boost_level),},
|
|
#endif
|
|
{SEC_CMD("second_screen_enable", second_screen_enable),},
|
|
{SEC_CMD("set_longpress_enable", set_longpress_enable),},
|
|
{SEC_CMD("set_grip_detection", set_grip_detection),},
|
|
{SEC_CMD("set_sidescreen_x_length", set_sidescreen_x_length),},
|
|
{SEC_CMD("set_dead_zone", set_dead_zone),},
|
|
{SEC_CMD("dead_zone_enable", dead_zone_enable),},
|
|
#ifdef SMARTCOVER_COVER
|
|
{SEC_CMD("smartcover_cmd", smartcover_cmd),},
|
|
#endif
|
|
#ifdef FTS_SUPPORT_MAINSCREEN_DISBLE
|
|
{SEC_CMD("set_mainscreen_disable", set_mainscreen_disable),},
|
|
#endif
|
|
{SEC_CMD("scrub_enable", scrub_enable),},
|
|
{SEC_CMD("spay_enable", spay_enable),},
|
|
{SEC_CMD("aod_enable", aod_enable),},
|
|
{SEC_CMD("delay", delay),},
|
|
{SEC_CMD("debug", debug),},
|
|
{SEC_CMD("run_force_calibration", run_force_calibration),},
|
|
{SEC_CMD("set_rotation_status", set_rotation_status),},
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
{SEC_CMD("run_key_cx_data_read", run_key_cx_data_read),},
|
|
{SEC_CMD("run_key_cm_data_read", run_key_cm_data_read),},
|
|
{SEC_CMD("run_key_rawcap_read", run_key_rawcap_read),},
|
|
#endif
|
|
{SEC_CMD("not_support_cmd", not_support_cmd),},
|
|
};
|
|
|
|
static DEVICE_ATTR(scrub_pos, S_IRUGO, fts_scrub_position, NULL);
|
|
#ifdef FTS_SUPPORT_EDGE_POSITION
|
|
static DEVICE_ATTR(edge_pos, S_IRUGO, fts_edge_x_position, NULL);
|
|
#endif
|
|
|
|
static struct attribute *sec_touch_facotry_attributes[] = {
|
|
&dev_attr_scrub_pos.attr,
|
|
#ifdef FTS_SUPPORT_EDGE_POSITION
|
|
&dev_attr_edge_pos.attr,
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group sec_touch_factory_attr_group = {
|
|
.attrs = sec_touch_facotry_attributes,
|
|
};
|
|
|
|
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;
|
|
tsp_debug_info(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];
|
|
tsp_debug_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 };
|
|
|
|
if (!info) {
|
|
printk(KERN_ERR "%s: No platform data found\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!info->input_dev) {
|
|
printk(KERN_ERR "%s: No input_dev data found\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
tsp_debug_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_id = 0;
|
|
info->scrub_x = 0;
|
|
info->scrub_y = 0;
|
|
|
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buff);
|
|
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_EDGE_POSITION
|
|
static ssize_t fts_edge_x_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 };
|
|
int edge_position_left, edge_position_right;
|
|
|
|
if (!info) {
|
|
pr_err("%s: No platform data found\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!info->input_dev) {
|
|
pr_err("%s: No input_dev data found\n",
|
|
__func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
edge_position_left = info->dt_data->grip_area;
|
|
edge_position_right = info->dt_data->max_x + 1 - info->dt_data->grip_area;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %d,%d\n", __func__,
|
|
edge_position_left, edge_position_right);
|
|
snprintf(buff, sizeof(buff), "%d,%d", edge_position_left, edge_position_right);
|
|
|
|
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buff);
|
|
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: \"%s(%d)\"\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
retval = fts_fw_update_on_hidden_menu(info, sec->cmd_param[0]);
|
|
|
|
if (retval < 0) {
|
|
snprintf(buff, SEC_CMD_STR_LEN, "%s", "NA");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
tsp_debug_info(true, &info->client->dev, "%s: failed [%d]\n", __func__, retval);
|
|
} else {
|
|
snprintf(buff, SEC_CMD_STR_LEN, "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: success [%d]\n", __func__, retval);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int fts_get_channel_info(struct fts_ts_info *info)
|
|
{
|
|
int rc = -1;
|
|
unsigned char cmd[4] = { 0xB2, 0x00, 0x14, 0x02 };
|
|
unsigned char data[FTS_EVENT_SIZE];
|
|
int retry = 0;
|
|
|
|
/* Rx/Tx channel information routine is using shared buffer with touch event block.
|
|
* So, when get Rx/Tx channel information, disable/enable interrupt(event block) */
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
|
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
|
|
fts_write_reg(info, &cmd[0], 4);
|
|
cmd[0] = READ_ONE_EVENT;
|
|
while (fts_read_reg
|
|
(info, &cmd[0], 1, (unsigned char *)data, FTS_EVENT_SIZE)) {
|
|
|
|
if ((data[0] == EVENTID_RESULT_READ_REGISTER)
|
|
&& (data[1] == cmd[1]) && (data[2] == cmd[2])) {
|
|
info->SenseChannelLength = data[3];
|
|
info->ForceChannelLength = data[4];
|
|
|
|
rc = 0;
|
|
break;
|
|
}
|
|
|
|
if (retry++ > 30) {
|
|
rc = -1;
|
|
tsp_debug_info(true, &info->client->dev, "Time over - wait for channel info\n");
|
|
break;
|
|
}
|
|
fts_delay(5);
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
dev_info(&info->client->dev, "%s: SenseChannel: %02d, Force Channel: %02d\n",
|
|
__func__, info->SenseChannelLength, info->ForceChannelLength);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static void fts_print_frame(struct fts_ts_info *info, short *min, short *max)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
unsigned char *pStr = NULL;
|
|
unsigned char pTmp[16] = { 0 };
|
|
|
|
pStr = kzalloc(6 * (info->SenseChannelLength + 1), GFP_KERNEL);
|
|
if (pStr == NULL) {
|
|
tsp_debug_info(true, &info->client->dev, "FTS pStr kzalloc failed\n");
|
|
return;
|
|
}
|
|
|
|
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
|
|
snprintf(pTmp, sizeof(pTmp), " ");
|
|
strncat(pStr, pTmp, 6 * info->SenseChannelLength);
|
|
|
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
|
snprintf(pTmp, sizeof(pTmp), "Rx%02d ", i);
|
|
strncat(pStr, pTmp, 6 * info->SenseChannelLength);
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "FTS %s\n", pStr);
|
|
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
|
|
snprintf(pTmp, sizeof(pTmp), " +");
|
|
strncat(pStr, pTmp, 6 * info->SenseChannelLength);
|
|
|
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
|
snprintf(pTmp, sizeof(pTmp), "------");
|
|
strncat(pStr, pTmp, 6 * info->SenseChannelLength);
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "FTS %s\n", pStr);
|
|
|
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
|
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
|
|
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", i);
|
|
strncat(pStr, pTmp, 6 * info->SenseChannelLength);
|
|
|
|
for (j = 0; j < info->SenseChannelLength; j++) {
|
|
snprintf(pTmp, sizeof(pTmp), "%5d ", info->pFrame[(i * info->SenseChannelLength) + j]);
|
|
|
|
if (i > 0) {
|
|
if (info->pFrame[(i * info->SenseChannelLength) + j] < *min)
|
|
*min = info->pFrame[(i * info->SenseChannelLength) + j];
|
|
|
|
if (info->pFrame[(i * info->SenseChannelLength) + j] > *max)
|
|
*max = info->pFrame[(i * info->SenseChannelLength) + j];
|
|
}
|
|
strncat(pStr, pTmp, 6 * info->SenseChannelLength);
|
|
}
|
|
tsp_debug_info(true, &info->client->dev, "FTS %s\n", pStr);
|
|
}
|
|
|
|
kfree(pStr);
|
|
}
|
|
|
|
static int fts_read_frame(struct fts_ts_info *info, unsigned char type, short *min,
|
|
short *max)
|
|
{
|
|
unsigned char pFrameAddress[8] = { 0xD0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 };
|
|
unsigned int FrameAddress = 0;
|
|
unsigned int writeAddr = 0;
|
|
unsigned int start_addr = 0;
|
|
unsigned int end_addr = 0;
|
|
unsigned int totalbytes = 0;
|
|
unsigned int remained = 0;
|
|
unsigned int readbytes = 0xFF;
|
|
unsigned int dataposition = 0;
|
|
unsigned char *pRead = NULL;
|
|
int rc = 0;
|
|
int ret = 0;
|
|
int i = 0;
|
|
pRead = kzalloc(BUFFER_MAX, GFP_KERNEL);
|
|
|
|
if (pRead == NULL) {
|
|
tsp_debug_info(true, &info->client->dev, "FTS pRead kzalloc failed\n");
|
|
rc = 1;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
pFrameAddress[2] = type;
|
|
totalbytes = info->SenseChannelLength * info->ForceChannelLength * 2;
|
|
ret = fts_read_reg(info, &pFrameAddress[0], 3, pRead, pFrameAddress[3]);
|
|
|
|
if (ret >= 0) {
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1)
|
|
FrameAddress = pRead[0] + (pRead[1] << 8);
|
|
else if ((info->digital_rev == FTS_DIGITAL_REV_2) || (info->digital_rev == FTS_DIGITAL_REV_3))
|
|
FrameAddress = pRead[1] + (pRead[2] << 8);
|
|
|
|
start_addr = FrameAddress+info->SenseChannelLength * 2;
|
|
end_addr = start_addr + totalbytes;
|
|
} else {
|
|
tsp_debug_info(true, &info->client->dev, "FTS read failed rc = %d \n", ret);
|
|
rc = 2;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
#ifdef DEBUG_MSG
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"FTS FrameAddress = %X\n", FrameAddress);
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"FTS start_addr = %X, end_addr = %X\n", start_addr, end_addr);
|
|
#endif
|
|
|
|
remained = totalbytes;
|
|
for (writeAddr = start_addr; writeAddr < end_addr; writeAddr += READ_CHUNK_SIZE) {
|
|
pFrameAddress[1] = (writeAddr >> 8) & 0xFF;
|
|
pFrameAddress[2] = writeAddr & 0xFF;
|
|
|
|
if (remained >= READ_CHUNK_SIZE)
|
|
readbytes = READ_CHUNK_SIZE;
|
|
else
|
|
readbytes = remained;
|
|
|
|
memset(pRead, 0x0, readbytes);
|
|
|
|
#ifdef DEBUG_MSG
|
|
tsp_debug_info(true, &info->client->dev, "FTS %02X%02X%02X readbytes=%d\n",
|
|
pFrameAddress[0], pFrameAddress[1],
|
|
pFrameAddress[2], readbytes);
|
|
|
|
#endif
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1) {
|
|
fts_read_reg(info, &pFrameAddress[0], 3, pRead, readbytes);
|
|
remained -= readbytes;
|
|
|
|
for (i = 0; i < readbytes; i += 2) {
|
|
info->pFrame[dataposition++] =
|
|
pRead[i] + (pRead[i + 1] << 8);
|
|
}
|
|
} else if ((info->digital_rev == FTS_DIGITAL_REV_2) || (info->digital_rev == FTS_DIGITAL_REV_3)) {
|
|
fts_read_reg(info, &pFrameAddress[0], 3, pRead, readbytes + 1);
|
|
remained -= readbytes;
|
|
|
|
for (i = 1; i < (readbytes+1); i += 2) {
|
|
info->pFrame[dataposition++] =
|
|
pRead[i] + (pRead[i + 1] << 8);
|
|
}
|
|
}
|
|
}
|
|
kfree(pRead);
|
|
|
|
#ifdef DEBUG_MSG
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"FTS writeAddr = %X, start_addr = %X, end_addr = %X\n",
|
|
writeAddr, start_addr, end_addr);
|
|
#endif
|
|
|
|
switch (type) {
|
|
case TYPE_RAW_DATA:
|
|
tsp_debug_info(true, &info->client->dev, "FTS [Raw Data : 0x%X%X]\n", pFrameAddress[0],
|
|
FrameAddress);
|
|
break;
|
|
case TYPE_FILTERED_DATA:
|
|
tsp_debug_info(true, &info->client->dev, "FTS [Filtered Data : 0x%X%X]\n",
|
|
pFrameAddress[0], FrameAddress);
|
|
break;
|
|
case TYPE_STRENGTH_DATA:
|
|
tsp_debug_info(true, &info->client->dev, "FTS [Strength Data : 0x%X%X]\n",
|
|
pFrameAddress[0], FrameAddress);
|
|
break;
|
|
case TYPE_BASELINE_DATA:
|
|
tsp_debug_info(true, &info->client->dev, "FTS [Baseline Data : 0x%X%X]\n",
|
|
pFrameAddress[0], FrameAddress);
|
|
break;
|
|
}
|
|
fts_print_frame(info, min, max);
|
|
|
|
ErrorExit:
|
|
return rc;
|
|
}
|
|
|
|
static int fts_panel_ito_test(struct fts_ts_info *info)
|
|
{
|
|
unsigned char cmd = READ_ONE_EVENT;
|
|
unsigned char data[FTS_EVENT_SIZE];
|
|
unsigned char regAdd[4] = {0xB0, 0x03, 0x60, 0xFB};
|
|
int retry = 0;
|
|
int result = -1;
|
|
|
|
info->fts_systemreset(info);
|
|
info->fts_wait_for_ready(info);
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
fts_command(info, SLEEPOUT);
|
|
fts_delay(20);
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_irq_enable(info, false);
|
|
fts_release_all_finger(info);
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
fts_command(info, 0xA7);
|
|
fts_delay(200);
|
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
|
while (fts_read_reg
|
|
(info, &cmd, 1, (unsigned char *)data, FTS_EVENT_SIZE)) {
|
|
|
|
if ((data[0] == 0x0F) && (data[1] == 0x05)) {
|
|
switch (data[2]) {
|
|
case 0x00:
|
|
result = 0;
|
|
break;
|
|
case 0x01:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Force channel [%d] open.\n",
|
|
data[3]);
|
|
break;
|
|
case 0x02:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Sense channel [%d] open.\n",
|
|
data[3]);
|
|
break;
|
|
case 0x03:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Force channel [%d] short to GND.\n",
|
|
data[3]);
|
|
break;
|
|
case 0x04:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Sense channel [%d] short to GND.\n",
|
|
data[3]);
|
|
break;
|
|
case 0x07:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Force channel [%d] short to force.\n",
|
|
data[3]);
|
|
break;
|
|
case 0x08:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Sennse channel [%d] short to sense.\n",
|
|
data[3]);
|
|
break;
|
|
case 0x0E:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : Sennse channel [%d] short to sense.\n",
|
|
data[3]);
|
|
break;
|
|
default:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"[FTS] ITO Test result : 0x%02x, %d\n",
|
|
data[2], data[3]);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (retry++ > 30) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"Time over - wait for result of ITO test\n");
|
|
break;
|
|
}
|
|
|
|
fts_delay(10);
|
|
}
|
|
|
|
fts_systemreset(info);
|
|
|
|
/* wait for ready event */
|
|
info->fts_wait_for_ready(info);
|
|
|
|
#ifdef FTS_SUPPORT_NOISE_PARAM
|
|
fts_set_noise_param(info);
|
|
#endif
|
|
if (info->stm_ver != STM_VER7)
|
|
fts_command(info, SLEEPOUT);
|
|
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
fts_command(info, SENSEON);
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
if (info->hover_enabled)
|
|
fts_command(info, FTS_CMD_HOVER_ON);
|
|
#endif
|
|
if (info->flip_enable) {
|
|
fts_set_cover_type(info, true);
|
|
}
|
|
#ifdef CONFIG_GLOVE_TOUCH
|
|
else {
|
|
if (info->glove_enabled)
|
|
fts_command(info, FTS_CMD_GLOVE_MODE_ON);
|
|
}
|
|
#endif
|
|
#ifdef FTS_SUPPORT_TA_MODE
|
|
if (info->TA_Pluged)
|
|
fts_command(info, FTS_CMD_CHARGER_PLUGGED);
|
|
#endif
|
|
|
|
info->touch_count = 0;
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
fts_irq_enable(info, true);
|
|
|
|
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[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buff, SEC_CMD_STR_LEN, "ST%02X%04X",
|
|
info->panel_revision,
|
|
info->fw_main_version_of_bin);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buff, SEC_CMD_STR_LEN, "ST%02X%04X",
|
|
info->panel_revision,
|
|
info->fw_main_version_of_ic);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buff, sizeof(buff), "%s_ST_%04X",
|
|
info->dt_data->model,
|
|
info->config_version_of_ic);
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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);
|
|
unsigned char cmd[4] = { 0xB2, 0x01, 0x62, 0x02 };
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
unsigned char data[FTS_EVENT_SIZE];
|
|
int retry = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->stm_ver == STM_VER7) {
|
|
cmd[1] = 0x01;
|
|
cmd[2] = 0x62;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
|
|
fts_write_reg(info, &cmd[0], 4);
|
|
|
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
|
cmd[0] = READ_ONE_EVENT;
|
|
|
|
while (info->fts_read_reg(info, &cmd[0], 1, (unsigned char *)data,
|
|
FTS_EVENT_SIZE)) {
|
|
|
|
if ((data[0] == EVENTID_RESULT_READ_REGISTER)
|
|
&& (data[1] == cmd[1]) && (data[2] == cmd[2])) {
|
|
snprintf(buff, sizeof(buff), "%d",
|
|
*(unsigned short *)&data[3]);
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(buff)));
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
break;
|
|
}
|
|
|
|
if (retry++ > 30) {
|
|
tsp_debug_err(true, info->dev,
|
|
"%s: Time Over\n", __func__);
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
}
|
|
|
|
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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
fts_irq_enable(info, false);
|
|
info->fts_power_ctrl(info->client, false);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
tsp_debug_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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
fts_irq_enable(info, true);
|
|
info->fts_power_ctrl(info->client, true);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
tsp_debug_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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
strncpy(buff, "STM", sizeof(buff));
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (strncmp(info->dt_data->project, "ZERO", 4) == 0) {
|
|
if (info->ic_product_id)
|
|
strncpy(buff, "FTS4BD056", sizeof(buff));
|
|
else
|
|
strncpy(buff, "FTS4BD062", sizeof(buff));
|
|
} else if (strncmp(info->dt_data->project, "HERO", 4) == 0) {
|
|
strncpy(buff, "FTS7BD50", sizeof(buff));
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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->SenseChannelLength);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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->ForceChannelLength);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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;
|
|
int retry = 0;
|
|
unsigned char regAdd[4];
|
|
unsigned char cmd[1];
|
|
unsigned char buf[5] = {0};
|
|
unsigned char data[FTS_EVENT_SIZE];
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
regAdd[0] = 0xb3;
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = 0x01;
|
|
info->fts_write_reg(info, regAdd, 3);
|
|
fts_delay(1);
|
|
|
|
regAdd[0] = 0xb1;
|
|
regAdd[1] = 0xEF;
|
|
regAdd[2] = 0xFC;
|
|
rc = info->fts_read_reg(info, regAdd, 3, buf, 5);
|
|
} else {
|
|
fts_release_all_finger(info);
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
|
|
regAdd[0] = 0xb2;
|
|
regAdd[1] = 0x07;
|
|
regAdd[2] = 0xfc;
|
|
regAdd[3] = 0x05;
|
|
info->fts_write_reg(info, regAdd, 4);
|
|
fts_delay(1);
|
|
|
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
|
cmd[0] = READ_ONE_EVENT;
|
|
|
|
while (info->fts_read_reg(info, &cmd[0], 1, (unsigned char *)data,
|
|
FTS_EVENT_SIZE)) {
|
|
if ((data[0] == EVENTID_RESULT_READ_REGISTER)
|
|
&& (data[1] == regAdd[1]) && (data[2] == regAdd[2])) {
|
|
rc = 0;
|
|
buf[1] = data[3];
|
|
buf[2] = data[4];
|
|
buf[3] = data[5];
|
|
buf[4] = data[6];
|
|
break;
|
|
}
|
|
|
|
if (retry++ > FTS_RETRY_COUNT) {
|
|
tsp_debug_err(true, info->dev,
|
|
"%s: Time Over\n", __func__);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
snprintf(buff, sizeof(buff), "%02X%02X%02X%02X", buf[1], buf[2], buf[3], buf[4]);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(buff)));
|
|
}
|
|
|
|
static void get_all_data(struct fts_ts_info *info, run_func_t run_func, void *data, enum data_type type)
|
|
{
|
|
struct sec_cmd_data *sec = &info->sec;
|
|
char mbuff[SEC_CMD_STR_LEN] = { 0 };
|
|
char *buff;
|
|
int node_num;
|
|
int page_size, len;
|
|
static int index = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
info->get_all_data = true;
|
|
|
|
if (!data) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: data is NULL\n",
|
|
__func__);
|
|
snprintf(mbuff, sizeof(mbuff), "%s", "FAIL");
|
|
sec_cmd_set_cmd_result(sec, mbuff, strnlen(mbuff, sizeof(mbuff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
goto all_data_out;
|
|
}
|
|
|
|
if (sec->cmd_param[0] == 0) {
|
|
run_func(sec);
|
|
if (sec->cmd_state != SEC_CMD_STATUS_RUNNING)
|
|
goto all_data_out;
|
|
index = 0;
|
|
} else {
|
|
if (index == 0) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Please do cmd_param '0' first\n",
|
|
__func__);
|
|
snprintf(mbuff, sizeof(mbuff), "%s", "NG");
|
|
sec_cmd_set_cmd_result(sec, mbuff, strnlen(mbuff, sizeof(mbuff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto all_data_out;
|
|
}
|
|
}
|
|
|
|
page_size = SEC_CMD_RESULT_STR_LEN - strlen(sec->cmd) - 10;
|
|
node_num = info->ForceChannelLength * info->SenseChannelLength;
|
|
buff = kzalloc(SEC_CMD_RESULT_STR_LEN, GFP_KERNEL);
|
|
if (buff != NULL) {
|
|
char *pBuf = buff;
|
|
for (; index < node_num; index++) {
|
|
switch(type) {
|
|
case DATA_UNSIGNED_CHAR: {
|
|
unsigned char *ddata = data;
|
|
len = snprintf(pBuf, 5, "%u,", ddata[index]);
|
|
break;}
|
|
case DATA_SIGNED_CHAR: {
|
|
char *ddata = data;
|
|
len = snprintf(pBuf, 5, "%d,", ddata[index]);
|
|
break;}
|
|
case DATA_UNSIGNED_SHORT: {
|
|
unsigned short *ddata = data;
|
|
len = snprintf(pBuf, 10, "%u,", ddata[index]);
|
|
break;}
|
|
case DATA_SIGNED_SHORT: {
|
|
short *ddata = data;
|
|
len = snprintf(pBuf, 10, "%d,", ddata[index]);
|
|
break;}
|
|
case DATA_UNSIGNED_INT: {
|
|
unsigned int *ddata = data;
|
|
len = snprintf(pBuf, 15, "%u,", ddata[index]);
|
|
break;}
|
|
case DATA_SIGNED_INT: {
|
|
int *ddata = data;
|
|
len = snprintf(pBuf, 15, "%d,", ddata[index]);
|
|
break;}
|
|
default:
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: not defined data type\n",
|
|
__func__);
|
|
snprintf(mbuff, sizeof(mbuff), "%s", "NG");
|
|
sec_cmd_set_cmd_result(sec, mbuff, strnlen(mbuff, sizeof(mbuff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
kfree(buff);
|
|
goto all_data_out;
|
|
}
|
|
|
|
if (page_size - len < 0) {
|
|
snprintf(pBuf, 5, "cont");
|
|
break;
|
|
} else {
|
|
page_size -= len;
|
|
pBuf += len;
|
|
}
|
|
}
|
|
if (index == node_num)
|
|
index = 0;
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, SEC_CMD_RESULT_STR_LEN);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
|
|
kfree(buff);
|
|
} else {
|
|
snprintf(mbuff, sizeof(mbuff), "%s", "kzalloc failed");
|
|
sec_cmd_set_cmd_result(sec, mbuff, strnlen(mbuff, sizeof(mbuff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
}
|
|
|
|
all_data_out:
|
|
info->get_all_data = false;
|
|
}
|
|
|
|
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->touch_stopped) {
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_read_frame(info, TYPE_BASELINE_DATA, &min, &max);
|
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
|
if (!info->get_all_data) {
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
tsp_debug_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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
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;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(buff)));
|
|
}
|
|
|
|
static void get_reference_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);
|
|
|
|
get_all_data(info, run_reference_read, info->pFrame, DATA_SIGNED_SHORT);
|
|
}
|
|
|
|
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;
|
|
|
|
#ifdef FTS_SUPPORT_PARTIAL_DOWNLOAD
|
|
//unsigned char regAdd[4] = {0xB0, 0x04, 0x49, 0x00}; // it's for Zero Prj
|
|
unsigned char regAdd[4] = {0xB0, 0x04, 0x48, 0x00}; // it's for Noble & Zero2 Prj
|
|
|
|
if (strncmp(info->dt_data->project, "ZERO", 4) == 0)
|
|
regAdd[2] = 0x49;
|
|
#endif
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max);
|
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
|
if (!info->get_all_data) {
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
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;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(buff)));
|
|
}
|
|
|
|
static void get_rawcap_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);
|
|
|
|
get_all_data(info, run_rawcap_read, info->pFrame, DATA_SIGNED_SHORT);
|
|
}
|
|
|
|
static void run_strength_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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
|
|
snprintf(buff, sizeof(buff), "%d,%d", min, max);
|
|
if (!info->get_all_data) {
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
static void get_strength(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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
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;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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);
|
|
|
|
get_all_data(info, run_strength_read, info->pFrame, DATA_SIGNED_SHORT);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
static void fts_read_self_frame(struct fts_ts_info *info, unsigned short oAddr)
|
|
{
|
|
struct sec_cmd_data *sec = &info->sec;
|
|
char buff[66] = {0, };
|
|
short *data = 0;
|
|
char temp[9] = {0, };
|
|
char temp2[512] = {0, };
|
|
int i;
|
|
int rc;
|
|
int retry = 1;
|
|
unsigned char regAdd[6] = {0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00};
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
if (!info->hover_enabled) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Hover is disabled\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP Hover disabled");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
while (!info->hover_ready) {
|
|
if (retry++ > 100) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [FTS] Timeout - Abs Raw Data Ready Event\n",
|
|
__func__);
|
|
break;
|
|
}
|
|
fts_delay(10);
|
|
}
|
|
|
|
regAdd[1] = (oAddr >> 8) & 0xff;
|
|
regAdd[2] = oAddr & 0xff;
|
|
rc = info->fts_read_reg(info, ®Add[0], 3, (unsigned char *)&buff[0], 5);
|
|
if (!rc) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
return;
|
|
}
|
|
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: Force Address : %02x%02x\n",
|
|
__func__, buff[1], buff[0]);
|
|
tsp_debug_info(true, &info->client->dev, "%s: Sense Address : %02x%02x\n",
|
|
__func__, buff[3], buff[2]);
|
|
regAdd[1] = buff[3];
|
|
regAdd[2] = buff[2];
|
|
regAdd[4] = buff[1];
|
|
regAdd[5] = buff[0];
|
|
} else if ((info->digital_rev == FTS_DIGITAL_REV_2) || (info->digital_rev == FTS_DIGITAL_REV_3)) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: Force Address : %02x%02x\n",
|
|
__func__, buff[2], buff[1]);
|
|
tsp_debug_info(true, &info->client->dev, "%s: Sense Address : %02x%02x\n",
|
|
__func__, buff[4], buff[3]);
|
|
regAdd[1] = buff[4];
|
|
regAdd[2] = buff[3];
|
|
regAdd[4] = buff[2];
|
|
regAdd[5] = buff[1];
|
|
}
|
|
|
|
rc = info->fts_read_reg(info, ®Add[0], 3,
|
|
(unsigned char *)&buff[0],
|
|
info->SenseChannelLength * 2 + 1);
|
|
if (!rc) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
return;
|
|
}
|
|
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1)
|
|
data = (short *)&buff[0];
|
|
else
|
|
data = (short *)&buff[1];
|
|
|
|
memset(temp2, 0, 512);
|
|
|
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Rx [%d] = %d\n", __func__,
|
|
i,
|
|
*data);
|
|
memset(temp, 0, 9);
|
|
snprintf(temp, SEC_CMD_STR_LEN, "%d,", *data);
|
|
strncat(temp2, temp, 9);
|
|
data++;
|
|
}
|
|
|
|
rc = info->fts_read_reg(info, ®Add[3], 3,
|
|
(unsigned char *)&buff[0],
|
|
info->ForceChannelLength*2 + 1);
|
|
if (!rc) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
return;
|
|
}
|
|
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1)
|
|
data = (short *)&buff[0];
|
|
else
|
|
data = (short *)&buff[1];
|
|
|
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Tx [%d] = %d\n", __func__, i, *data);
|
|
snprintf(temp, SEC_CMD_STR_LEN, "%d,", *data);
|
|
strncat(temp2, temp, 9);
|
|
data++;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, temp2, strnlen(temp2, sizeof(temp2)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
static void run_abscap_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);
|
|
fts_read_self_frame(info, 0x000E);
|
|
}
|
|
|
|
static void run_absdelta_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);
|
|
fts_read_self_frame(info, 0x0012);
|
|
}
|
|
#endif
|
|
|
|
#define FTS_F_WIX1_ADDR 0x1FE7
|
|
#define FTS_S_WIX1_ADDR 0x1FE8
|
|
#define FTS_F_WIX2_ADDR 0x18FD
|
|
#define FTS_S_WIX2_ADDR 0x1929
|
|
#define FTS_WATER_SELF_RAW_ADDR 0x1A
|
|
|
|
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 };
|
|
|
|
unsigned short max_tx_ix_sum = 0;
|
|
unsigned short min_tx_ix_sum = 0xFFFF;
|
|
|
|
unsigned short max_rx_ix_sum = 0;
|
|
unsigned short min_rx_ix_sum = 0xFFFF;
|
|
|
|
unsigned char tx_ix2[info->ForceChannelLength + 4];
|
|
unsigned char rx_ix2[info->SenseChannelLength + 4];
|
|
|
|
unsigned char regAdd[FTS_EVENT_SIZE];
|
|
unsigned short tx_ix1 = 0, rx_ix1 = 0;
|
|
|
|
unsigned short force_ix_data[info->ForceChannelLength * 2 + 1];
|
|
unsigned short sense_ix_data[info->SenseChannelLength * 2 + 1];
|
|
|
|
int buff_size, i = 0;
|
|
char *mbuff = NULL;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
// fts_command(info, SLEEPIN); // Sleep In for INT disable
|
|
|
|
fts_irq_enable(info, false);
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
|
|
if (info->stm_ver == STM_VER7) {
|
|
fts_command(info, SENSEOFF);
|
|
} else {
|
|
fts_systemreset(info);
|
|
fts_delay(50);
|
|
fts_wait_for_ready(info);
|
|
|
|
fts_command(info, SLEEPOUT);
|
|
|
|
fts_delay(50);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
|
|
}
|
|
#endif
|
|
|
|
fts_command(info, FLUSHBUFFER); // Clear FIFO
|
|
fts_delay(50);
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
unsigned short ix1_addr = FTS_F_WIX1_ADDR;
|
|
unsigned short ix2_tx_addr = FTS_F_WIX2_ADDR;
|
|
unsigned short ix2_rx_addr = FTS_S_WIX2_ADDR;
|
|
|
|
unsigned char buf[FTS_EVENT_SIZE] = {0};
|
|
unsigned char r_addr = READ_ONE_EVENT;
|
|
int retry = 0;
|
|
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (ix1_addr >> 8)&0xff;
|
|
regAdd[2] = (ix1_addr&0xff);
|
|
regAdd[3] = 0x04;
|
|
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
fts_delay(1);
|
|
|
|
retry = FTS_RETRY_COUNT * 3;
|
|
do {
|
|
if (retry < 0) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: failed to compare buf,[%x][%x][%x][%x] break1!\n",
|
|
__func__, buf[1], buf[2], regAdd[1], regAdd[2]);
|
|
break;
|
|
}
|
|
fts_delay(10);
|
|
fts_read_reg(info, &r_addr, 1, &buf[0], FTS_EVENT_SIZE);
|
|
retry--;
|
|
} while (buf[1] != regAdd[1] || buf[2] != regAdd[2]);
|
|
|
|
//read fifo
|
|
tx_ix1 = (short)buf[3] * 4;
|
|
rx_ix1 = (short)buf[4] * 4;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: tx_ix1 : %d, rx_ix1 : %d (%d, %d)\n",
|
|
__func__, tx_ix1, rx_ix1, buf[3], buf[4]);
|
|
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (ix2_tx_addr >>8)&0xff;
|
|
regAdd[2] = (ix2_tx_addr & 0xff);
|
|
|
|
for (i = 0; i < info->ForceChannelLength / 4 + 1; i++) {
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
fts_delay(1);
|
|
|
|
retry = FTS_RETRY_COUNT * 3;
|
|
do {
|
|
if (retry < 0) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: failed to compare buf,[%x][%x][%x][%x] break2!\n",
|
|
__func__, buf[1], buf[2], regAdd[1], regAdd[2]);
|
|
break;
|
|
}
|
|
fts_delay(10);
|
|
fts_read_reg(info, &r_addr, 1, &buf[0], FTS_EVENT_SIZE);
|
|
retry--;
|
|
} while (buf[1] != regAdd[1] || buf[2] != regAdd[2]);
|
|
|
|
//read fifo
|
|
tx_ix2[i * 4] = buf[3];
|
|
tx_ix2[i * 4 + 1] = buf[4];
|
|
tx_ix2[i * 4 + 2] = buf[5];
|
|
tx_ix2[i * 4 + 3] = buf[6];
|
|
|
|
ix2_tx_addr += 4;
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (ix2_tx_addr >> 8) & 0xff;
|
|
regAdd[2] = (ix2_tx_addr & 0xff);
|
|
}
|
|
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (ix2_rx_addr >> 8) & 0xff;
|
|
regAdd[2] = (ix2_rx_addr & 0xff);
|
|
|
|
for (i = 0; i < info->SenseChannelLength / 4 + 1;i++) {
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
fts_delay(1);
|
|
|
|
retry = FTS_RETRY_COUNT * 3;
|
|
do {
|
|
if (retry < 0) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: failed to compare buf,[%x][%x][%x][%x] break3!\n",
|
|
__func__, buf[1], buf[2], regAdd[1], regAdd[2]);
|
|
|
|
break;
|
|
}
|
|
fts_delay(10);
|
|
fts_read_reg(info, &r_addr, 1, &buf[0], FTS_EVENT_SIZE);
|
|
retry--;
|
|
} while (buf[1] != regAdd[1] || buf[2] != regAdd[2]);
|
|
|
|
//read fifo
|
|
rx_ix2[i * 4] = buf[3];
|
|
rx_ix2[i * 4 + 1] = buf[4];
|
|
rx_ix2[i * 4 + 2] = buf[5];
|
|
rx_ix2[i * 4 + 3] = buf[6];
|
|
|
|
ix2_rx_addr += 4;
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (ix2_rx_addr >> 8) & 0xff;
|
|
regAdd[2] = (ix2_rx_addr & 0xff);
|
|
}
|
|
|
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
|
force_ix_data[i] = tx_ix1 + tx_ix2[i];
|
|
if (max_tx_ix_sum < tx_ix1 + tx_ix2[i])
|
|
max_tx_ix_sum = tx_ix1 + tx_ix2[i];
|
|
if (min_tx_ix_sum > tx_ix1 + tx_ix2[i])
|
|
min_tx_ix_sum = tx_ix1 + tx_ix2[i];
|
|
}
|
|
|
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
|
sense_ix_data[i] = rx_ix1 + rx_ix2[i];
|
|
if (max_rx_ix_sum < rx_ix1 + rx_ix2[i])
|
|
max_rx_ix_sum = rx_ix1 + rx_ix2[i];
|
|
if (min_rx_ix_sum > rx_ix1 + rx_ix2[i])
|
|
min_rx_ix_sum = rx_ix1 + rx_ix2[i];
|
|
}
|
|
} else {
|
|
int comp_header_addr, comp_start_tx_addr, comp_start_rx_addr;
|
|
unsigned int rx_num, tx_num;
|
|
|
|
/* Request compensation data */
|
|
regAdd[0] = 0xB8;
|
|
regAdd[1] = 0x20; // SELF IX
|
|
regAdd[2] = 0x00;
|
|
fts_write_reg(info, ®Add[0], 3);
|
|
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, 0x20, 0x00);
|
|
|
|
/* Read an address of compensation data */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = 0x50;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], 4);
|
|
comp_header_addr = buff[1] + (buff[2] << 8);
|
|
|
|
/* Read header of compensation area */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_header_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
|
|
tx_num = buff[5];
|
|
rx_num = buff[6];
|
|
|
|
tx_ix1 = (short) buff[10] * 4; // Self TX Ix1
|
|
rx_ix1 = (short) buff[11] * 2; // Self RX Ix1
|
|
|
|
comp_start_tx_addr = comp_header_addr + 0x10;
|
|
comp_start_rx_addr = comp_start_tx_addr + tx_num;
|
|
|
|
memset(tx_ix2, 0x0, tx_num);
|
|
memset(rx_ix2, 0x0, rx_num);
|
|
|
|
/* Read Self TX Ix2 */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_start_tx_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_start_tx_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &tx_ix2[0], tx_num + 1);
|
|
|
|
/* Read Self RX Ix2 */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_start_rx_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_start_rx_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &rx_ix2[0], rx_num + 1);
|
|
|
|
for (i = 0; i < info->ForceChannelLength; i++) {
|
|
force_ix_data[i] = tx_ix1 + tx_ix2[i + 1];
|
|
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];
|
|
}
|
|
|
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
|
sense_ix_data[i] = rx_ix1 + rx_ix2[i + 1];
|
|
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];
|
|
}
|
|
}
|
|
|
|
tsp_debug_info(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 );
|
|
tsp_debug_info(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 );
|
|
|
|
fts_systemreset(info);
|
|
fts_wait_for_ready(info);
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
fts_command(info, SLEEPOUT);
|
|
fts_delay(1);
|
|
}
|
|
fts_command(info, SENSEON);
|
|
#ifdef FTS_SUPPORT_WATER_MODE
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_WATER_SELF_DONE);
|
|
#else
|
|
if( info->stm_ver == STM_VER7)
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE_D3);
|
|
else
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
#endif
|
|
|
|
fts_irq_enable(info, true);
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
if (allnode == true) {
|
|
buff_size = (info->ForceChannelLength + info->SenseChannelLength + 2)*5;
|
|
mbuff = kzalloc(buff_size, GFP_KERNEL);
|
|
}
|
|
if (mbuff != NULL) {
|
|
char *pBuf = mbuff;
|
|
int num, n, a, fzero, j;
|
|
char cnum;
|
|
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++ = ',';
|
|
tsp_debug_info(true, &info->client->dev, "%d ", force_ix_data[i]);
|
|
}
|
|
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++ = ',';
|
|
tsp_debug_info(true, &info->client->dev, "%d ", sense_ix_data[i]);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, mbuff, buff_size);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
kfree(mbuff);
|
|
}
|
|
else {
|
|
if (allnode == true) {
|
|
snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
} 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;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
tsp_debug_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);
|
|
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);
|
|
fts_read_ix_data(info, true);
|
|
}
|
|
|
|
static void fts_read_self_raw_frame(struct fts_ts_info *info, unsigned short oAddr, bool allnode)
|
|
{
|
|
struct sec_cmd_data *sec = &info->sec;
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
unsigned char D0_offset = 1;
|
|
unsigned char regAdd[3] = {0xD0, 0x00, 0x00};
|
|
unsigned char ReadData[info->SenseChannelLength * 2 + 1];
|
|
unsigned short self_force_raw_data[info->ForceChannelLength * 2 + 1];
|
|
unsigned short self_sense_raw_data[info->SenseChannelLength * 2 + 1];
|
|
unsigned int FrameAddress = 0;
|
|
unsigned char count=0;
|
|
int buff_size,i,j;
|
|
char *mbuff = NULL;
|
|
int num,n,a,fzero;
|
|
char cnum;
|
|
unsigned short min_tx_self_raw_data = 0xFFFF;
|
|
unsigned short max_tx_self_raw_data = 0;
|
|
unsigned short min_rx_self_raw_data = 0xFFFF;
|
|
unsigned short max_rx_self_raw_data = 0;
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
// fts_command(info, SLEEPIN); // Sleep In for INT disable
|
|
|
|
fts_irq_enable(info, false);
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
// fts_command(info, SENSEOFF);
|
|
|
|
fts_delay(50);
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
|
|
}
|
|
#endif
|
|
|
|
fts_command(info, FLUSHBUFFER); // Clear FIFO
|
|
fts_delay(50);
|
|
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = oAddr;
|
|
fts_read_reg(info, regAdd, 3, &ReadData[0], 4);
|
|
|
|
FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); // D1 : DOFFSET = 0, D2 : DOFFSET : 1
|
|
|
|
regAdd[1] = (FrameAddress >> 8) & 0xFF;
|
|
regAdd[2] = FrameAddress & 0xFF;
|
|
|
|
fts_read_reg(info, regAdd, 3, &ReadData[0], info->ForceChannelLength * 2 + 1);
|
|
|
|
for (count = 0; count < info->ForceChannelLength; count++) {
|
|
self_force_raw_data[count] = ReadData[count * 2 + D0_offset]
|
|
+ (ReadData[count * 2 + D0_offset + 1] << 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];
|
|
}
|
|
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = oAddr + 2;
|
|
fts_read_reg(info, regAdd, 3, &ReadData[0], 4);
|
|
|
|
FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); // D1 : DOFFSET = 0, D2 : DOFFSET : 1
|
|
|
|
regAdd[1] = (FrameAddress >> 8) & 0xFF;
|
|
regAdd[2] = FrameAddress & 0xFF;
|
|
|
|
fts_read_reg(info, regAdd, 3, &ReadData[0], info->SenseChannelLength * 2 + 1);
|
|
|
|
for (count = 0; count < info->SenseChannelLength; count++) {
|
|
self_sense_raw_data[count] = ReadData[count * 2 + D0_offset]
|
|
+ (ReadData[count * 2 + D0_offset + 1] << 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];
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s MIN_TX_SELF_RAW: %d MAX_TX_SELF_RAW : %d\n",
|
|
__func__, min_tx_self_raw_data, max_tx_self_raw_data );
|
|
tsp_debug_info(true, &info->client->dev, "%s MIN_RX_SELF_RAW : %d MIN_RX_SELF_RAW : %d\n",
|
|
__func__, min_rx_self_raw_data, max_rx_self_raw_data );
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
fts_command(info, SLEEPOUT);
|
|
fts_delay(1);
|
|
}
|
|
fts_command(info, SENSEON);
|
|
#ifdef FTS_SUPPORT_WATER_MODE
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_WATER_SELF_DONE);
|
|
#else
|
|
if( info->stm_ver == STM_VER7)
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE_D3);
|
|
else
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
#endif
|
|
|
|
fts_irq_enable(info, true);
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
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 = self_force_raw_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++ = ',';
|
|
tsp_debug_info(true, &info->client->dev, "%d ", self_force_raw_data[i]);
|
|
}
|
|
for (i = 0; i < info->SenseChannelLength; i++) {
|
|
num = self_sense_raw_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++ = ',';
|
|
tsp_debug_info(true, &info->client->dev, "%d ", self_sense_raw_data[i]);
|
|
}
|
|
|
|
|
|
sec_cmd_set_cmd_result(sec, mbuff, buff_size);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
kfree(mbuff);
|
|
}
|
|
else {
|
|
if (allnode == true) {
|
|
snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
} else {
|
|
snprintf(buff, sizeof(buff), "%d,%d,%d,%d", min_tx_self_raw_data, max_tx_self_raw_data, min_rx_self_raw_data, max_rx_self_raw_data);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
tsp_debug_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);
|
|
fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR, 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);
|
|
fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR, true);
|
|
}
|
|
|
|
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 ret = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
ret = fts_panel_ito_test(info);
|
|
if (ret == 0) {
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
} else {
|
|
snprintf(buff, sizeof(buff), "%s", "FAIL");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_PARTIAL_DOWNLOAD
|
|
static void set_status_pureautotune(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;
|
|
unsigned char regAdd[2] = {0xC2, 0x0E};
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_command(info, SENSEOFF);
|
|
fts_delay(50);
|
|
|
|
fts_irq_enable(info, false);
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_delay(50);
|
|
|
|
if (sec->cmd_param[0]==0)
|
|
regAdd[0] = 0xC2;
|
|
else
|
|
regAdd[0] = 0xC1;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: CMD[%2X]\n",__func__,regAdd[0]);
|
|
|
|
rc = fts_write_reg(info, regAdd, 2);
|
|
msleep(20);
|
|
if (info->stm_ver != STM_VER7)
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_PURE_AUTOTUNE_FLAG_ERASE_FINISH);
|
|
|
|
info->fts_command(info, FTS_CMD_SAVE_CX_TUNING);
|
|
msleep(230);
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
|
|
|
|
info->fts_systemreset(info);
|
|
fts_wait_for_ready(info);
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
info->fts_command(info, SLEEPOUT);
|
|
msleep(50);
|
|
}
|
|
info->fts_command(info, SENSEON);
|
|
|
|
fts_irq_enable(info, true);
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
if (!rc)
|
|
snprintf(buff, sizeof(buff), "%s", "FAIL");
|
|
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;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
static void get_status_pureautotune(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;
|
|
unsigned char regAdd[3];
|
|
unsigned char buf[5];
|
|
int retVal = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
regAdd[0] = 0xd0;
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = 0x58;
|
|
if (info->stm_ver == STM_VER7)
|
|
regAdd[2] = 0x4E;
|
|
rc = info->fts_read_reg(info, regAdd, 3, buf, 4);
|
|
if (!rc) {
|
|
tsp_debug_info(true, info->dev, "%s: PureAutotune Information Read Fail!! [Data : %2X%2X]\n", __func__, buf[1], buf[2]);
|
|
} else {
|
|
if((buf[1] == 0xA5) && (buf[2] == 0x96))
|
|
retVal = 1;
|
|
tsp_debug_info(true, info->dev,
|
|
"%s: PureAutotune Information !! [Data : %2X%2X]\n", __func__, buf[1], buf[2]);
|
|
}
|
|
snprintf(buff, sizeof(buff), "%d", retVal);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
static void get_status_afe(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 = 0;
|
|
unsigned char regAdd[3];
|
|
unsigned char buf[5];
|
|
int retVal = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
regAdd[0] = 0xd0;
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = 0x5A;
|
|
if (info->stm_ver == STM_VER7)
|
|
regAdd[2] = 0x53;
|
|
rc = info->fts_read_reg(info, regAdd, 3, buf, 4);
|
|
if (!rc) {
|
|
tsp_debug_info(true, info->dev, "%s: Final AFE [Data : %2X] Read Fail AFE Ver [Data : %2X]\n", __func__, buf[1], buf[2]);
|
|
}
|
|
if (buf[1])
|
|
retVal = 1;
|
|
tsp_debug_info(true, info->dev, "%s: Final AFE [Data : %2X] AFE Ver [Data : %2X]\n", __func__, buf[1], buf[2]);
|
|
|
|
snprintf(buff, sizeof(buff), "%d", retVal);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
#endif
|
|
|
|
#define FTS_MAX_TX_LENGTH 44
|
|
#define FTS_MAX_RX_LENGTH 64
|
|
|
|
#define FTS_CX2_READ_LENGTH 4
|
|
#define FTS_CX2_ADDR_OFFSET 3
|
|
#define FTS_CX2_TX_START 0
|
|
#define FTS_CX2_BASE_ADDR 0x1000
|
|
|
|
#define FTS_WTR_TX_CX2_BASE_ADDR 0x1969
|
|
#define FTS_WTR_RX_CX2_BASE_ADDR 0x198A
|
|
|
|
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 };
|
|
unsigned char ReadData[info->ForceChannelLength][info->SenseChannelLength + FTS_CX2_READ_LENGTH];
|
|
unsigned char regAdd[8];
|
|
unsigned int addr, rx_num, tx_num;
|
|
int i, j;
|
|
unsigned char *pStr = NULL;
|
|
unsigned char pTmp[16] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_irq_enable(info, false);
|
|
fts_release_all_finger(info);
|
|
|
|
if (info->stm_ver == STM_VER7) {
|
|
fts_command(info, SENSEOFF);
|
|
fts_delay(50);
|
|
} else {
|
|
fts_systemreset(info);
|
|
fts_delay(50);
|
|
fts_wait_for_ready(info);
|
|
|
|
fts_command(info, SLEEPOUT);
|
|
fts_delay(50);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_command(info, FTS_CMD_KEY_SENSE_OFF); // Key Sensor OFF
|
|
#endif
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(50);
|
|
|
|
tx_num = info->ForceChannelLength;
|
|
rx_num = info->SenseChannelLength;
|
|
|
|
pStr = kzalloc(4 * (rx_num + 1), GFP_KERNEL);
|
|
if (pStr == NULL) {
|
|
tsp_debug_info(true, &info->client->dev, "FTS pStr kzalloc failed\n");
|
|
return;
|
|
}
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
int cx_rx_length, max_tx_length, max_rx_length;
|
|
int address_offset = 0, start_tx_offset = 0, retry = 0;
|
|
unsigned char r_addr = READ_ONE_EVENT;
|
|
unsigned char buf[8];
|
|
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1) {
|
|
max_tx_length = FTS_MAX_TX_LENGTH - 4;
|
|
max_rx_length = FTS_MAX_RX_LENGTH - 4;
|
|
} else {
|
|
max_tx_length = FTS_MAX_TX_LENGTH;
|
|
max_rx_length = FTS_MAX_RX_LENGTH;
|
|
}
|
|
|
|
start_tx_offset = FTS_CX2_TX_START * max_rx_length / FTS_CX2_READ_LENGTH * FTS_CX2_ADDR_OFFSET;
|
|
address_offset = max_rx_length / FTS_CX2_READ_LENGTH;
|
|
|
|
dev_info(&info->client->dev, "%s: start\n", __func__);
|
|
for (j = 0; j < tx_num; j++) {
|
|
|
|
memset(pStr, 0x0, 4 * (rx_num + 1));
|
|
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
|
|
strncat(pStr, pTmp, 4 * rx_num);
|
|
|
|
addr = FTS_CX2_BASE_ADDR + (j * address_offset * FTS_CX2_ADDR_OFFSET) + start_tx_offset;
|
|
|
|
if (rx_num % FTS_CX2_READ_LENGTH != 0)
|
|
cx_rx_length = rx_num / FTS_CX2_READ_LENGTH + 1;
|
|
else
|
|
cx_rx_length = rx_num / FTS_CX2_READ_LENGTH;
|
|
|
|
for (i = 0; i < cx_rx_length; i++) {
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (addr >> 8) & 0xff;
|
|
regAdd[2] = (addr & 0xff);
|
|
regAdd[3] = 0x04;
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
|
|
retry = 100;
|
|
do {
|
|
if (retry < 0) {
|
|
dev_err(&info->client->dev,
|
|
"%s: failed to compare buf, break!\n", __func__);
|
|
break;
|
|
}
|
|
|
|
fts_read_reg(info, &r_addr, 1, &buf[0], FTS_EVENT_SIZE);
|
|
retry--;
|
|
} while (buf[1] != regAdd[1] || buf[2] != regAdd[2]);
|
|
|
|
ReadData[j][i * 4] = buf[3] & 0x3F;
|
|
ReadData[j][i * 4 + 1] = (buf[3] & 0xC0) >> 6 | (buf[4] & 0x0F) << 2;
|
|
ReadData[j][i * 4 + 2] = ((buf[4] & 0xF0) >> 4) | ((buf[5] & 0x03) << 4);
|
|
ReadData[j][i * 4 + 3] = buf[5] >> 2;
|
|
addr = addr + 3;
|
|
|
|
snprintf(pTmp, sizeof(pTmp), "%3d%3d%3d%3d ",
|
|
ReadData[j][i*4], ReadData[j][i*4+1], ReadData[j][i*4+2], ReadData[j][i*4+3]);
|
|
strncat(pStr, pTmp, 4 * rx_num);
|
|
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "FTS %s\n", pStr);
|
|
|
|
}
|
|
} else {
|
|
int comp_header_addr, comp_start_addr;
|
|
|
|
/* Request compensation data */
|
|
regAdd[0] = 0xB8;
|
|
regAdd[1] = 0x04; // MUTUAL CX (LPA)
|
|
regAdd[2] = 0x00;
|
|
fts_write_reg(info, ®Add[0], 3);
|
|
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, 0x04, 0x00);
|
|
|
|
/* Read an address of compensation data */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = 0x50;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], 4);
|
|
comp_header_addr = buff[1] + (buff[2] << 8);
|
|
|
|
/* Read header of compensation area */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_header_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
|
|
tx_num = buff[5];
|
|
rx_num = buff[6];
|
|
comp_start_addr = comp_header_addr + 0x10;
|
|
|
|
/* Read compensation data */
|
|
for (j = 0; j < tx_num; j++) {
|
|
memset(&ReadData[j], 0x0, rx_num);
|
|
memset(pStr, 0x0, 4 * (rx_num + 1));
|
|
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
|
|
strncat(pStr, pTmp, 4 * rx_num);
|
|
|
|
addr = comp_start_addr + (rx_num * j);
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (addr >> 8) & 0xFF;
|
|
regAdd[2] = addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1);
|
|
for (i = 0; i < rx_num; i++) {
|
|
snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i]);
|
|
strncat(pStr, pTmp, 4 * rx_num);
|
|
}
|
|
tsp_debug_info(true, &info->client->dev, "FTS %s\n", pStr);
|
|
}
|
|
}
|
|
|
|
if (info->cx_data) {
|
|
for (j = 0; j < tx_num; j++) {
|
|
for(i = 0; i < rx_num; i++)
|
|
info->cx_data[(j * rx_num) + i] = ReadData[j][i];
|
|
}
|
|
}
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
fts_irq_enable(info, true);
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
fts_command(info, SENSEON);
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
#endif
|
|
kfree(pStr);
|
|
|
|
if (!info->get_all_data) {
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
tsp_debug_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->touch_stopped || !info->cx_data) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
node = fts_check_index(info);
|
|
if (node < 0)
|
|
return;
|
|
|
|
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;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(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);
|
|
|
|
get_all_data(info, run_cx_data_read, info->cx_data, DATA_UNSIGNED_CHAR);
|
|
}
|
|
|
|
static void fts_read_wtr_cx_data(struct fts_ts_info *info, bool allnode)
|
|
{
|
|
struct sec_cmd_data *sec = &info->sec;
|
|
char buff[512] = { 0 };
|
|
unsigned char regAdd[8];
|
|
unsigned char *result_tx, *result_rx;
|
|
char buf[8];
|
|
char temp[8];
|
|
unsigned char r_addr = READ_ONE_EVENT;
|
|
unsigned int addr;
|
|
int ii, kk = 0, retry;
|
|
int tx_num, rx_num;
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: ++\n", __func__);
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_irq_enable(info, false);
|
|
fts_release_all_finger(info);
|
|
|
|
if (info->stm_ver == STM_VER7) {
|
|
fts_command(info, SENSEOFF);
|
|
} else {
|
|
fts_systemreset(info);
|
|
fts_delay(50);
|
|
fts_wait_for_ready(info);
|
|
|
|
fts_command(info, SLEEPOUT);
|
|
fts_delay(50);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
|
|
}
|
|
#endif
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(50);
|
|
|
|
result_tx = kzalloc(info->ForceChannelLength + 10, GFP_KERNEL);
|
|
if (!result_tx) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: failed to alloc mem\n",
|
|
__func__);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "FAIL");
|
|
goto err_alloc_tx_mem;
|
|
}
|
|
|
|
result_rx = kzalloc(info->SenseChannelLength + 10, GFP_KERNEL);
|
|
if (!result_rx) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: failed to alloc mem\n",
|
|
__func__);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "FAIL");
|
|
goto err_alloc_rx_mem;
|
|
}
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
if (info->ForceChannelLength % FTS_CX2_READ_LENGTH)
|
|
tx_num = (info->ForceChannelLength / FTS_CX2_READ_LENGTH + 1);
|
|
else
|
|
tx_num = info->ForceChannelLength / FTS_CX2_READ_LENGTH;
|
|
|
|
if (info->SenseChannelLength % FTS_CX2_READ_LENGTH)
|
|
rx_num = (info->SenseChannelLength / FTS_CX2_READ_LENGTH + 1);
|
|
else
|
|
rx_num = info->SenseChannelLength / FTS_CX2_READ_LENGTH;
|
|
|
|
for (ii = 0; ii < tx_num + rx_num; ii++) {
|
|
|
|
if (ii < tx_num)
|
|
addr = FTS_WTR_TX_CX2_BASE_ADDR + (ii * 3);
|
|
else
|
|
addr = FTS_WTR_RX_CX2_BASE_ADDR + ((ii - tx_num) * 3);
|
|
|
|
if (ii == tx_num)
|
|
kk = 0;
|
|
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (addr >> 8) & 0xFF;
|
|
regAdd[2] = addr & 0xFF;
|
|
regAdd[3] = 0x04;
|
|
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
|
|
retry = FTS_RETRY_COUNT * 3;
|
|
do {
|
|
if (retry < 0) {
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: failed to compare buf, break!\n", __func__);
|
|
break;
|
|
}
|
|
|
|
memset(buf, 0x0, 8);
|
|
|
|
fts_read_reg(info, &r_addr, 1, &buf[0], FTS_EVENT_SIZE);
|
|
retry--;
|
|
|
|
} while (buf[1] != regAdd[1] || buf[2] != regAdd[2]);
|
|
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: %d: [%04X] (%02X, %02X,) %02X, %02X, %02X, %02X, %02X, %02X\n",
|
|
__func__, ii, addr, buf[0], buf[1], buf[2], buf[3],
|
|
buf[4], buf[5], buf[6], buf[7]);
|
|
|
|
if (ii < tx_num) {
|
|
result_tx[kk++] = buf[3] & 0x3F;
|
|
result_tx[kk++] = (buf[3] & 0xC0) >> 6 | (buf[4] & 0x0F) << 2;
|
|
result_tx[kk++] = ((buf[4] & 0xF0)>> 4) | ((buf[5] & 0x03) << 4);
|
|
result_tx[kk++] = buf[5] >> 2;
|
|
} else {
|
|
result_rx[kk++] = buf[3] & 0x3F;
|
|
result_rx[kk++] = (buf[3] & 0xC0) >> 6 | (buf[4] & 0x0F) << 2;
|
|
result_rx[kk++] = ((buf[4] & 0xF0)>> 4) | ((buf[5] & 0x03) << 4);
|
|
result_rx[kk++] = buf[5] >> 2;
|
|
}
|
|
}
|
|
} else {
|
|
int comp_header_addr, comp_start_tx_addr, comp_start_rx_addr;
|
|
|
|
/* Request compensation data */
|
|
regAdd[0] = 0xB8;
|
|
regAdd[1] = 0x20; // SELF IX
|
|
regAdd[2] = 0x00;
|
|
fts_write_reg(info, ®Add[0], 3);
|
|
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, 0x20, 0x00);
|
|
|
|
/* Read an address of compensation data */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = 0x00;
|
|
regAdd[2] = 0x50;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], 4);
|
|
comp_header_addr = buff[1] + (buff[2] << 8);
|
|
|
|
/* Read header of compensation area */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_header_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
|
|
tx_num = buff[5];
|
|
rx_num = buff[6];
|
|
|
|
comp_start_tx_addr = comp_header_addr + 0x10 + tx_num + rx_num;
|
|
comp_start_rx_addr = comp_start_tx_addr + tx_num;
|
|
|
|
memset(result_tx, 0x0, tx_num);
|
|
memset(result_rx, 0x0, rx_num);
|
|
|
|
memset(buff, 0x0, 512);
|
|
/* Read Self TX Cx2 */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_start_tx_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_start_tx_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], tx_num + 1);
|
|
|
|
for (ii = 0; ii < tx_num; ii++) {
|
|
result_tx[ii] = buff[ii + 1];
|
|
}
|
|
|
|
memset(buff, 0x0, 512);
|
|
/* Read Self RX Ix2 */
|
|
regAdd[0] = 0xD0;
|
|
regAdd[1] = (comp_start_rx_addr >> 8) & 0xFF;
|
|
regAdd[2] = comp_start_rx_addr & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, &buff[0], rx_num + 1);
|
|
|
|
for (ii = 0; ii < rx_num; ii++) {
|
|
result_rx[ii] = buff[ii + 1];
|
|
}
|
|
}
|
|
|
|
if (allnode) {
|
|
char *data = 0;
|
|
|
|
data = result_tx;
|
|
for (ii = 0; ii < info->ForceChannelLength; ii++) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Tx[%d] = %d\n", __func__, ii, *data);
|
|
sprintf(temp, "%d,", *data);
|
|
strncat(buff, temp, 9);
|
|
data++;
|
|
}
|
|
|
|
data = result_rx;
|
|
for (ii = 0; ii < info->SenseChannelLength; ii++) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Rx[%d] = %d\n", __func__, ii, *data);
|
|
sprintf(temp, "%d,", *data);
|
|
strncat(buff, temp, 9);
|
|
data++;
|
|
}
|
|
} else {
|
|
unsigned char min_tx = 255, max_tx = 0, min_rx = 255, max_rx = 0;
|
|
|
|
for (ii = 0; ii < info->ForceChannelLength; ii++) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Tx[%d] = %d\n", __func__, ii, result_tx[ii]);
|
|
|
|
min_tx = min(min_tx, result_tx[ii]);
|
|
max_tx = max(max_tx, result_tx[ii]);
|
|
}
|
|
|
|
for (ii = 0; ii < info->SenseChannelLength; ii++) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: Rx[%d] = %d\n", __func__, ii, result_rx[ii]);
|
|
min_rx = min(min_rx, result_rx[ii]);
|
|
max_rx = max(max_rx, result_rx[ii]);
|
|
}
|
|
|
|
sprintf(buff, "%d,%d,%d,%d", min_tx, max_tx, min_rx, max_rx);
|
|
|
|
}
|
|
|
|
kfree(result_rx);
|
|
err_alloc_rx_mem:
|
|
kfree(result_tx);
|
|
err_alloc_tx_mem:
|
|
fts_irq_enable(info, true);
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
fts_command(info, SENSEON);
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
}
|
|
#endif
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
|
|
}
|
|
|
|
static void run_wtr_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);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
fts_read_wtr_cx_data(info, false);
|
|
|
|
}
|
|
|
|
static void run_wtr_cx_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);
|
|
|
|
fts_read_wtr_cx_data(info, true);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
#define USE_KEY_NUM 2
|
|
#define FTS_MKEY_ADDR 0x32
|
|
#define DOFFSET 1 //Digital rev 2
|
|
|
|
static void run_key_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 };
|
|
unsigned char key_cx2_data[2];
|
|
unsigned char ReadData[USE_KEY_NUM * FTS_CX2_READ_LENGTH];
|
|
unsigned char regAdd[8];
|
|
unsigned char buf[8];
|
|
unsigned char r_addr = READ_ONE_EVENT;
|
|
unsigned int addr;
|
|
int i = 0, retry = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->dt_data->support_mskey) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touchkey is not supported\n",
|
|
__func__);
|
|
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;
|
|
return;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_irq_enable(info, false);
|
|
|
|
addr = FTS_CX2_BASE_ADDR;
|
|
|
|
regAdd[0] = 0xB2;
|
|
regAdd[1] = (addr >> 8) & 0xff;
|
|
regAdd[2] = (addr & 0xff);
|
|
regAdd[3] = 0x04;
|
|
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
fts_delay(1);
|
|
|
|
retry = 100;
|
|
do {
|
|
if (retry < 0) {
|
|
dev_err(&info->client->dev, "%s: failed to compare buf, break!\n", __func__);
|
|
break;
|
|
}
|
|
|
|
fts_read_reg(info, &r_addr, 1, &buf[0], FTS_EVENT_SIZE);
|
|
retry--;
|
|
} while (buf[1] != regAdd[1] || buf[2] != regAdd[2]);
|
|
|
|
|
|
ReadData[i * 4] = buf[3] & 0x3F;
|
|
ReadData[i * 4 + 1] = (buf[3] & 0xC0) >> 6 | (buf[4] & 0x0F) << 2;
|
|
ReadData[i * 4 + 2] = ((buf[4] & 0xF0) >> 4) | ((buf[5] & 0x03) << 4);
|
|
ReadData[i * 4 + 3] = buf[5] >> 2;
|
|
|
|
key_cx2_data[0] = ReadData[2]; key_cx2_data[1] = ReadData[3];
|
|
|
|
dev_info(&info->client->dev, "%s: [Key 1:%d][Key 2:%d]\n", __func__,
|
|
key_cx2_data[0], key_cx2_data[1]);
|
|
|
|
//snprintf(buff, sizeof(buff), "%s", "OK");
|
|
snprintf(buff, sizeof(buff), "%d,%d", key_cx2_data[0], key_cx2_data[1]);
|
|
fts_irq_enable(info, true);
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#define KEY_CHANNEL_LENGTH 4
|
|
#define USING_KEY_CHANNEL_LENGTH 2
|
|
|
|
static void run_key_cm_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 };
|
|
unsigned char data[4] = { 0 };
|
|
unsigned char addr[4] = {0xD0, 0x00, 0x32, 0x00};// key channel address is 0xD0, 0x00, 0x32
|
|
unsigned int start_addr;
|
|
unsigned int end_addr;
|
|
unsigned int length;
|
|
unsigned int len;
|
|
unsigned char *buffer = NULL;
|
|
unsigned char *pbuffer = NULL;
|
|
int ii;
|
|
unsigned int cm_value;
|
|
unsigned int max_val = 0;
|
|
unsigned int min_val = 32767;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->dt_data->support_mskey) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touchkey is not supported\n",
|
|
__func__);
|
|
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;
|
|
return;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_irq_enable(info, false);
|
|
fts_release_all_finger(info);
|
|
|
|
fts_command(info, SENSEOFF);
|
|
fts_delay(50);
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
|
|
fts_delay(50);
|
|
}
|
|
#endif
|
|
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(50);
|
|
|
|
fts_read_reg(info, addr, 3, data, 4);
|
|
tsp_debug_info(true, &info->client->dev, "%s: %X, %X, %X, %X\n",
|
|
__func__, data[0], data[1], data[2], data[3]);
|
|
|
|
fts_delay(10);
|
|
|
|
// key channel length : 4
|
|
start_addr = data[1] + (data[2] << 8);
|
|
length = KEY_CHANNEL_LENGTH * 2 + 1;
|
|
end_addr = start_addr + length;
|
|
|
|
buffer = kzalloc(length, GFP_KERNEL);
|
|
if (!buffer) {
|
|
snprintf(buff, sizeof(buff), "%s", "FAIL");
|
|
goto err_key_cm_out;
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: start: %X, end: %X, length: %X, len: %X\n",
|
|
__func__, start_addr, end_addr, length, len);
|
|
|
|
addr[0] = 0xD0;
|
|
addr[1] = (start_addr >> 8) & 0xff;
|
|
addr[2] = (start_addr & 0xff);
|
|
|
|
memset(buffer, 0x00, length);
|
|
pbuffer = buffer;
|
|
fts_read_reg(info, addr, 3, buffer, length);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %X\n", __func__, *pbuffer);
|
|
|
|
pbuffer++;
|
|
|
|
for (ii = 0; ii < USING_KEY_CHANNEL_LENGTH; ii++) {
|
|
cm_value = 0;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: (D2) %X\n", __func__, *pbuffer);
|
|
|
|
cm_value |= (*pbuffer & 0xFF);
|
|
pbuffer++;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: (D1) %X\n", __func__, *pbuffer);
|
|
|
|
cm_value |= (*pbuffer << 8);
|
|
pbuffer++;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: [%d]: %d(%X)\n", __func__, ii, cm_value, cm_value);
|
|
|
|
max_val = max(max_val, cm_value);
|
|
min_val = min(min_val, cm_value);
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "max: %d, min: %d\n", max_val, min_val);
|
|
|
|
snprintf(buff, SEC_CMD_STR_LEN, "%d,%d", max_val, min_val);
|
|
|
|
kfree(buffer);
|
|
|
|
err_key_cm_out:
|
|
fts_irq_enable(info, true);
|
|
fts_command(info, SENSEON);
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
fts_delay(50);
|
|
}
|
|
#endif
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
static void run_key_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);
|
|
unsigned char regAdd[3] = {0xD0, 0x00, FTS_MKEY_ADDR};
|
|
unsigned char ReadData[USE_KEY_NUM*2+1] = {0};
|
|
unsigned int key_raw_data[USE_KEY_NUM] = {0};
|
|
unsigned int FrameAddress = 0, StartAddress = 0, TotalLength = 0; //EndAddress = 0;
|
|
//unsigned int writeAddr = 0;
|
|
//unsigned int col_cnt=0, row_cnt = 0;
|
|
unsigned char count = 0;
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->dt_data->support_mskey) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touchkey is not supported\n",
|
|
__func__);
|
|
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;
|
|
return;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
if (info->digital_rev == FTS_DIGITAL_REV_2) {
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
|
|
TotalLength = USE_KEY_NUM * 2;
|
|
fts_read_reg(info, regAdd, 3, (unsigned char *)ReadData, FTS_EVENT_SIZE);
|
|
|
|
FrameAddress = ReadData[DOFFSET] + (ReadData[DOFFSET+1] << 8); // D1 : DOFFSET = 0, D2 : DOFFSET : 1
|
|
|
|
StartAddress = FrameAddress;
|
|
|
|
memset(&ReadData[0], 0x0, sizeof(ReadData));
|
|
|
|
regAdd[1] = (StartAddress >> 8) & 0xFF;
|
|
regAdd[2] = StartAddress & 0xFF;
|
|
fts_read_reg(info, regAdd, 3, (unsigned char *)ReadData, USE_KEY_NUM * 2 + 1);
|
|
|
|
for(count=0; count < USE_KEY_NUM; count++)
|
|
key_raw_data[count] = ReadData[count * 2 + DOFFSET] + (ReadData[count * 2 + DOFFSET + 1] << 8);
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%d,%d", key_raw_data[0], key_raw_data[1]);
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#endif
|
|
|
|
int fts_get_tsp_test_result(struct fts_ts_info *info)
|
|
{
|
|
struct sec_cmd_data *sec = &info->sec;
|
|
unsigned char cmd[4] = {0xB2, 0x07, 0xEB, 0x01};
|
|
unsigned char data[FTS_EVENT_SIZE];
|
|
int retry = 0;
|
|
int ret = -EINVAL;
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
|
|
fts_write_reg(info, &cmd[0], 4);
|
|
|
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
|
cmd[0] = READ_ONE_EVENT;
|
|
|
|
while (info->fts_read_reg(info, &cmd[0], 1, (unsigned char *)data,
|
|
FTS_EVENT_SIZE)) {
|
|
|
|
if ((data[0] == EVENTID_RESULT_READ_REGISTER)
|
|
&& (data[1] == cmd[1]) && (data[2] == cmd[2])) {
|
|
info->test_result.data[0] = data[3];
|
|
tsp_debug_info(true, &info->client->dev, "%s: [0x%X] M:%s, M:%d, A:%s, A:%d\n",
|
|
"get_tsp_test_result", info->test_result.data[0],
|
|
info->test_result.module_result == 0 ? "NONE" :
|
|
info->test_result.module_result == 1 ? "FAIL" : "PASS",
|
|
info->test_result.module_count,
|
|
info->test_result.assy_result == 0 ? "NONE" :
|
|
info->test_result.assy_result == 1 ? "FAIL" : "PASS",
|
|
info->test_result.assy_count);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
if (retry++ > 30) {
|
|
tsp_debug_err(true, info->dev,
|
|
"%s: Time Over\n", __func__);
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
out:
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
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->stm_ver != STM_VER7) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: not_support_cmd\n",
|
|
__func__);
|
|
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;
|
|
return;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
ret = fts_get_tsp_test_result(info);
|
|
if (ret < 0) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: failed to get result\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;
|
|
} 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" : "PASS",
|
|
info->test_result.module_count,
|
|
info->test_result.assy_result == 0 ? "NONE" :
|
|
info->test_result.assy_result == 1 ? "FAIL" : "PASS",
|
|
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
|
|
*/
|
|
void fts_set_tsp_test_result(struct fts_ts_info *info)
|
|
{
|
|
unsigned char regAdd[4] = {0xB0, 0x07, 0xEB, 0x00};
|
|
|
|
tsp_debug_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" : "PASS",
|
|
info->test_result.module_count,
|
|
info->test_result.assy_result == 0 ? "NONE" :
|
|
info->test_result.assy_result == 1 ? "FAIL" : "PASS",
|
|
info->test_result.assy_count);
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
|
|
regAdd[3] = info->test_result.data[0];
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
fts_delay(100);
|
|
fts_command(info, FTS_CMD_SAVE_FWCONFIG);
|
|
|
|
fts_delay(230);
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CONFIG);
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
}
|
|
EXPORT_SYMBOL(fts_set_tsp_test_result);
|
|
|
|
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->stm_ver != STM_VER7) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: not_support_cmd\n",
|
|
__func__);
|
|
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;
|
|
return;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
ret = fts_get_tsp_test_result(info);
|
|
if (ret < 0) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: [ERROR] failed to get_tsp_test_result\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;
|
|
}
|
|
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++;
|
|
}
|
|
|
|
fts_set_tsp_test_result(info);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_HOVER
|
|
static void hover_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 (info->touch_stopped || !(info->reinit_done) || (info->power_state & STATE_LOWPOWER)) {
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: [ERROR] Touch is stopped:%d, reinit_done:%d, power state:%d\n",
|
|
__func__, info->touch_stopped, info->reinit_done, info->power_state);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
|
|
if (sec->cmd_param[0] == 1) {
|
|
info->retry_hover_enable_after_wakeup = 1;
|
|
tsp_debug_info(true, &info->client->dev, "%s: retry_hover_on_after_wakeup\n", __func__);
|
|
}
|
|
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
int enables;
|
|
enables = sec->cmd_param[0];
|
|
if (enables) {
|
|
unsigned char regAdd[4] = {0xB0, 0x01, 0x29, 0x41};
|
|
unsigned char Dly_regAdd[4] = {0xB0, 0x01, 0x72, 0x04};
|
|
|
|
fts_write_reg(info, &Dly_regAdd[0], 4);
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
fts_command(info, FTS_CMD_HOVER_ON);
|
|
info->hover_ready = false;
|
|
info->hover_enabled = true;
|
|
} else {
|
|
unsigned char Dly_regAdd[4] = {0xB0, 0x01, 0x72, 0x08};
|
|
fts_write_reg(info, &Dly_regAdd[0], 4);
|
|
fts_command(info, FTS_CMD_HOVER_OFF);
|
|
info->hover_enabled = false;
|
|
info->hover_ready = false;
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
|
|
out:
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
/*
|
|
static void hover_no_sleep_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);
|
|
unsigned char regAdd[4] = {0xB0, 0x01, 0x18, 0x00};
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0]) {
|
|
regAdd[3]=0x0F;
|
|
} else {
|
|
regAdd[3]=0x08;
|
|
}
|
|
fts_write_reg(info, ®Add[0], 4);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, 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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
info->glove_enabled = sec->cmd_param[0];
|
|
|
|
if (!info->touch_stopped && info->reinit_done) {
|
|
if (info->glove_enabled)
|
|
fts_command(info, FTS_CMD_GLOVE_MODE_ON);
|
|
else
|
|
fts_command(info, FTS_CMD_GLOVE_MODE_OFF);
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
static void get_glove_sensitivity(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);
|
|
unsigned char cmd[4] = { 0xB2, 0x01, 0xC6, 0x02 };
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
unsigned char data[FTS_EVENT_SIZE];
|
|
int retry = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->touch_stopped) {
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
|
|
fts_write_reg(info, &cmd[0], 4);
|
|
|
|
memset(data, 0x0, FTS_EVENT_SIZE);
|
|
cmd[0] = READ_ONE_EVENT;
|
|
|
|
while (info->fts_read_reg(info, &cmd[0], 1, (unsigned char *)data,
|
|
FTS_EVENT_SIZE)) {
|
|
|
|
if ((data[0] == EVENTID_RESULT_READ_REGISTER)
|
|
&& (data[1] == cmd[1]) && (data[2] == cmd[2])) {
|
|
snprintf(buff, sizeof(buff), "%d",
|
|
*(unsigned short *)&data[3]);
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s(%d)\n", __func__, buff,
|
|
(int)strnlen(buff, sizeof(buff)));
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
break;
|
|
}
|
|
|
|
if (retry++ > 30) {
|
|
tsp_debug_err(true, info->dev,
|
|
"%s: Time Over\n", __func__);
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
|
|
}
|
|
|
|
static void fast_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 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
info->fast_glove_enabled = sec->cmd_param[0];
|
|
|
|
if (!info->touch_stopped && info->reinit_done) {
|
|
if (info->fast_glove_enabled)
|
|
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
|
|
else
|
|
fts_command(info, FTS_CMD_SET_NOR_GLOVE_MODE);
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_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), "%s", "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->touch_stopped && info->reinit_done) {
|
|
if (info->flip_enable) {
|
|
#ifdef CONFIG_GLOVE_TOUCH
|
|
if (info->glove_enabled)
|
|
fts_command(info, FTS_CMD_GLOVE_MODE_OFF);
|
|
#endif
|
|
fts_set_cover_type(info, true);
|
|
} else {
|
|
fts_set_cover_type(info, false);
|
|
#ifdef CONFIG_GLOVE_TOUCH
|
|
if (info->fast_glove_enabled)
|
|
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
|
|
else if (info->glove_enabled)
|
|
fts_command(info, FTS_CMD_GLOVE_MODE_ON);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
#ifdef USE_STYLUS_PEN
|
|
static void stylus_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 (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 2) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
|
|
info->use_stylus = sec->cmd_param[0];
|
|
|
|
dev_info(&info->client->dev, "%s: stylus %s\n",
|
|
__func__, info->use_stylus ? "enable" : "disable");
|
|
|
|
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);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
#endif
|
|
|
|
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 };
|
|
int ret = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 2) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
|
|
if (sec->cmd_param[0] == REPORT_RATE_90HZ) {
|
|
ret = info->fts_change_scan_rate(info, FTS_CMD_FAST_SCAN);
|
|
} else if (sec->cmd_param[0] == REPORT_RATE_60HZ) {
|
|
ret = info->fts_change_scan_rate(info, FTS_CMD_SLOW_SCAN);
|
|
} else if (sec->cmd_param[0] == REPORT_RATE_30HZ) {
|
|
/* will be fixed 30hz report rate command */
|
|
ret = info->fts_change_scan_rate(info, FTS_CMD_USLOW_SCAN);
|
|
}
|
|
if (ret < 0) {
|
|
dev_err(&info->client->dev, "%s: can not change report rate, %d\n", __func__, ret);
|
|
snprintf(buff, sizeof(buff), "%s", "FAIL");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
}
|
|
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);
|
|
|
|
tsp_debug_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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
int enables;
|
|
enables = sec->cmd_param[0];
|
|
if (enables)
|
|
fts_irq_enable(info, true);
|
|
else
|
|
fts_irq_enable(info, false);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
|
|
out:
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
#endif
|
|
|
|
static bool check_lowpower_mode(struct fts_ts_info *info, unsigned char flag)
|
|
{
|
|
bool ret = FTS_DISABLE;
|
|
flag = flag & 0xFF;
|
|
|
|
if (flag)
|
|
ret = FTS_ENABLE;
|
|
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: lowpower_mode flag : %d, ret:%d\n", __func__, flag, ret);
|
|
|
|
if (flag & FTS_LOWP_FLAG_2ND_SCREEN)
|
|
tsp_debug_info(true, &info->client->dev, "%s: 2nd screen on\n", __func__);
|
|
if (flag & FTS_LOWP_FLAG_BLACK_UI)
|
|
tsp_debug_info(true, &info->client->dev, "%s: AOD double tap on\n", __func__);
|
|
if (flag & FTS_LOWP_FLAG_SPAY)
|
|
tsp_debug_info(true, &info->client->dev, "%s: spay cmd on\n", __func__);
|
|
if (flag & FTS_LOWP_FLAG_TEMP_CMD)
|
|
tsp_debug_info(true, &info->client->dev, "%s: known cmd on\n", __func__);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
static void set_lowpower_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), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0])
|
|
info->lowpower_mode = FTS_ENABLE;
|
|
else
|
|
info->lowpower_mode = FTS_DISABLE;
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
static void set_deepsleep_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), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
info->deepsleep_mode = sec->cmd_param[0];
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
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 };
|
|
unsigned char regAdd[2] = {0xC2, 0x10};
|
|
int rc;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
info->wirelesscharger_mode = sec->cmd_param[0];
|
|
|
|
if (info->wirelesscharger_mode ==0)
|
|
regAdd[0] = 0xC2;
|
|
else
|
|
regAdd[0] = 0xC1;
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: CMD[%2X]\n",__func__,regAdd[0]);
|
|
|
|
rc = fts_write_reg(info, regAdd, 2);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
|
|
out:
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
static void active_sleep_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] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
/* To do here */
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
#if defined(TSP_BOOSTER) && !defined(INPUT_BOOSTER_SYSFS)
|
|
static void boost_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 };
|
|
int retval;
|
|
int stage;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->tsp_booster) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: booster is NULL.\n", __func__);
|
|
|
|
goto boost_out;
|
|
}
|
|
|
|
stage = 1 << sec->cmd_param[0];
|
|
if (!(info->tsp_booster->dvfs_stage & stage)) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: %d is not supported(%04x != %04x).\n",
|
|
__func__, sec->cmd_param[0],
|
|
stage, info->tsp_booster->dvfs_stage);
|
|
|
|
goto boost_out;
|
|
}
|
|
|
|
info->tsp_booster->dvfs_boost_mode = stage;
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
if (info->tsp_booster->dvfs_boost_mode == DVFS_STAGE_NONE) {
|
|
retval = info->tsp_booster->dvfs_off(info->tsp_booster);
|
|
if (retval < 0) {
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: booster stop failed(%d).\n",
|
|
__func__, retval);
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
}
|
|
|
|
boost_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);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
#endif
|
|
|
|
static void second_screen_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] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0])
|
|
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_2ND_SCREEN;
|
|
else
|
|
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_2ND_SCREEN);
|
|
|
|
info->lowpower_mode = check_lowpower_mode(info, info->lowpower_flag);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
static void longpress_grip_enable_mode(struct fts_ts_info *info, bool on)
|
|
{
|
|
int ret;
|
|
unsigned char regAdd[4] = {0xB0, 0x07, 0x10, 0x03};
|
|
|
|
if (on)
|
|
regAdd[3] = 0x03; // default
|
|
else
|
|
regAdd[3] = 0x02; // can long press
|
|
|
|
ret = fts_write_reg(info, regAdd, 4);
|
|
|
|
if (ret < 0)
|
|
dev_err(&info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
dev_info(&info->client->dev, "%s: reg:%d, ret: %d\n", __func__, on, ret);
|
|
|
|
fts_delay(1);
|
|
}
|
|
|
|
static void set_longpress_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] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0])
|
|
longpress_grip_enable_mode(info, 1);
|
|
else
|
|
longpress_grip_enable_mode(info, 0);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
|
|
static void grip_check_enable_mode(struct fts_ts_info *info, bool on)
|
|
{
|
|
int ret;
|
|
unsigned char regAdd[4] = {0xB0, 0x07, 0x11, 0x7F};
|
|
|
|
if (on) {
|
|
regAdd[3] = 0x7F; // default
|
|
info->edge_grip_mode = true;
|
|
} else {
|
|
regAdd[3] = 0x7E; // don't check grip
|
|
info->edge_grip_mode = false;
|
|
}
|
|
|
|
ret = fts_write_reg(info, regAdd, 4);
|
|
|
|
if (ret < 0)
|
|
dev_err(&info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
dev_info(&info->client->dev, "%s: reg:%d, ret: %d\n", __func__, on, ret);
|
|
fts_delay(1);
|
|
}
|
|
|
|
static void set_grip_detection(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), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0]) {
|
|
longpress_grip_enable_mode(info, 1); // default
|
|
grip_check_enable_mode(info, 1); // default
|
|
} else {
|
|
longpress_grip_enable_mode(info, 0);
|
|
grip_check_enable_mode(info, 0);
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
static void set_sidescreen_x_length(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 };
|
|
/* TB Side screen area length */
|
|
unsigned char regAdd[4] = {0xB0, 0x07, 0x1C, 0xA0}; //default Side screen x length setting
|
|
int ret;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 0xA0) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
regAdd[3] = sec->cmd_param[0]; // Change Side screen x length
|
|
|
|
ret = fts_write_reg(info, regAdd, 4);
|
|
if (ret < 0)
|
|
dev_err(&info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
dev_info(&info->client->dev, "%s: x length:%d, ret: %d\n", __func__, regAdd[3], ret);
|
|
|
|
fts_delay(1);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
|
|
|
|
static void set_dead_zone(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 };
|
|
/* long press */
|
|
unsigned char regAdd[2] = {0xC4, 0x00};
|
|
int ret;
|
|
/* long press */
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 6) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0] == 1)
|
|
regAdd[1] = 0x01; /* side edge top */
|
|
else if (sec->cmd_param[0] == 2)
|
|
regAdd[1] = 0x02; /* side edge bottom */
|
|
else if (sec->cmd_param[0] == 3)
|
|
regAdd[1] = 0x03; /* side edge All On */
|
|
else if (sec->cmd_param[0] == 4)
|
|
regAdd[1] = 0x04; /* side edge Left Off */
|
|
else if (sec->cmd_param[0] == 5)
|
|
regAdd[1] = 0x05; /* side edge Right Off */
|
|
else if (sec->cmd_param[0] == 6)
|
|
regAdd[1] = 0x06; /* side edge All Off */
|
|
else
|
|
regAdd[1] = 0x0; /* none */
|
|
|
|
ret = fts_write_reg(info, regAdd, 2);
|
|
|
|
if (ret < 0)
|
|
dev_err(&info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
dev_info(&info->client->dev, "%s: reg:%d, ret: %d\n", __func__, sec->cmd_param[0], ret);
|
|
fts_delay(1);
|
|
/* long press */
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
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 };
|
|
unsigned char regAdd[2] = {0xC2, 0x0C};
|
|
int ret;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0]==0) {
|
|
regAdd[0] = 0xC1; /* dead zone disable */
|
|
} else {
|
|
regAdd[0] = 0xC2; /* dead zone enable */
|
|
}
|
|
|
|
ret = fts_write_reg(info, regAdd, 2);
|
|
|
|
if (ret < 0)
|
|
tsp_debug_err(true, &info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
tsp_debug_info(true, &info->client->dev, "%s: reg:%d, ret: %d\n", __func__, sec->cmd_param[0], ret);
|
|
|
|
fts_delay(1);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
static void select_wakeful_edge(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 };
|
|
unsigned char regAdd[2] = {0xC2, 0x0F};
|
|
int ret;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0]==0) {
|
|
regAdd[0] = FTS_CMS_DISABLE_FEATURE; /* right - C2, 0F */
|
|
info->wakeful_edge_side = EDGEWAKE_RIGHT;
|
|
} else {
|
|
regAdd[0] = FTS_CMS_ENABLE_FEATURE; /* left - C1, 0F */
|
|
info->wakeful_edge_side = EDGEWAKE_LEFT;
|
|
}
|
|
ret = fts_write_reg(info, regAdd, 2);
|
|
|
|
if (ret < 0)
|
|
tsp_debug_err(true, &info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
tsp_debug_info(true, &info->client->dev, "%s: reg:%d, ret: %d\n", __func__, sec->cmd_param[0], ret);
|
|
|
|
fts_delay(1);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_MAINSCREEN_DISBLE
|
|
static void set_mainscreen_disable_cmd(struct fts_ts_info *info, bool on)
|
|
{
|
|
int ret;
|
|
unsigned char regAdd[2] = {0xC2, 0x07};
|
|
|
|
if (on) {
|
|
regAdd[0] = 0xC1; // main screen disable
|
|
info->mainscr_disable = true;
|
|
} else {
|
|
regAdd[0] = 0xC2; // enable like normal
|
|
info->mainscr_disable = false;
|
|
}
|
|
|
|
ret = fts_write_reg(info, regAdd, 2);
|
|
|
|
if (ret < 0)
|
|
dev_err(&info->client->dev, "%s failed. ret: %d\n", __func__, ret);
|
|
else
|
|
dev_info(&info->client->dev, "%s: reg:%d, ret: %d\n", __func__, on, ret);
|
|
fts_delay(1);
|
|
}
|
|
|
|
static void set_mainscreen_disable(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] > 2) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
if (sec->cmd_param[0] == 1)
|
|
set_mainscreen_disable_cmd(info, 1);
|
|
else
|
|
set_mainscreen_disable_cmd(info, 0);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
#endif
|
|
|
|
static void scrub_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);
|
|
unsigned short addr = FTS_CMD_STRING_ACCESS;
|
|
int ret;
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->dt_data->support_string_lib) {
|
|
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;
|
|
goto out;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
dev_info(&info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: not_support_cmd\n",
|
|
__func__);
|
|
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;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0]) {
|
|
info->fts_mode |= FTS_MODE_SCRUB;
|
|
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_BLACK_UI;
|
|
|
|
} else {
|
|
info->fts_mode &= ~FTS_MODE_SCRUB;
|
|
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_BLACK_UI);
|
|
}
|
|
|
|
ret = info->fts_write_to_string(info, &addr, &info->fts_mode, sizeof(info->fts_mode));
|
|
if (ret < 0) {
|
|
dev_err(&info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
out:
|
|
|
|
info->lowpower_mode = check_lowpower_mode(info, info->lowpower_flag);
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
dev_info(&info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#ifdef SMARTCOVER_COVER
|
|
static void change_smartcover_table(struct fts_ts_info *info)
|
|
{
|
|
u8 i, j, k, h, temp, temp_sum;
|
|
|
|
for (i = 0; i < MAX_BYTE; i++)
|
|
for(j = 0; j < MAX_TX; j++)
|
|
info->changed_table[j][i] = info->smart_cover[i][j];
|
|
|
|
#if 1 // debug
|
|
tsp_debug_info(true, &info->client->dev, "%s smart_cover value\n", __func__);
|
|
for (i = 0; i < MAX_BYTE; i++){
|
|
pr_info("[fts] ");
|
|
for (j = 0; j < MAX_TX; j++)
|
|
pr_cont("%d ",info->smart_cover[i][j]);
|
|
pr_cont("\n");
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s changed_table value\n", __func__);
|
|
for (j = 0; j < MAX_TX; j++){
|
|
pr_info("[fts] ");
|
|
for (i = 0; i < MAX_BYTE; i++)
|
|
pr_cont("%d ",info->changed_table[j][i]);
|
|
pr_cont("\n");
|
|
}
|
|
#endif
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s %d\n", __func__, __LINE__);
|
|
|
|
for (i = 0; i < MAX_TX; i++)
|
|
for (j = 0; j < 4; j++)
|
|
info->send_table[i][j] = 0;
|
|
tsp_debug_info(true, &info->client->dev, "%s %d\n", __func__, __LINE__);
|
|
|
|
for (i = 0; i < MAX_TX; i++){
|
|
temp = 0;
|
|
for (j = 0; j < MAX_BYTE; j++)
|
|
temp += info->changed_table[i][j];
|
|
if (temp == 0) continue;
|
|
|
|
for (k = 0; k < 4; k++){
|
|
temp_sum = 0;
|
|
for (h = 0; h < 8; h++){
|
|
temp_sum += ((u8)(info->changed_table[i][h+8*k])) << (7-h);
|
|
}
|
|
info->send_table[i][k] = temp_sum;
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "i:%2d, %2X %2X %2X %2X\n",
|
|
i, info->send_table[i][0], info->send_table[i][1],
|
|
info->send_table[i][2], info->send_table[i][3]);
|
|
}
|
|
tsp_debug_info(true, &info->client->dev, "%s %d\n", __func__, __LINE__);
|
|
|
|
|
|
}
|
|
|
|
static void set_smartcover_mode(struct fts_ts_info *info, bool on)
|
|
{
|
|
int ret;
|
|
unsigned char regMon[2] = {0xC1, 0x0A};
|
|
unsigned char regMoff[2] = {0xC2, 0x0A};
|
|
|
|
if (on == 1) {
|
|
ret = fts_write_reg(info, regMon, 2);
|
|
if (ret < 0)
|
|
tsp_debug_err(true, &info->client->dev, "%s mode on failed. ret: %d\n", __func__, ret);
|
|
} else {
|
|
ret = fts_write_reg(info, regMoff, 2);
|
|
if (ret < 0)
|
|
tsp_debug_err(true, &info->client->dev, "%s mode off failed. ret: %d\n", __func__, ret);
|
|
}
|
|
}
|
|
|
|
static void set_smartcover_clear(struct fts_ts_info *info)
|
|
{
|
|
int ret;
|
|
unsigned char regClr[6] = {0xC5, 0xFF, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
ret = fts_write_reg(info, regClr, 6);
|
|
if (ret < 0)
|
|
tsp_debug_err(true, &info->client->dev, "%s data clear failed. ret: %d\n", __func__, ret);
|
|
}
|
|
|
|
static void set_smartcover_data(struct fts_ts_info *info)
|
|
{
|
|
int ret;
|
|
u8 i, j;
|
|
u8 temp=0;
|
|
unsigned char regData[6] = {0xC5, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
|
|
for (i = 0; i < MAX_TX; i++){
|
|
temp = 0;
|
|
for (j = 0; j < 4; j++)
|
|
temp += info->send_table[i][j];
|
|
if (temp == 0) continue;
|
|
|
|
regData[1] = i;
|
|
|
|
for (j = 0; j < 4; j++)
|
|
regData[2 + j] = info->send_table[i][j];
|
|
|
|
tsp_debug_info(true, &info->client->dev, "i:%2d, %2X %2X %2X %2X \n",
|
|
regData[1], regData[2], regData[3], regData[4], regData[5]);
|
|
|
|
// data write
|
|
ret = fts_write_reg(info, regData, 6);
|
|
if (ret < 0)
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s data write[%d] failed. ret: %d\n", __func__, i, ret);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ####################################################
|
|
func : smartcover_cmd [0] [1] [2] [3]
|
|
index 0
|
|
vlaue 0 : off (normal)
|
|
vlaue 1 : off (globe mode)
|
|
vlaue 2 : X
|
|
vlaue 3 : on
|
|
clear -> data send(send_table value) -> mode on
|
|
vlaue 4 : clear smart_cover value
|
|
vlaue 5 : data save to smart_cover value
|
|
index 1 : tx channel num
|
|
index 2 : data 0xFF
|
|
index 3 : data 0xFF
|
|
value 6 : table value change, smart_cover -> changed_table -> send_table
|
|
|
|
ex)
|
|
// clear
|
|
echo smartcover_cmd,4 > cmd
|
|
// data write (hart)
|
|
echo smartcover_cmd,5,3,16,16 > cmd
|
|
echo smartcover_cmd,5,4,56,56 > cmd
|
|
echo smartcover_cmd,5,5,124,124 > cmd
|
|
echo smartcover_cmd,5,6,126,252 > cmd
|
|
echo smartcover_cmd,5,7,127,252 > cmd
|
|
echo smartcover_cmd,5,8,63,248 > cmd
|
|
echo smartcover_cmd,5,9,31,240 > cmd
|
|
echo smartcover_cmd,5,10,15,224 > cmd
|
|
echo smartcover_cmd,5,11,7,192 > cmd
|
|
echo smartcover_cmd,5,12,3,128 > cmd
|
|
// data change
|
|
echo smartcover_cmd,6 > cmd
|
|
// mode on
|
|
echo smartcover_cmd,3 > cmd
|
|
|
|
###################################################### */
|
|
|
|
static void smartcover_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[SEC_CMD_STR_LEN] = { 0 };
|
|
u8 i, j, t;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 6) {
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
|
|
if (sec->cmd_param[0] == 0) { // off
|
|
|
|
set_smartcover_mode(info, 0);
|
|
tsp_debug_info(true, &info->client->dev, "%s mode off, normal\n", __func__);
|
|
|
|
} else if (sec->cmd_param[0] == 1) { // off, globe mode
|
|
|
|
set_smartcover_mode(info, 0);
|
|
tsp_debug_info(true, &info->client->dev, "%s mode off, globe mode\n", __func__);
|
|
|
|
#ifdef CONFIG_GLOVE_TOUCH
|
|
if (info->fast_glove_enabled)
|
|
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
|
|
else if (info->glove_enabled)
|
|
fts_command(info, FTS_CMD_GLOVE_MODE_ON);
|
|
#endif
|
|
} else if (sec->cmd_param[0] == 3) { // on
|
|
|
|
set_smartcover_clear(info);
|
|
set_smartcover_data(info);
|
|
tsp_debug_info(true, &info->client->dev, "%s data send\n", __func__);
|
|
set_smartcover_mode(info, 1);
|
|
tsp_debug_info(true, &info->client->dev, "%s mode on\n", __func__);
|
|
|
|
} else if (sec->cmd_param[0] == 4) { // clear
|
|
|
|
for (i = 0; i < MAX_BYTE; i++)
|
|
for (j = 0; j < MAX_TX; j++)
|
|
info->smart_cover[i][j] = 0;
|
|
tsp_debug_info(true, &info->client->dev, "%s data clear\n", __func__);
|
|
|
|
} else if (sec->cmd_param[0] == 5) { // data write
|
|
|
|
if (sec->cmd_param[1] < 0 || sec->cmd_param[1] >= 32){
|
|
tsp_debug_info(true, &info->client->dev, "%s data tx size is over[%d]\n",
|
|
__func__, sec->cmd_param[1]);
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
goto fail;
|
|
}
|
|
tsp_debug_info(true, &info->client->dev, "%s data %2X, %2X, %2X\n", __func__,
|
|
sec->cmd_param[1], sec->cmd_param[2], sec->cmd_param[3] );
|
|
|
|
t = sec->cmd_param[1];
|
|
info->smart_cover[t][0] = (sec->cmd_param[2]&0x80)>>7;
|
|
info->smart_cover[t][1] = (sec->cmd_param[2]&0x40)>>6;
|
|
info->smart_cover[t][2] = (sec->cmd_param[2]&0x20)>>5;
|
|
info->smart_cover[t][3] = (sec->cmd_param[2]&0x10)>>4;
|
|
info->smart_cover[t][4] = (sec->cmd_param[2]&0x08)>>3;
|
|
info->smart_cover[t][5] = (sec->cmd_param[2]&0x04)>>2;
|
|
info->smart_cover[t][6] = (sec->cmd_param[2]&0x02)>>1;
|
|
info->smart_cover[t][7] = (sec->cmd_param[2]&0x01);
|
|
info->smart_cover[t][8] = (sec->cmd_param[3]&0x80)>>7;
|
|
info->smart_cover[t][9] = (sec->cmd_param[3]&0x40)>>6;
|
|
info->smart_cover[t][10] = (sec->cmd_param[3]&0x20)>>5;
|
|
info->smart_cover[t][11] = (sec->cmd_param[3]&0x10)>>4;
|
|
info->smart_cover[t][12] = (sec->cmd_param[3]&0x08)>>3;
|
|
info->smart_cover[t][13] = (sec->cmd_param[3]&0x04)>>2;
|
|
info->smart_cover[t][14] = (sec->cmd_param[3]&0x02)>>1;
|
|
info->smart_cover[t][15] = (sec->cmd_param[3]&0x01);
|
|
|
|
} else if(sec->cmd_param[0] == 6) { // data change
|
|
|
|
change_smartcover_table(info);
|
|
tsp_debug_info(true, &info->client->dev, "%s data change\n", __func__);
|
|
|
|
} else {
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s cmd[%d] not use\n", __func__, sec->cmd_param[0]);
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
goto fail;
|
|
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
fail:
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
};
|
|
#endif
|
|
|
|
static void set_rotation_status(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), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
int status = sec->cmd_param[0] % 2;
|
|
|
|
if (status)
|
|
fts_enable_feature(info, FTS_FEATURE_DUAL_SIDE_GUSTURE, true);
|
|
else
|
|
fts_enable_feature(info, FTS_FEATURE_DUAL_SIDE_GUSTURE, false);
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_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);
|
|
unsigned short addr = FTS_CMD_STRING_ACCESS;
|
|
|
|
int ret;
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->dt_data->support_string_lib) {
|
|
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;
|
|
goto out;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: not_support_cmd\n",
|
|
__func__);
|
|
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;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0]) {
|
|
info->fts_mode |= FTS_MODE_SPAY;
|
|
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_SPAY;
|
|
} else {
|
|
info->fts_mode &= ~FTS_MODE_SPAY;
|
|
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_SPAY);
|
|
}
|
|
|
|
ret = info->fts_write_to_string(info, &addr, &info->fts_mode, sizeof(info->fts_mode));
|
|
if (ret < 0) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: write failed. ret: %d\n", __func__, ret);
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
out:
|
|
info->lowpower_mode = check_lowpower_mode(info, info->lowpower_flag);
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
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);
|
|
unsigned short addr = FTS_CMD_STRING_ACCESS;
|
|
int ret;
|
|
char buff[SEC_CMD_STR_LEN] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!info->dt_data->support_string_lib) {
|
|
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;
|
|
goto out;
|
|
}
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
goto out;
|
|
}
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: not_support_cmd\n",
|
|
__func__);
|
|
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;
|
|
goto out;
|
|
}
|
|
|
|
if (sec->cmd_param[0]) {
|
|
info->fts_mode |= FTS_MODE_AOD_TRIGGER;
|
|
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_BLACK_UI;
|
|
} else {
|
|
info->fts_mode &= ~FTS_MODE_AOD_TRIGGER;
|
|
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_BLACK_UI);
|
|
}
|
|
|
|
ret = info->fts_write_to_string(info, &addr, &info->fts_mode, sizeof(info->fts_mode));
|
|
if (ret < 0) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: write failed. ret: %d\n", __func__, ret);
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
out:
|
|
info->lowpower_mode = check_lowpower_mode(info, info->lowpower_flag);
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
}
|
|
|
|
#if defined(CONFIG_TOUCHSCREEN_DUMP_MODE)
|
|
void fts_ts_run_rawdata_all(struct fts_ts_info *info)
|
|
{
|
|
short min = 10000;
|
|
short max = 0;
|
|
|
|
tsp_debug_err(true, &info->client->dev, "%s, start ##\n", __func__);
|
|
|
|
fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max);
|
|
tsp_debug_err(true, &info->client->dev, "%s, ## run Raw Cap data ##, max:%d,min:%d\n", __func__, max,min);
|
|
|
|
//run_cx_data_read((void *)t_sec);
|
|
get_all_data(info, run_cx_data_read, info->cx_data, DATA_UNSIGNED_CHAR);
|
|
tsp_debug_err(true, &info->client->dev, "%s, ## run CX data ##, %d\n", __func__, __LINE__);
|
|
|
|
tsp_debug_err(true, &info->client->dev, "%s, ## Done ##, %d\n", __func__, __LINE__);
|
|
|
|
}
|
|
#endif
|
|
|
|
static void delay(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->delay_time = sec->cmd_param[0];
|
|
|
|
dev_info(&info->client->dev, "%s: delay time is %d\n", __func__, info->delay_time);
|
|
snprintf(buff, sizeof(buff), "%d", info->delay_time);
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
dev_info(&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->temp = sec->cmd_param[0];
|
|
|
|
dev_info(&info->client->dev, "%s: command is %d\n", __func__, info->temp);
|
|
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_WAITING;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
dev_info(&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->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
|
|
__func__);
|
|
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
return;
|
|
}
|
|
|
|
#ifdef CONFIG_SEC_DEBUG_TSP_LOG
|
|
if(info->rawdata_read_lock == 1){
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: ramdump mode is runing, %d\n", __func__, info->rawdata_read_lock);
|
|
goto autotune_fail;
|
|
}
|
|
#endif
|
|
if (info->touch_count > 0) {
|
|
touch_on = true;
|
|
tsp_debug_info(true, info->dev, "%s: finger on touch(%d)\n", __func__, info->touch_count);
|
|
}
|
|
|
|
fts_irq_enable(info, false);
|
|
|
|
if ((info->digital_rev == FTS_DIGITAL_REV_2) || (info->digital_rev == FTS_DIGITAL_REV_3)) {
|
|
fts_interrupt_set(info, INT_DISABLE);
|
|
fts_release_all_finger(info);
|
|
|
|
fts_command(info, SENSEOFF);
|
|
fts_delay(50);
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey) {
|
|
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
|
|
}
|
|
#endif
|
|
fts_command(info, FLUSHBUFFER);
|
|
fts_delay(10);
|
|
|
|
fts_release_all_finger(info);
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_release_all_key(info);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_PARTIAL_DOWNLOAD
|
|
fts_command(info, FTS_CMD_FORCE_AUTOTUNE);
|
|
info->o_afe_ver = info->afe_ver;
|
|
#endif
|
|
|
|
if (touch_on) {
|
|
tsp_debug_info(true, info->dev, "%s: finger! do not run autotune\n", __func__);
|
|
} else {
|
|
tsp_debug_info(true, info->dev, "%s: run autotune\n", __func__);
|
|
fts_execute_autotune(info);
|
|
}
|
|
|
|
if (info->stm_ver != STM_VER7) {
|
|
fts_command(info, SLEEPOUT);
|
|
fts_delay(1);
|
|
}
|
|
fts_command(info, SENSEON);
|
|
|
|
#ifdef FTS_SUPPORT_WATER_MODE
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_WATER_SELF_DONE);
|
|
#else
|
|
if (info->stm_ver == STM_VER7)
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE_D3);
|
|
else
|
|
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE);
|
|
#endif
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
if (info->dt_data->support_mskey)
|
|
fts_command(info, FTS_CMD_KEY_SENSE_ON);
|
|
#endif
|
|
|
|
fts_interrupt_set(info, INT_ENABLE);
|
|
} else {
|
|
fts_irq_enable(info, true);
|
|
tsp_debug_info(true, &info->client->dev, "%s: digital_rev not matched, %d\n", __func__, info->digital_rev);
|
|
goto autotune_fail;
|
|
}
|
|
|
|
fts_irq_enable(info, true);
|
|
if (touch_on) {
|
|
snprintf(buff, sizeof(buff), "NG_FINGER_ON");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buff, sizeof(buff), "%s", "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
return;
|
|
|
|
autotune_fail:
|
|
snprintf(buff, sizeof(buff), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
|
|
return;
|
|
}
|
|
|
|
#ifdef FTS_SUPPORT_TOUCH_KEY
|
|
static int read_touchkey_data(struct fts_ts_info *info, unsigned char type, unsigned int keycode)
|
|
{
|
|
unsigned char pCMD[3] = { 0xD0, 0x00, 0x00};
|
|
unsigned char buf[9] = { 0 };
|
|
int i;
|
|
int ret = 0;
|
|
|
|
if (!info->dt_data->support_mskey) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touchkey is not supported\n",
|
|
__func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
pCMD[2] = type;
|
|
|
|
ret = fts_read_reg(info, &pCMD[0], 3, buf, 3);
|
|
if (ret >= 0) {
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1) {
|
|
pCMD[1] = buf[1];
|
|
pCMD[2] = buf[0];
|
|
} else {
|
|
pCMD[1] = buf[2];
|
|
pCMD[2] = buf[1];
|
|
}
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
ret = fts_read_reg(info, &pCMD[0], 3, buf, 9);
|
|
if (ret < 0)
|
|
return -2;
|
|
|
|
for (i = 0 ; i < info->dt_data->num_touchkey ; i++)
|
|
if (info->dt_data->touchkey[i].keycode == keycode) {
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1)
|
|
return *(short *)&buf[(info->dt_data->touchkey[i].value - 1) * 2];
|
|
else
|
|
return *(short *)&buf[(info->dt_data->touchkey[i].value - 1) * 2 + 1];
|
|
}
|
|
|
|
return -3;
|
|
}
|
|
|
|
static ssize_t touchkey_recent_strength(struct device *dev,
|
|
struct device_attribute *attr, char *buf) {
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
int value = 0;
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
value = read_touchkey_data(info, TYPE_TOUCHKEY_STRENGTH, KEY_RECENT);
|
|
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
static ssize_t touchkey_back_strength(struct device *dev,
|
|
struct device_attribute *attr, char *buf) {
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
int value = 0;
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
value = read_touchkey_data(info, TYPE_TOUCHKEY_STRENGTH, KEY_BACK);
|
|
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
static ssize_t touchkey_recent_raw(struct device *dev,
|
|
struct device_attribute *attr, char *buf) {
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
int value = 0;
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
value = read_touchkey_data(info, TYPE_TOUCHKEY_RAW, KEY_RECENT);
|
|
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
static ssize_t touchkey_back_raw(struct device *dev,
|
|
struct device_attribute *attr, char *buf) {
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
int value = 0;
|
|
|
|
if (info->touch_stopped) {
|
|
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
value = read_touchkey_data(info, TYPE_TOUCHKEY_RAW, KEY_BACK);
|
|
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", value);
|
|
}
|
|
|
|
static ssize_t touchkey_threshold(struct device *dev,
|
|
struct device_attribute *attr, char *buf) {
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
unsigned char pCMD[3] = { 0xD0, 0x00, 0x00};
|
|
int value;
|
|
int ret = 0;
|
|
|
|
value = -1;
|
|
pCMD[2] = TYPE_TOUCHKEY_THRESHOLD;
|
|
ret = fts_read_reg(info, &pCMD[0], 3, buf, 3);
|
|
if (ret >= 0) {
|
|
if (info->digital_rev == FTS_DIGITAL_REV_1)
|
|
value = *(unsigned short *)&buf[0];
|
|
else
|
|
value = *(unsigned short *)&buf[1];
|
|
}
|
|
|
|
info->touchkey_threshold = value;
|
|
return snprintf(buf, SEC_CMD_STR_LEN, "%d\n", info->touchkey_threshold);
|
|
}
|
|
|
|
static ssize_t fts_touchkey_led_control(struct device *dev,
|
|
struct device_attribute *attr, const char *buf,
|
|
size_t size)
|
|
{
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
int data, ret;
|
|
|
|
ret = sscanf(buf, "%d", &data);
|
|
tsp_debug_dbg(true, &info->client->dev, "%s, %d\n", __func__, data);
|
|
|
|
if (ret != 1) {
|
|
tsp_debug_err(true, &info->client->dev, "%s, %d err\n",
|
|
__func__, __LINE__);
|
|
return size;
|
|
}
|
|
|
|
if (data != 0 && data != 1) {
|
|
tsp_debug_err(true, &info->client->dev, "%s wrong cmd %x\n",
|
|
__func__, data);
|
|
return size;
|
|
}
|
|
|
|
if (info->led_power)
|
|
ret = info->led_power(info, data);
|
|
|
|
if (ret) {
|
|
tsp_debug_err(true, &info->client->dev, "%s: Error turn on led %d\n",
|
|
__func__, ret);
|
|
|
|
goto out;
|
|
}
|
|
msleep(30);
|
|
|
|
out:
|
|
return size;
|
|
}
|
|
|
|
#ifdef TKEY_BOOSTER
|
|
static ssize_t boost_level_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct fts_ts_info *info = dev_get_drvdata(dev);
|
|
int val, retval;
|
|
int stage;
|
|
|
|
if (!info->tkey_booster) {
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: booster is NULL\n", __func__);
|
|
return count;
|
|
}
|
|
|
|
tsp_debug_info(true, &info->client->dev, "%s\n", __func__);
|
|
sscanf(buf, "%d", &val);
|
|
|
|
stage = 1 << val;
|
|
|
|
if (!(info->tkey_booster->dvfs_stage & stage)) {
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: wrong cmd %d\n", __func__, val);
|
|
return count;
|
|
}
|
|
|
|
info->tkey_booster->dvfs_boost_mode = stage;
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: dvfs_boost_mode = 0x%X\n",
|
|
__func__, info->tkey_booster->dvfs_boost_mode);
|
|
|
|
if (info->tkey_booster->dvfs_boost_mode == DVFS_STAGE_DUAL) {
|
|
info->tkey_booster->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: boost_mode DUAL, dvfs_freq = %d\n",
|
|
__func__, info->tkey_booster->dvfs_freq);
|
|
} else if (info->tkey_booster->dvfs_boost_mode == DVFS_STAGE_SINGLE) {
|
|
info->tkey_booster->dvfs_freq = MIN_TOUCH_LIMIT;
|
|
tsp_debug_info(true, &info->client->dev,
|
|
"%s: boost_mode SINGLE, dvfs_freq = %d\n",
|
|
__func__, info->tkey_booster->dvfs_freq);
|
|
} else if (info->tkey_booster->dvfs_boost_mode == DVFS_STAGE_NONE) {
|
|
retval = info->tkey_booster->dvfs_off(info->tkey_booster);
|
|
if (retval < 0) {
|
|
tsp_debug_err(true, &info->client->dev,
|
|
"%s: booster stop failed(%d).\n",
|
|
__func__, retval);
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
#endif
|
|
|
|
static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL, fts_touchkey_led_control);
|
|
static DEVICE_ATTR(touchkey_recent, S_IRUGO, touchkey_recent_strength, NULL);
|
|
static DEVICE_ATTR(touchkey_back, S_IRUGO, touchkey_back_strength, NULL);
|
|
static DEVICE_ATTR(touchkey_recent_raw, S_IRUGO, touchkey_recent_raw, NULL);
|
|
static DEVICE_ATTR(touchkey_back_raw, S_IRUGO, touchkey_back_raw, NULL);
|
|
static DEVICE_ATTR(touchkey_threshold, S_IRUGO, touchkey_threshold, NULL);
|
|
#ifdef TKEY_BOOSTER
|
|
static DEVICE_ATTR(boost_level, S_IWUSR | S_IWGRP, NULL, boost_level_store);
|
|
#endif
|
|
|
|
static struct attribute *sec_touchkey_factory_attributes[] = {
|
|
&dev_attr_touchkey_recent.attr,
|
|
&dev_attr_touchkey_back.attr,
|
|
&dev_attr_touchkey_recent_raw.attr,
|
|
&dev_attr_touchkey_back_raw.attr,
|
|
&dev_attr_touchkey_threshold.attr,
|
|
&dev_attr_brightness.attr,
|
|
#ifdef TKEY_BOOSTER
|
|
&dev_attr_boost_level.attr,
|
|
#endif
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group sec_touchkey_factory_attr_group = {
|
|
.attrs = sec_touchkey_factory_attributes,
|
|
};
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|