android_kernel_samsung_on5x.../drivers/input/touchscreen/stm/fts_sec.c
2018-06-19 23:16:04 +02:00

4032 lines
114 KiB
C

#ifdef SEC_TSP_FACTORY_TEST
#define TSP_FACTEST_RESULT_PASS 2
#define TSP_FACTEST_RESULT_FAIL 1
#define TSP_FACTEST_RESULT_NONE 0
#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,
};
enum CMD_STATUS {
CMD_STATUS_WAITING = 0,
CMD_STATUS_RUNNING,
CMD_STATUS_OK,
CMD_STATUS_FAIL,
CMD_STATUS_NOT_APPLICABLE,
};
#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 run_rawcap_read(void *device_data);
static void get_rawcap(void *device_data);
static void run_delta_read(void *device_data);
static void get_delta(void *device_data);
static void run_abscap_read(void *device_data);
static void run_absdelta_read(void *device_data);
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_trx_short_test(void *device_data);
static void get_cx_data(void *device_data);
static void get_cx_all_data(void *device_data);
static void run_cx_data_read(void *device_data);
#ifdef FTS_SUPPORT_TOUCH_KEY
static void run_key_cx_data_read(void *device_data);
#endif
static void set_tsp_test_result(void *device_data);
static void get_tsp_test_result(void *device_data);
static void hover_enable(void *device_data);
/* static void hover_no_sleep_enable(void *device_data); */
static void glove_mode(void *device_data);
static void get_glove_sensitivity(void *device_data);
static void clear_cover_mode(void *device_data);
static void fast_glove_mode(void *device_data);
static void report_rate(void *device_data);
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
static void interrupt_control(void *device_data);
#endif
#if defined(CONFIG_INPUT_BOOSTER) || defined(TOUCH_BOOSTER_DVFS)
static void boost_level(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 second_screen_enable(void *device_data);
static void set_longpress_enable(void *device_data);
static void set_sidescreen_x_length(void *device_data);
static void set_dead_zone(void *device_data);
#ifdef SMARTCOVER_COVER
static void smartcover_cmd(void *device_data);
#endif
#ifdef FTS_SUPPORT_STRINGLIB
static void quick_shot_enable(void *device_data);
static void scrub_enable(void *device_data);
static void quick_app_access_enable(void *device_data);
static void direct_indicator_enable(void *device_data);
static void spay_enable(void *device_data);
#endif
static void delay(void *device_data);
static void debug(void *device_data);
static void run_autotune_enable(void *device_data);
static void run_autotune(void *device_data);
static void set_mainscreen_disable(void *device_data);
static void set_rotation_status(void *device_data);
static void not_support_cmd(void *device_data);
static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count);
static ssize_t show_cmd_status(struct device *dev,
struct device_attribute *devattr, char *buf);
static ssize_t show_cmd_result(struct device *dev,
struct device_attribute *devattr, char *buf);
static ssize_t cmd_list_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t fts_scrub_position(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t fts_edge_x_position(struct device *dev,
struct device_attribute *attr, char *buf);
#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
static void tui_mode_cmd(struct fts_ts_info *info);
#endif
#define FT_CMD(name, func) .cmd_name = name, .cmd_func = func
struct ft_cmd {
struct list_head list;
const char *cmd_name;
void (*cmd_func) (void *device_data);
};
struct ft_cmd ft_commands[] = {
{FT_CMD("fw_update", fw_update),},
{FT_CMD("get_fw_ver_bin", get_fw_ver_bin),},
{FT_CMD("get_fw_ver_ic", get_fw_ver_ic),},
{FT_CMD("get_config_ver", get_config_ver),},
{FT_CMD("get_threshold", get_threshold),},
{FT_CMD("module_off_master", module_off_master),},
{FT_CMD("module_on_master", module_on_master),},
{FT_CMD("module_off_slave", not_support_cmd),},
{FT_CMD("module_on_slave", not_support_cmd),},
{FT_CMD("get_chip_vendor", get_chip_vendor),},
{FT_CMD("get_chip_name", get_chip_name),},
{FT_CMD("get_x_num", get_x_num),},
{FT_CMD("get_y_num", get_y_num),},
{FT_CMD("get_checksum_data", get_checksum_data),},
{FT_CMD("run_reference_read", run_reference_read),},
{FT_CMD("get_reference", get_reference),},
{FT_CMD("run_rawcap_read", run_rawcap_read),},
{FT_CMD("get_rawcap", get_rawcap),},
{FT_CMD("run_delta_read", run_delta_read),},
{FT_CMD("get_delta", get_delta),},
{FT_CMD("run_abscap_read" , run_abscap_read),},
{FT_CMD("run_absdelta_read", run_absdelta_read),},
{FT_CMD("run_ix_data_read", run_ix_data_read),},
{FT_CMD("run_ix_data_read_all", run_ix_data_read_all),},
{FT_CMD("run_self_raw_read", run_self_raw_read),},
{FT_CMD("run_self_raw_read_all", run_self_raw_read_all),},
{FT_CMD("run_trx_short_test", run_trx_short_test),},
{FT_CMD("get_cx_data", get_cx_data),},
{FT_CMD("get_cx_all_data", get_cx_all_data),},
{FT_CMD("run_cx_data_read", run_cx_data_read),},
#ifdef FTS_SUPPORT_TOUCH_KEY
{FT_CMD("run_key_cx_data_read", run_key_cx_data_read),},
#endif
{FT_CMD("set_tsp_test_result", set_tsp_test_result),},
{FT_CMD("get_tsp_test_result", get_tsp_test_result),},
{FT_CMD("hover_enable", hover_enable),},
{FT_CMD("hover_no_sleep_enable", not_support_cmd),},
{FT_CMD("glove_mode", glove_mode),},
{FT_CMD("get_glove_sensitivity", get_glove_sensitivity),},
{FT_CMD("clear_cover_mode", clear_cover_mode),},
{FT_CMD("fast_glove_mode", fast_glove_mode),},
{FT_CMD("report_rate", report_rate),},
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
{FT_CMD("interrupt_control", interrupt_control),},
#endif
#if defined(CONFIG_INPUT_BOOSTER)|| defined(TOUCH_BOOSTER_DVFS)
{FT_CMD("boost_level", boost_level),},
#endif
{FT_CMD("set_lowpower_mode", set_lowpower_mode),},
{FT_CMD("set_deepsleep_mode", set_deepsleep_mode),},
{FT_CMD("active_sleep_enable", active_sleep_enable),},
{FT_CMD("second_screen_enable", second_screen_enable),},
{FT_CMD("set_longpress_enable", set_longpress_enable),},
{FT_CMD("set_sidescreen_x_length", set_sidescreen_x_length),},
{FT_CMD("set_dead_zone", set_dead_zone),},
#ifdef FTS_SUPPORT_STRINGLIB
{FT_CMD("quick_shot_enable", quick_shot_enable),},
{FT_CMD("scrub_enable", scrub_enable),},
{FT_CMD("quick_app_access_enable", quick_app_access_enable),},
{FT_CMD("direct_indicator_enable", direct_indicator_enable),},
{FT_CMD("spay_enable", spay_enable),},
#endif
#ifdef SMARTCOVER_COVER
{FT_CMD("smartcover_cmd", smartcover_cmd),},
#endif
{FT_CMD("delay", delay),},
{FT_CMD("debug", debug),},
{FT_CMD("run_autotune_enable", run_autotune_enable),},
{FT_CMD("run_autotune", run_autotune),},
{FT_CMD("set_mainscreen_disable", set_mainscreen_disable),},
{FT_CMD("set_rotation_status", set_rotation_status),},
{FT_CMD("not_support_cmd", not_support_cmd),},
};
static DEVICE_ATTR(cmd, S_IWUSR | S_IWGRP, NULL, store_cmd);
static DEVICE_ATTR(cmd_status, S_IRUGO, show_cmd_status, NULL);
static DEVICE_ATTR(cmd_result, S_IRUGO, show_cmd_result, NULL);
static DEVICE_ATTR(cmd_list, S_IRUGO, cmd_list_show, NULL);
static DEVICE_ATTR(scrub_pos, S_IRUGO, fts_scrub_position, NULL);
static DEVICE_ATTR(edge_pos, S_IRUGO, fts_edge_x_position, NULL);
static struct attribute *sec_touch_facotry_attributes[] = {
&dev_attr_cmd.attr,
&dev_attr_cmd_status.attr,
&dev_attr_cmd_result.attr,
&dev_attr_cmd_list.attr,
&dev_attr_scrub_pos.attr,
&dev_attr_edge_pos.attr,
NULL,
};
static struct attribute_group sec_touch_factory_attr_group = {
.attrs = sec_touch_facotry_attributes,
};
static int fts_check_index(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
int node;
if (info->cmd_param[0] < 0
|| info->cmd_param[0] >= info->SenseChannelLength
|| info->cmd_param[1] < 0
|| info->cmd_param[1] >= info->ForceChannelLength) {
snprintf(buff, sizeof(buff), "%s", "NG");
strncat(info->cmd_result, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_FAIL;
tsp_debug_info(true, &info->client->dev, "%s: parameter error: %u,%u\n",
__func__, info->cmd_param[0], info->cmd_param[1]);
node = -1;
return node;
}
node = info->cmd_param[1] * info->SenseChannelLength + info->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 fts_ts_info *info = dev_get_drvdata(dev);
char buff[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, TSP_BUF_SIZE, "%s\n", buff);
}
static ssize_t fts_edge_x_position(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fts_ts_info *info = dev_get_drvdata(dev);
char buff[CMD_STR_LEN] = { 0 };
int edge_position_left, edge_position_right;
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;
}
#ifdef CONFIG_SEC_FACTORY
if ((lcdtype == S6E3HF2_WQXGA_ID1) || (lcdtype == S6E3HF2_WQXGA_ID2)) {
edge_position_left = -1;
edge_position_right = info->board->max_x + 1 - info->board->grip_area;
} else {
edge_position_left = info->board->grip_area;
edge_position_right = info->board->max_x + 1 - info->board->grip_area;
}
#else
edge_position_left = info->board->grip_area;
edge_position_right = info->board->max_x + 1 - info->board->grip_area;
#endif
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, TSP_BUF_SIZE, "%s\n", buff);
}
static void clear_cover_cmd_work(struct work_struct *work)
{
struct fts_ts_info *info = container_of(work, struct fts_ts_info,
cover_cmd_work.work);
if (info->cmd_is_running) {
schedule_delayed_work(&info->cover_cmd_work, msecs_to_jiffies(5));
} else {
/* check lock */
mutex_lock(&info->cmd_lock);
info->cmd_is_running = true;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_RUNNING;
tsp_debug_err(true, &info->client->dev,
"%s param = %d, %d\n", __func__,
info->delayed_cmd_param[0], info->delayed_cmd_param[1]);
info->cmd_param[0] = info->delayed_cmd_param[0];
if (info->delayed_cmd_param[0] > 1)
info->cmd_param[1] = info->delayed_cmd_param[1];
strcpy(info->cmd, "clear_cover_mode");
clear_cover_mode(info);
}
}
static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
struct fts_ts_info *info = dev_get_drvdata(dev);
char *cur, *start, *end;
char buff[CMD_STR_LEN] = { 0 };
int len, i;
struct ft_cmd *ft_cmd_ptr = NULL;
char delim = ',';
bool cmd_found = false;
int param_cnt = 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;
}
if (count > CMD_STR_LEN) {
printk(KERN_ERR "%s: overflow command length\n",
__func__);
return -EINVAL;
}
if (info->cmd_is_running == true) {
tsp_debug_err(true, &info->client->dev, "ft_cmd: other cmd is running.\n");
if (strncmp("clear_cover_mode", buf, 16) == 0) {
cancel_delayed_work(&info->cover_cmd_work);
tsp_debug_err(true, &info->client->dev,
"[cmd is delayed] %d, param = %d, %d\n", __LINE__, buf[17]-'0', buf[19]-'0');
info->delayed_cmd_param[0] = buf[17]-'0';
if (info->delayed_cmd_param[0] > 1)
info->delayed_cmd_param[1] = buf[19]-'0';
schedule_delayed_work(&info->cover_cmd_work, msecs_to_jiffies(10));
}
return -EBUSY;
}
else if (info->reinit_done == false) {
tsp_debug_err(true, &info->client->dev, "ft_cmd: reinit is working\n");
if (strncmp("clear_cover_mode", buf, 16) == 0) {
cancel_delayed_work(&info->cover_cmd_work);
tsp_debug_err(true, &info->client->dev,
"[cmd is delayed] %d, param = %d, %d\n", __LINE__, buf[17]-'0', buf[19]-'0');
info->delayed_cmd_param[0] = buf[17]-'0';
if (info->delayed_cmd_param[0] > 1)
info->delayed_cmd_param[1] = buf[19]-'0';
if(info->delayed_cmd_param[0] == 0) schedule_delayed_work(&info->cover_cmd_work, msecs_to_jiffies(300));
}
}
/* check lock */
mutex_lock(&info->cmd_lock);
info->cmd_is_running = true;
mutex_unlock(&info->cmd_lock);
info->cmd_state = 1;
memset(info->cmd_param, 0x00, ARRAY_SIZE(info->cmd_param));
len = (int)count;
if (*(buf + len - 1) == '\n')
len--;
memset(info->cmd, 0x00, ARRAY_SIZE(info->cmd));
memcpy(info->cmd, buf, len);
cur = strchr(buf, (int)delim);
if (cur)
memcpy(buff, buf, cur - buf);
else
memcpy(buff, buf, len);
tsp_debug_info(true, &info->client->dev, "COMMAND : %s\n", buff);
/* find command */
list_for_each_entry(ft_cmd_ptr, &info->cmd_list_head, list) {
if (!strncmp(buff, ft_cmd_ptr->cmd_name, CMD_STR_LEN)) {
cmd_found = true;
break;
}
}
/* set not_support_cmd */
if (!cmd_found) {
list_for_each_entry(ft_cmd_ptr, &info->cmd_list_head, list) {
if (!strncmp
("not_support_cmd", ft_cmd_ptr->cmd_name,
CMD_STR_LEN))
break;
}
}
/* parsing parameters */
if (cur && cmd_found) {
cur++;
start = cur;
memset(buff, 0x00, ARRAY_SIZE(buff));
do {
if (*cur == delim || cur - buf == len) {
end = cur;
memcpy(buff, start, end - start);
*(buff + strnlen(buff, ARRAY_SIZE(buff))) =
'\0';
if (kstrtoint
(buff, 10,
info->cmd_param + param_cnt) < 0)
goto err_out;
start = cur + 1;
memset(buff, 0x00, ARRAY_SIZE(buff));
param_cnt++;
}
cur++;
} while (cur - buf <= len);
}
tsp_debug_info(true, &info->client->dev, "cmd = %s\n", ft_cmd_ptr->cmd_name);
for (i = 0; i < param_cnt; i++)
tsp_debug_info(true, &info->client->dev, "cmd param %d= %d\n", i,
info->cmd_param[i]);
#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
if (TRUSTEDUI_MODE_INPUT_SECURED & trustedui_get_current_mode())
tui_mode_cmd(info);
else
#endif
ft_cmd_ptr->cmd_func(info);
err_out:
return count;
}
static ssize_t show_cmd_status(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct fts_ts_info *info = dev_get_drvdata(dev);
char buff[16] = { 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, "tsp cmd: status:%d\n", info->cmd_state);
if (info->cmd_state == CMD_STATUS_WAITING)
snprintf(buff, sizeof(buff), "WAITING");
else if (info->cmd_state == CMD_STATUS_RUNNING)
snprintf(buff, sizeof(buff), "RUNNING");
else if (info->cmd_state == CMD_STATUS_OK)
snprintf(buff, sizeof(buff), "OK");
else if (info->cmd_state == CMD_STATUS_FAIL)
snprintf(buff, sizeof(buff), "FAIL");
else if (info->cmd_state == CMD_STATUS_NOT_APPLICABLE)
snprintf(buff, sizeof(buff), "NOT_APPLICABLE");
return snprintf(buf, TSP_BUF_SIZE, "%s\n", buff);
}
static ssize_t show_cmd_result(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct fts_ts_info *info = dev_get_drvdata(dev);
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, "tsp cmd: result: %s\n",
info->cmd_result);
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = 0;
return snprintf(buf, TSP_BUF_SIZE, "%s\n", info->cmd_result);
}
static ssize_t cmd_list_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fts_ts_info *info = dev_get_drvdata(dev);
int ii = 0;
char buffer[info->cmd_buffer_size+CMD_STR_LEN];
char buffer_name[CMD_STR_LEN];
snprintf(buffer, CMD_STR_LEN, "++factory command list++\n");
while (strncmp(ft_commands[ii].cmd_name, "not_support_cmd", 16) != 0) {
snprintf(buffer_name, CMD_STR_LEN, "%s\n", ft_commands[ii].cmd_name);
strcat(buffer, buffer_name);
ii++;
}
tsp_debug_info(true, &info->client->dev,
"%s: length : %u / %d\n", __func__,
(unsigned int)strlen(buffer), info->cmd_buffer_size+CMD_STR_LEN);
return snprintf(buf, TSP_BUF_SIZE, "%s\n", buffer);
}
static void set_default_result(struct fts_ts_info *info)
{
char delim = ':';
memset(info->cmd_result, 0x00, ARRAY_SIZE(info->cmd_result));
memcpy(info->cmd_result, info->cmd, strnlen(info->cmd, CMD_STR_LEN));
strncat(info->cmd_result, &delim, 1);
}
static void set_cmd_result(struct fts_ts_info *info, char *buff, int len)
{
strncat(info->cmd_result, buff, len);
}
#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
static void tui_mode_cmd(struct fts_ts_info *info)
{
char buff[16] = "TUImode:FAIL";
set_default_result(info);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
static void not_support_cmd(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
set_default_result(info);
snprintf(buff, sizeof(buff), "%s", "NA");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
tsp_debug_info(true, &info->client->dev, "%s: \"%s\"\n", __func__, buff);
}
static void fw_update(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[64] = { 0 };
int retval = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
retval = fts_fw_update_on_hidden_menu(info, info->cmd_param[0]);
if (retval < 0) {
sprintf(buff, "%s", "NA");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_FAIL;
tsp_debug_info(true, &info->client->dev, "%s: failed [%d]\n", __func__, retval);
} else {
sprintf(buff, "%s", "OK");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 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;
unsigned char cmd[4] =
{ 0xB2, 0x00, 0x14, 0x02 };
unsigned char data[FTS_EVENT_SIZE];
int retry = 0;
memset(data, 0x0, FTS_EVENT_SIZE);
rc = -1;
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) {
if ((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;
}
mdelay(5);
}
return rc;
}
static void procedure_cmd_event(struct fts_ts_info *info, unsigned char *data)
{
char buff[16] = { 0 };
if ((data[1] == 0x00) && (data[2] == 0x62))
{
snprintf(buff, sizeof(buff), "%d",
*(unsigned short *)&data[3]);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", "get_threshold", buff);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
}
else if ((data[1] == 0x01) && (data[2] == 0xC6))
{
snprintf(buff, sizeof(buff), "%d",
*(unsigned short *)&data[3]);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", "get_glove_sensitivity", buff);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
}
else if ((data[1] == 0x07) && (data[2] == 0xE7))
{
if (data[3] <= TSP_FACTEST_RESULT_PASS) {
sprintf(buff, "%s",
data[3] == TSP_FACTEST_RESULT_PASS ? "PASS" :
data[3] == TSP_FACTEST_RESULT_FAIL ? "FAIL" : "NONE");
tsp_debug_info(true, &info->client->dev, "%s: success [%s][%d]", "get_tsp_test_result",
data[3] == TSP_FACTEST_RESULT_PASS ? "PASS" :
data[3] == TSP_FACTEST_RESULT_FAIL ? "FAIL" :
"NONE", data[3]);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
}
else
{
snprintf(buff, sizeof(buff), "%s", "NG");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_FAIL;
tsp_debug_info(true, &info->client->dev, "%s: %s\n",
"get_tsp_test_result",
buff);
}
}
}
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);
}
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)
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) {
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;
fts_systemreset(info);
fts_wait_for_ready(info);
fts_command(info, SLEEPOUT);
fts_delay(20);
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_write_reg(info, &regAdd[0], 4);
fts_command(info, FLUSHBUFFER);
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 0x0E :
tsp_debug_info(true, &info->client->dev, "[FTS] ITO Test result : Sennse channel [%d] short to sense.\n",
data[3]);
break;
default:
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 */
fts_wait_for_ready(info);
#ifdef FTS_SUPPORT_NOISE_PARAM
fts_set_noise_param(info);
#endif
fts_command(info, SLEEPOUT);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
if (info->hover_enabled)
fts_command(info, FTS_CMD_HOVER_ON);
if (info->flip_enable) {
fts_set_cover_type(info, true);
} else {
if (info->mshover_enabled)
fts_command(info, FTS_CMD_MSHOVER_ON);
}
#ifdef FTS_SUPPORT_TA_MODE
if (info->TA_Pluged)
fts_command(info, FTS_CMD_CHARGER_PLUGGED);
#endif
info->touch_count = 0;
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_ENABLE);
enable_irq(info->irq);
return result;
}
static void get_fw_ver_bin(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
set_default_result(info);
if (strncmp(info->board->model_name, "G925", 4) == 0) {
info->tspid_val= gpio_get_value(info->board->tspid);
info->tspid2_val= gpio_get_value(info->board->tspid2);
sprintf(buff, "ST%01X%01X%04X",
info->tspid_val, info->tspid2_val,
info->fw_main_version_of_bin);
} else if (strncmp(info->board->model_name, "G920", 4) == 0) {
sprintf(buff, "ST%02X%04X",
info->panel_revision,
info->fw_main_version_of_bin);
} else {
tsp_debug_info(true, &info->client->dev, "%s: Check model name[%s]!\n",
__func__, info->board->model_name);
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_fw_ver_ic(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
set_default_result(info);
if (strncmp(info->board->model_name, "G925", 4) == 0) {
info->tspid_val= gpio_get_value(info->board->tspid);
info->tspid2_val= gpio_get_value(info->board->tspid2);
sprintf(buff, "ST%01X%01X%04X",
info->tspid_val, info->tspid2_val,
info->fw_main_version_of_ic);
} else if (strncmp(info->board->model_name, "G920", 4) == 0) {
sprintf(buff, "ST%02X%04X",
info->panel_revision,
info->fw_main_version_of_ic);
} else {
tsp_debug_info(true, &info->client->dev, "%s: Check model name[%s]!\n",
__func__, info->board->model_name);
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_config_ver(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[20] = { 0 };
snprintf(buff, sizeof(buff), "%s_ST_%04X",
info->board->model_name ?: info->board->project_name ?: STM_DEVICE_NAME,
info->config_version_of_ic);
set_default_result(info);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_threshold(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned char cmd[4] =
{ 0xB2, 0x00, 0x62, 0x02 };
int timeout=0;
set_default_result(info);
if (info->touch_stopped) {
char buff[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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_write_reg(info, &cmd[0], 4);
info->cmd_state = CMD_STATUS_RUNNING;
while (info->cmd_state == CMD_STATUS_RUNNING) {
if (timeout++>30) {
info->cmd_state = CMD_STATUS_FAIL;
break;
}
msleep(10);
}
}
static void module_off_master(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[3] = { 0 };
int ret = 0;
mutex_lock(&info->lock);
if (info->enabled) {
disable_irq(info->irq);
info->enabled = false;
}
mutex_unlock(&info->lock);
if (info->board->power)
info->board->power(info, false);
else
ret = 1;
if (ret == 0)
snprintf(buff, sizeof(buff), "%s", "OK");
else
snprintf(buff, sizeof(buff), "%s", "NG");
set_default_result(info);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
if (strncmp(buff, "OK", 2) == 0)
info->cmd_state = CMD_STATUS_OK;
else
info->cmd_state = CMD_STATUS_FAIL;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void module_on_master(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[3] = { 0 };
int ret = 0;
mutex_lock(&info->lock);
if (!info->enabled) {
enable_irq(info->irq);
info->enabled = true;
}
mutex_unlock(&info->lock);
if (info->board->power)
info->board->power(info, true);
else
ret = 1;
if (ret == 0)
snprintf(buff, sizeof(buff), "%s", "OK");
else
snprintf(buff, sizeof(buff), "%s", "NG");
set_default_result(info);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
if (strncmp(buff, "OK", 2) == 0)
info->cmd_state = CMD_STATUS_OK;
else
info->cmd_state = CMD_STATUS_FAIL;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_chip_vendor(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
strncpy(buff, "STM", sizeof(buff));
set_default_result(info);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_chip_name(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
if (info->ic_product_id)
strncpy(buff, "FTS4BD056", sizeof(buff));
else
strncpy(buff, "FTS4BD062", sizeof(buff));
set_default_result(info);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_x_num(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
set_default_result(info);
snprintf(buff, sizeof(buff), "%d", info->SenseChannelLength);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 2;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_y_num(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
set_default_result(info);
snprintf(buff, sizeof(buff), "%d", info->ForceChannelLength);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_checksum_data(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[16] = { 0 };
int rc;
unsigned char regAdd[3];
unsigned char buf[5];
set_default_result(info);
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);
snprintf(buff, sizeof(buff), "%02X%02X%02X%02X", buf[1], buf[2], buf[3], buf[4]);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_reference_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
set_default_result(info);
if (info->touch_stopped) {
char buff[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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_read_frame(info, TYPE_BASELINE_DATA, &min, &max);
snprintf(buff, sizeof(buff), "%d,%d", min, max);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_reference(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
val = info->pFrame[node];
snprintf(buff, sizeof(buff), "%d", val);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_rawcap_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
unsigned char regAdd[4] = {0xB0, 0x04, 0x49, 0x00};
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
if (!info->run_autotune && (info->digital_rev == FTS_DIGITAL_REV_2))
goto rawcap_read;
else
tsp_debug_info(true, &info->client->dev, "%s: set autotune\n\n", __func__);
disable_irq(info->irq);
if (info->digital_rev == FTS_DIGITAL_REV_1) {
unsigned char data[FTS_EVENT_SIZE];
unsigned char regAdd;
int fail_retry = 0;
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, CX_TUNNING);
fts_delay(300);
regAdd = READ_ONE_EVENT;
while (fts_read_reg(info, &regAdd, 1, (unsigned char *)data, FTS_EVENT_SIZE)) {
if ((data[0] == EVENTID_STATUS_EVENT) &&
(data[1] == STATUS_EVENT_MUTUAL_AUTOTUNE_DONE)) {
break;
}
if (fail_retry++ > FTS_RETRY_COUNT * 15) {
tsp_debug_info(true, info->dev, "%s: Raw data read Time Over\n", __func__);
break;
}
fts_delay(10);
}
fts_fw_wait_for_event(info, STATUS_EVENT_MUTUAL_AUTOTUNE_DONE);
fts_fw_wait_for_event (info, STATUS_EVENT_WATER_SELF_AUTOTUNE_DONE);
fts_interrupt_set(info, INT_ENABLE);
} else if ((info->digital_rev == FTS_DIGITAL_REV_2)
#ifdef CONFIG_SEC_DEBUG_TSP_LOG
&& !info->rawdata_read_lock
#endif
) {
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF); // Key Sensor OFF
}
#endif
fts_command(info, FLUSHBUFFER);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
fts_release_all_key(info);
#endif
fts_execute_autotune(info);
//STMicro Auto-tune protection disable
fts_write_reg(info, regAdd, 4);
fts_delay(1);
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
fts_fw_wait_for_event (info, STATUS_EVENT_FORCE_CAL_DONE);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
}
enable_irq(info->irq);
rawcap_read:
fts_delay(50);
fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max);
snprintf(buff, sizeof(buff), "%d,%d", min, max);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_rawcap(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
val = info->pFrame[node];
snprintf(buff, sizeof(buff), "%d", val);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_delta_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
snprintf(buff, sizeof(buff), "%d,%d", min, max);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_delta(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
val = info->pFrame[node];
snprintf(buff, sizeof(buff), "%d", val);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
void fts_read_self_frame(struct fts_ts_info *info, unsigned short oAddr)
{
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
while (!info->hover_ready) {
if (retry++ > 500) {
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, &regAdd[0], 3, (unsigned char *)&buff[0], 5);
if (!rc) {
info->cmd_state = 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) {
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, &regAdd[0], 3,
(unsigned char *)&buff[0],
info->SenseChannelLength * 2 + 1);
if (!rc) {
info->cmd_state = CMD_STATUS_FAIL;
return;
}
if (info->digital_rev == FTS_DIGITAL_REV_1)
data = (short *)&buff[0];
else
data = (short *)&buff[1];
memset(temp, 0x00, ARRAY_SIZE(temp));
memset(temp2, 0x00, ARRAY_SIZE(temp2));
for (i = 0; i < info->SenseChannelLength; i++) {
tsp_debug_info(true, &info->client->dev,
"%s: Rx [%d] = %d\n", __func__,
i,
*data);
sprintf(temp, "%d,", *data);
strncat(temp2, temp, 9);
data++;
}
rc = info->fts_read_reg(info, &regAdd[3], 3,
(unsigned char *)&buff[0],
info->ForceChannelLength * 2 + 1);
if (!rc) {
info->cmd_state = 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);
sprintf(temp, "%d,", *data);
strncat(temp2, temp, 9);
data++;
}
set_cmd_result(info, temp2, strnlen(temp2, sizeof(temp2)));
info->cmd_state = CMD_STATUS_OK;
}
static void run_abscap_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
set_default_result(info);
fts_read_self_frame(info, 0x000E);
}
static void run_absdelta_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
set_default_result(info);
fts_read_self_frame(info, 0x0012);
}
#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)
{
char buff[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 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 regAdd[FTS_EVENT_SIZE];
unsigned char tx_ix1 = 0, rx_ix1 = 0;
unsigned char buf[FTS_EVENT_SIZE] = {0};
unsigned char r_addr = READ_ONE_EVENT;
unsigned short force_ix_data[info->ForceChannelLength * 2 + 1];
unsigned short sense_ix_data[info->SenseChannelLength * 2 + 1];
int buff_size,j;
char *mbuff = NULL;
int num,n,a,fzero;
char cnum;
int retry = 0, i = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
// fts_command(info, SLEEPIN); // Sleep In for INT disable
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
}
#endif
fts_command(info, FLUSHBUFFER); // Clear FIFO
fts_delay(50);
regAdd[0] = 0xB2;
regAdd[1] = (ix1_addr >> 8)&0xff;
regAdd[2] = (ix1_addr&0xff);
regAdd[3] = 0x04;
fts_write_reg(info, &regAdd[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 = buf[3] * 2;
rx_ix1 = buf[4] * 2;
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, &regAdd[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, &regAdd[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];
}
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);
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
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
enable_irq(info->irq);
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 = 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]);
}
set_cmd_result(info, mbuff, buff_size);
info->cmd_state = CMD_STATUS_OK;
kfree(mbuff);
}
else {
if(allnode == true){
snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
info->cmd_state = 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);
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, 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 fts_ts_info *info = (struct fts_ts_info *)device_data;
set_default_result(info);
fts_read_ix_data(info, false);
}
static void run_ix_data_read_all(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
set_default_result(info);
fts_read_ix_data(info, true);
}
static void fts_read_self_raw_frame(struct fts_ts_info *info, unsigned short oAddr, bool allnode)
{
char buff[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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
// fts_command(info, SLEEPIN); // Sleep In for INT disable
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->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 );
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
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
enable_irq(info->irq);
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]);
}
set_cmd_result(info, mbuff, buff_size);
info->cmd_state = CMD_STATUS_OK;
kfree(mbuff);
}
else {
if(allnode == true){
snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
info->cmd_state = 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);
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, 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 fts_ts_info *info = (struct fts_ts_info *)device_data;
set_default_result(info);
fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR,false);
}
static void run_self_raw_read_all(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
set_default_result(info);
fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR,true);
}
static void run_trx_short_test(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
int ret = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
ret = fts_panel_ito_test(info);
if (ret == 0)
snprintf(buff, sizeof(buff), "%s", "OK");
else
snprintf(buff, sizeof(buff), "%s", "FAIL");
enable_irq(info->irq);
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#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
static void get_cx_data(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 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);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_OK;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_cx_all_data(void *device_data)
{
const char HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char mbuff[CMD_STR_LEN] = { 0 };
char *buff;
int i, j, buff_size;
set_default_result(info);
if (info->touch_stopped) {
tsp_debug_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(mbuff, sizeof(mbuff), "%s", "TSP turned off");
set_cmd_result(info, mbuff, strnlen(mbuff, sizeof(mbuff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
buff_size = info->ForceChannelLength * info->SenseChannelLength * 2;
buff = kzalloc(buff_size, GFP_KERNEL);
if (buff != NULL) {
char *pBuf = buff;
if (info->cx_data) {
for (j = 0; j < info->ForceChannelLength; j++) {
for(i = 0; i < info->SenseChannelLength; i++) {
*pBuf++ = HEX[(info->cx_data[(j * info->SenseChannelLength) + i] >> 4)&0x0f];
*pBuf++ = HEX[info->cx_data[(j * info->SenseChannelLength) + i]&0x0f];
}
// tsp_debug_info(true, &info->client->dev, "%s", info->cx_data[(j * info->SenseChannelLength) + i]);
}
//tsp_debug_info(true, &info->client->dev, "%s", info->cx_data[(j * info->SenseChannelLength) + i]);
}
set_cmd_result(info, buff, buff_size);
info->cmd_state = 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");
set_cmd_result(info, mbuff, strnlen(mbuff, sizeof(mbuff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
}
}
static void run_cx_data_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
unsigned char ReadData[info->ForceChannelLength][info->SenseChannelLength + FTS_CX2_READ_LENGTH];
unsigned char regAdd[8];
unsigned char buf[8];
unsigned char r_addr = READ_ONE_EVENT;
unsigned int addr, rx_num, tx_num;
int i, j, cx_rx_length, max_tx_length, max_rx_length, address_offset = 0, start_tx_offset = 0, retry = 0;
unsigned char *pStr = NULL;
unsigned char pTmp[16] = { 0 };
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL);
if (pStr == NULL) {
tsp_debug_info(true, &info->client->dev, "FTS pStr kzalloc failed\n");
return;
}
tsp_debug_info(true, &info->client->dev, "%s: start \n", __func__);
fts_command(info, SENSEOFF);
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF); // Key Sensor OFF
}
#endif
disable_irq(info->irq);
fts_command(info, FLUSHBUFFER);
fts_delay(50);
tx_num = info->ForceChannelLength;
rx_num = info->SenseChannelLength;
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;
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, &regAdd[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;
}
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);
}
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];
}
}
kfree(pStr);
snprintf(buff, sizeof(buff), "%s", "OK");
enable_irq(info->irq);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_ON);
}
#endif
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#ifdef FTS_SUPPORT_TOUCH_KEY
#define USE_KEY_NUM 2
static void run_key_cx_data_read(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[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;
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
addr = FTS_CX2_BASE_ADDR;
regAdd[0] = 0xB2;
regAdd[1] = (addr >> 8) & 0xff;
regAdd[2] = (addr & 0xff);
regAdd[3] = 0x04;
fts_write_reg(info, &regAdd[0], 4);
fts_delay(1);
retry = FTS_RETRY_COUNT * 10;
do {
if (retry < 0) {
tsp_debug_info(true, &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];
tsp_debug_info(true, &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]);
enable_irq(info->irq);
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
static void set_tsp_test_result(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
unsigned char regAdd[4] = {0xB0, 0x07, 0xE7, 0x00};
set_default_result(info);
if (info->cmd_param[0] < TSP_FACTEST_RESULT_NONE
|| info->cmd_param[0] > TSP_FACTEST_RESULT_PASS) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
regAdd[3] = info->cmd_param[0];
fts_write_reg(info, &regAdd[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);
enable_irq(info->irq);
fts_interrupt_set(info, INT_ENABLE);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_tsp_test_result(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned char cmd[4] = {0xB2, 0x07, 0xE7, 0x01};
int timeout = 0;
set_default_result(info);
if (info->touch_stopped) {
char buff[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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_command(info, FLUSHBUFFER);
fts_write_reg(info, &cmd[0], 4);
info->cmd_state = CMD_STATUS_RUNNING;
while (info->cmd_state == CMD_STATUS_RUNNING) {
if (timeout++>30) {
info->cmd_state = CMD_STATUS_FAIL;
break;
}
fts_delay(10);
}
}
static void hover_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->touch_stopped || !(info->reinit_done) || (info->fts_power_state == FTS_POWER_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->fts_power_state);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
if(info->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 (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
int enables;
enables = info->cmd_param[0];
if (enables == info->hover_enabled) {
tsp_debug_dbg(true, &info->client->dev,
"%s: Skip duplicate command. Hover is already %s.\n",
__func__, info->hover_enabled ? "enabled" : "disabled");
} else {
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, &regAdd[0], 4);
fts_command(info, FTS_CMD_HOVER_ON);
info->hover_enabled = true;
info->hover_ready = false;
} 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");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
out:
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
/* static void hover_no_sleep_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned char regAdd[4] = {0xB0, 0x01, 0x18, 0x00};
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if (info->cmd_param[0]) {
regAdd[3]=0x0F;
} else {
regAdd[3]=0x08;
}
fts_write_reg(info, &regAdd[0], 4);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
} */
static void glove_mode(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
info->mshover_enabled = info->cmd_param[0];
if (!info->touch_stopped && info->reinit_done) {
if (info->mshover_enabled)
fts_command(info, FTS_CMD_MSHOVER_ON);
else
fts_command(info, FTS_CMD_MSHOVER_OFF);
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_glove_sensitivity(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned char cmd[4] =
{ 0xB2, 0x01, 0xC6, 0x02 };
int timeout=0;
set_default_result(info);
if (info->touch_stopped) {
char buff[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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_write_reg(info, &cmd[0], 4);
info->cmd_state = CMD_STATUS_RUNNING;
while (info->cmd_state == CMD_STATUS_RUNNING) {
if (timeout++>30) {
info->cmd_state = CMD_STATUS_FAIL;
break;
}
msleep(10);
}
}
static void clear_cover_mode(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 3) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if (info->cmd_param[0] > 1) {
info->flip_enable = true;
info->cover_type = info->cmd_param[1];
} else {
info->flip_enable = false;
}
if (!info->touch_stopped && info->reinit_done) {
if (info->flip_enable) {
if (info->mshover_enabled
&& (strncmp(info->board->project_name, "TB", 2) != 0))
fts_command(info, FTS_CMD_MSHOVER_OFF);
fts_set_cover_type(info, true);
} else {
fts_set_cover_type(info, false);
if (info->fast_mshover_enabled)
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
else if (info->mshover_enabled)
fts_command(info, FTS_CMD_MSHOVER_ON);
}
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
static void fast_glove_mode(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
info->fast_mshover_enabled = info->cmd_param[0];
if (!info->touch_stopped && info->reinit_done) {
if (info->fast_mshover_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");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
static void report_rate(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 2) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if (info->cmd_param[0] == REPORT_RATE_90HZ)
fts_change_scan_rate(info, FTS_CMD_FAST_SCAN);
else if (info->cmd_param[0] == REPORT_RATE_60HZ)
fts_change_scan_rate(info, FTS_CMD_SLOW_SCAN);
else if (info->cmd_param[0] == REPORT_RATE_30HZ)
fts_change_scan_rate(info, FTS_CMD_USLOW_SCAN);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
out:
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
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 fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
int enables;
enables = info->cmd_param[0];
if (enables)
fts_irq_enable(info, true);
else
fts_irq_enable(info, false);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
out:
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
#if defined(CONFIG_INPUT_BOOSTER)
static void boost_level(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
unsigned char max_level = 4;
#ifdef CONFIG_INPUT_BOOSTER
max_level = BOOSTER_LEVEL_MAX;
#endif
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] >= max_level) {
snprintf(buff, sizeof(buff), "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
#ifdef CONFIG_INPUT_BOOSTER
change_booster_level_for_tsp(info->cmd_param[0]);
#endif
tsp_debug_dbg(false, &info->client->dev,
"%s %d\n",
__func__, info->cmd_param[0]);
snprintf(buff, sizeof(buff), "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_WAITING;
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
return;
}
#endif
bool check_lowpower_mode(struct fts_ts_info *info)
{
bool ret = 0;
unsigned char flag = info->lowpower_flag & 0xFF;
if (flag)
ret = 1;
tsp_debug_info(true, &info->client->dev,
"%s: lowpower_mode flag : %d, ret:%d\n", __func__, flag, ret);
if (flag & FTS_LOWP_FLAG_QUICK_CAM)
tsp_debug_info(true, &info->client->dev, "%s: quick cam *- on\n", __func__);
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: swipe finger on\n", __func__);
if (flag & FTS_LOWP_FLAG_QUICK_APP_ACCESS)
tsp_debug_info(true, &info->client->dev, "%s: quick app cmd on\n", __func__);
if (flag & FTS_LOWP_FLAG_DIRECT_INDICATOR)
tsp_debug_info(true, &info->client->dev, "%s: direct indicator cmd 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 fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
#ifdef FTS_SUPPORT_SIDE_GESTURE
if (info->board->support_sidegesture)
info->lowpower_mode = info->cmd_param[0];
#endif
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
static void set_deepsleep_mode(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
info->deepsleep_mode = info->cmd_param[0];
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
static void active_sleep_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
/* To do here */
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
static void second_screen_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if(info->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);
#ifdef FTS_SUPPORT_SIDE_GESTURE
if (info->board->support_sidegesture)
info->lowpower_mode = check_lowpower_mode(info);
#endif
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_longpress_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
unsigned char regAdd[4] = {0xB0, 0x07, 0x10, 0x03};
int ret;
int bflag = 0;
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if (info->cmd_param[0])
bflag = 1;
else
bflag = 0;
if (bflag)
regAdd[3] = 0x03;
else
regAdd[3] = 0x02;
ret = fts_write_reg(info, regAdd, 4);
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: on/off:%d, ret: %d\n", __func__, bflag, ret);
fts_delay(1);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_sidescreen_x_length(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[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;
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 0xA0) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
regAdd[3] = info->cmd_param[0]; // Change Side screen x length
ret = fts_write_reg(info, regAdd, 4);
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: x length:%d, ret: %d\n", __func__, regAdd[3], ret);
fts_delay(1);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_dead_zone(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
unsigned char regAdd[2] = {0xC4, 0x00};
int ret;
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 6) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if (info->cmd_param[0]==1)
regAdd[1] = 0x01; /* side edge top */
else if (info->cmd_param[0]==2)
regAdd[1] = 0x02; /* side edge bottom */
else if (info->cmd_param[0]==3)
regAdd[1] = 0x03; /* side edge All On */
else if (info->cmd_param[0]==4)
regAdd[1] = 0x04; /* side edge Left Off */
else if (info->cmd_param[0]==5)
regAdd[1] = 0x05; /* side edge Right Off */
else if (info->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)
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__, info->cmd_param[0], ret);
fts_delay(1);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
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)
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__, info->cmd_param[0], ret);
fts_delay(1);
}
static void set_mainscreen_disable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 2) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if (info->cmd_param[0]==1){
set_mainscreen_disable_cmd(info, 1);
}else{
set_mainscreen_disable_cmd(info, 0);
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#ifdef SMARTCOVER_COVER
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_cont("[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_cont("[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__);
}
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);
}
}
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);
}
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
###################################################### */
void smartcover_cmd(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
u8 i, j, t;
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 6) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
if(info->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(info->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__);
if (info->fast_mshover_enabled)
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
else if (info->mshover_enabled)
fts_command(info, FTS_CMD_MSHOVER_ON);
} else if(info->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(info->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(info->cmd_param[0]==5){ // data write
if(info->cmd_param[1]<0 || info->cmd_param[1]>= 32){
tsp_debug_info(true, &info->client->dev, "%s data tx size is over[%d]\n", \
__func__,info->cmd_param[1]);
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
goto fail;
}
tsp_debug_info(true, &info->client->dev, "%s data %2X, %2X, %2X\n", __func__, \
info->cmd_param[1],info->cmd_param[2],info->cmd_param[3] );
t = info->cmd_param[1];
info->smart_cover[t][0] = (info->cmd_param[2]&0x80)>>7;
info->smart_cover[t][1] = (info->cmd_param[2]&0x40)>>6;
info->smart_cover[t][2] = (info->cmd_param[2]&0x20)>>5;
info->smart_cover[t][3] = (info->cmd_param[2]&0x10)>>4;
info->smart_cover[t][4] = (info->cmd_param[2]&0x08)>>3;
info->smart_cover[t][5] = (info->cmd_param[2]&0x04)>>2;
info->smart_cover[t][6] = (info->cmd_param[2]&0x02)>>1;
info->smart_cover[t][7] = (info->cmd_param[2]&0x01);
info->smart_cover[t][8] = (info->cmd_param[3]&0x80)>>7;
info->smart_cover[t][9] = (info->cmd_param[3]&0x40)>>6;
info->smart_cover[t][10] = (info->cmd_param[3]&0x20)>>5;
info->smart_cover[t][11] = (info->cmd_param[3]&0x10)>>4;
info->smart_cover[t][12] = (info->cmd_param[3]&0x08)>>3;
info->smart_cover[t][13] = (info->cmd_param[3]&0x04)>>2;
info->smart_cover[t][14] = (info->cmd_param[3]&0x02)>>1;
info->smart_cover[t][15] = (info->cmd_param[3]&0x01);
} else if(info->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__, info->cmd_param[0] );
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
goto fail;
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
}
fail:
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
#endif
static void set_rotation_status(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->cmd_param[0] < 0 || info->cmd_param[0] > 3) {
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
} else {
int status = info->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");
info->cmd_state = CMD_STATUS_OK;
}
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#ifdef FTS_SUPPORT_STRINGLIB
static void quick_shot_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned short addr = FTS_CMD_STRING_ACCESS;
int ret;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
if (info->cmd_param[0]) {
info->fts_mode |= FTS_MODE_QUICK_SHOT;
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_QUICK_CAM;
} else {
info->fts_mode &= ~FTS_MODE_QUICK_SHOT;
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_QUICK_CAM);
}
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");
info->cmd_state = CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
out:
info->lowpower_mode = check_lowpower_mode(info);
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void scrub_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned short addr = FTS_CMD_STRING_ACCESS;
int ret;
char buff[CMD_STR_LEN] = { 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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
set_default_result(info);
if (info->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");
info->cmd_state = CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
out:
info->lowpower_mode = check_lowpower_mode(info);
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void quick_app_access_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned short addr = FTS_CMD_STRING_ACCESS;
int ret;
char buff[CMD_STR_LEN] = { 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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
set_default_result(info);
if (info->cmd_param[0]) {
info->fts_mode |= FTS_MODE_QUICK_APP_ACCESS;
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_QUICK_APP_ACCESS;
} else {
info->fts_mode &= ~FTS_MODE_QUICK_APP_ACCESS;
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_QUICK_APP_ACCESS);
}
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");
info->cmd_state = CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
out:
info->lowpower_mode = check_lowpower_mode(info);
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void direct_indicator_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned short addr = FTS_CMD_STRING_ACCESS;
int ret;
char buff[CMD_STR_LEN] = { 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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
set_default_result(info);
if (info->cmd_param[0]) {
info->fts_mode |= FTS_MODE_DIRECT_INDICATOR;
info->lowpower_flag = info->lowpower_flag | FTS_LOWP_FLAG_DIRECT_INDICATOR;
} else {
info->fts_mode &= ~FTS_MODE_DIRECT_INDICATOR;
info->lowpower_flag = info->lowpower_flag & ~(FTS_LOWP_FLAG_DIRECT_INDICATOR);
}
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");
info->cmd_state = CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
out:
info->lowpower_mode = check_lowpower_mode(info);
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void spay_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
unsigned short addr = FTS_CMD_STRING_ACCESS;
int ret;
char buff[CMD_STR_LEN] = { 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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
goto out;
}
set_default_result(info);
if (info->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: failed. ret: %d\n", __func__, ret);
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
out:
info->lowpower_mode = check_lowpower_mode(info);
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
static void delay(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
info->delay_time = info->cmd_param[0];
tsp_debug_info(true, &info->client->dev, "%s: delay time is %d\n", __func__, info->delay_time);
snprintf(buff, sizeof(buff), "%d", info->delay_time);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void debug(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
info->debug_string = info->cmd_param[0];
tsp_debug_info(true, &info->client->dev, "%s: command is %d\n", __func__, info->debug_string);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_autotune_enable(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
info->run_autotune = info->cmd_param[0];
tsp_debug_info(true, &info->client->dev, "%s: command is %s\n",
__func__, info->run_autotune ? "ENABLE" : "DISABLE");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
info->cmd_state = CMD_STATUS_WAITING;
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_autotune(void *device_data)
{
struct fts_ts_info *info = (struct fts_ts_info *)device_data;
char buff[CMD_STR_LEN] = { 0 };
set_default_result(info);
if (info->touch_stopped) {
dev_info(&info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
}
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");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = CMD_STATUS_NOT_APPLICABLE;
return;
}
if (!info->run_autotune){
tsp_debug_info(true, &info->client->dev, "%s: autotune is disabled, %d\n", __func__, info->run_autotune);
goto autotune_fail;
}
#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
disable_irq(info->irq);
if (info->digital_rev == FTS_DIGITAL_REV_2) {
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
}
#endif
fts_command(info, FLUSHBUFFER);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
fts_release_all_key(info);
#endif
fts_execute_autotune(info);
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
fts_fw_wait_for_event(info, STATUS_EVENT_FORCE_CAL_DONE);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
}else {
tsp_debug_info(true, &info->client->dev, "%s: digital_rev not matched, %d\n", __func__, info->digital_rev);
goto autotune_fail;
}
enable_irq(info->irq);
snprintf(buff, sizeof(buff), "%s", "OK");
info->cmd_state = CMD_STATUS_OK;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
autotune_fail:
snprintf(buff, sizeof(buff), "%s", "NG");
info->cmd_state = CMD_STATUS_FAIL;
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
mutex_lock(&info->cmd_lock);
info->cmd_is_running = false;
mutex_unlock(&info->cmd_lock);
tsp_debug_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
}
#ifdef FTS_SUPPORT_TOUCH_KEY
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;
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->board->num_touchkey ; i++)
if (info->board->touchkey[i].keycode == keycode) {
if (info->digital_rev == FTS_DIGITAL_REV_1)
return *(short *)&buf[(info->board->touchkey[i].value - 1) * 2];
else
return *(short *)&buf[(info->board->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 sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_STRENGTH, KEY_RECENT);
return sprintf(buf, "%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 sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_STRENGTH, KEY_BACK);
return sprintf(buf, "%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 sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_RAW, KEY_RECENT);
return sprintf(buf, "%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 sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_RAW, KEY_BACK);
return sprintf(buf, "%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 sprintf(buf, "%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;
}
ret = info->board->led_power(info, (bool)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;
}
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);
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,
NULL,
};
static struct attribute_group sec_touchkey_factory_attr_group = {
.attrs = sec_touchkey_factory_attributes,
};
#endif
#endif