3367 lines
86 KiB
C
3367 lines
86 KiB
C
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
|
/*
|
||
|
|
* Copyright (c) 2019 MediaTek Inc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/*#include "himax_common.h"*/
|
||
|
|
/*#include "himax_ic_core.h"*/
|
||
|
|
#include "himax_inspection.h"
|
||
|
|
#include "himax_modular_table.h"
|
||
|
|
/*rotate*/
|
||
|
|
static void tpd_rotate_180(int *x, int *y)
|
||
|
|
{
|
||
|
|
*x = TPD_RES_X - *x;
|
||
|
|
*y = TPD_RES_Y - *y;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#if defined(__HIMAX_MOD__)
|
||
|
|
int (*hx_msm_drm_register_client)(struct notifier_block *nb);
|
||
|
|
int (*hx_msm_drm_unregister_client)(struct notifier_block *nb);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
#define GEST_SUP_NUM 26
|
||
|
|
/* Setting cust key define (DF = double finger) */
|
||
|
|
/* {Double Tap, Up, Down, Left, Right, C, Z, M,
|
||
|
|
* O, S, V, W, e, m, @, (reserve),
|
||
|
|
* Finger gesture, ^, >, <, f(R), f(L), Up(DF), Down(DF),
|
||
|
|
* Left(DF), Right(DF)}
|
||
|
|
*/
|
||
|
|
uint8_t gest_event[GEST_SUP_NUM] = {
|
||
|
|
0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||
|
|
0x81, 0x1D, 0x2D, 0x3D, 0x1F, 0x2F, 0x51, 0x52,
|
||
|
|
0x53, 0x54};
|
||
|
|
|
||
|
|
/*gest_event mapping to gest_key_def*/
|
||
|
|
uint16_t gest_key_def[GEST_SUP_NUM] = {
|
||
|
|
HX_KEY_DOUBLE_CLICK, HX_KEY_UP, HX_KEY_DOWN, HX_KEY_LEFT,
|
||
|
|
HX_KEY_RIGHT, HX_KEY_C, HX_KEY_Z, HX_KEY_M,
|
||
|
|
HX_KEY_O, HX_KEY_S, HX_KEY_V, HX_KEY_W,
|
||
|
|
HX_KEY_E, HX_KEY_LC_M, HX_KEY_AT, HX_KEY_RESERVE,
|
||
|
|
HX_KEY_FINGER_GEST, HX_KEY_V_DOWN, HX_KEY_V_LEFT, HX_KEY_V_RIGHT,
|
||
|
|
HX_KEY_F_RIGHT, HX_KEY_F_LEFT, HX_KEY_DF_UP, HX_KEY_DF_DOWN,
|
||
|
|
HX_KEY_DF_LEFT, HX_KEY_DF_RIGHT};
|
||
|
|
|
||
|
|
uint8_t *wake_event_buffer;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(HX_USE_KSYM)
|
||
|
|
struct himax_chip_entry himax_ksym_lookup;
|
||
|
|
EXPORT_SYMBOL(himax_ksym_lookup);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F
|
||
|
|
#define TS_WAKE_LOCK_TIMEOUT (5000)
|
||
|
|
#define FRAME_COUNT 5
|
||
|
|
|
||
|
|
#if defined(HX_TP_PROC_GUEST_INFO)
|
||
|
|
struct hx_guest_info *g_guest_info_data;
|
||
|
|
EXPORT_SYMBOL(g_guest_info_data);
|
||
|
|
|
||
|
|
char *g_guest_info_item[] = {
|
||
|
|
"projectID",
|
||
|
|
"CGColor",
|
||
|
|
"BarCode",
|
||
|
|
"Reserve1",
|
||
|
|
"Reserve2",
|
||
|
|
"Reserve3",
|
||
|
|
"Reserve4",
|
||
|
|
"Reserve5",
|
||
|
|
"VCOM",
|
||
|
|
"Vcom-3Gar",
|
||
|
|
NULL
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
uint32_t g_hx_chip_inited;
|
||
|
|
|
||
|
|
#if defined(__EMBEDDED_FW__)
|
||
|
|
struct firmware g_embedded_fw = {
|
||
|
|
.data = _binary___Himax_firmware_bin_start,
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
bool g_boot_upgrade_flag;
|
||
|
|
const struct firmware *hxfw;
|
||
|
|
int g_i_FW_VER;
|
||
|
|
int g_i_CFG_VER;
|
||
|
|
int g_i_CID_MAJ; /*GUEST ID*/
|
||
|
|
int g_i_CID_MIN; /*VER for GUEST*/
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
int g_f_0f_updat;
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
struct himax_ts_data *private_ts;
|
||
|
|
EXPORT_SYMBOL(private_ts);
|
||
|
|
|
||
|
|
struct himax_ic_data *ic_data;
|
||
|
|
EXPORT_SYMBOL(ic_data);
|
||
|
|
|
||
|
|
struct himax_report_data *hx_touch_data;
|
||
|
|
EXPORT_SYMBOL(hx_touch_data);
|
||
|
|
|
||
|
|
struct himax_core_fp g_core_fp;
|
||
|
|
EXPORT_SYMBOL(g_core_fp);
|
||
|
|
|
||
|
|
struct himax_debug *debug_data;
|
||
|
|
EXPORT_SYMBOL(debug_data);
|
||
|
|
|
||
|
|
struct proc_dir_entry *himax_touch_proc_dir;
|
||
|
|
EXPORT_SYMBOL(himax_touch_proc_dir);
|
||
|
|
|
||
|
|
int g_mmi_refcnt;
|
||
|
|
EXPORT_SYMBOL(g_mmi_refcnt);
|
||
|
|
|
||
|
|
#define HIMAX_PROC_TOUCH_FOLDER "android_touch"
|
||
|
|
/*ts_work about start*/
|
||
|
|
struct himax_target_report_data *g_target_report_data;
|
||
|
|
EXPORT_SYMBOL(g_target_report_data);
|
||
|
|
|
||
|
|
static void himax_report_all_leave_event(struct himax_ts_data *ts);
|
||
|
|
/*ts_work about end*/
|
||
|
|
|
||
|
|
struct filename* (*kp_getname_kernel)(const char *filename);
|
||
|
|
struct file* (*kp_file_open_name)(struct filename *name,
|
||
|
|
int flags, umode_t mode);
|
||
|
|
|
||
|
|
unsigned long FW_VER_MAJ_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(FW_VER_MAJ_FLASH_ADDR);
|
||
|
|
|
||
|
|
unsigned long FW_VER_MIN_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(FW_VER_MIN_FLASH_ADDR);
|
||
|
|
|
||
|
|
unsigned long CFG_VER_MAJ_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(CFG_VER_MAJ_FLASH_ADDR);
|
||
|
|
|
||
|
|
unsigned long CFG_VER_MIN_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(CFG_VER_MIN_FLASH_ADDR);
|
||
|
|
|
||
|
|
unsigned long CID_VER_MAJ_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(CID_VER_MAJ_FLASH_ADDR);
|
||
|
|
|
||
|
|
unsigned long CID_VER_MIN_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(CID_VER_MIN_FLASH_ADDR);
|
||
|
|
/*unsigned long PANEL_VERSION_ADDR;*/
|
||
|
|
uint32_t CFG_TABLE_FLASH_ADDR;
|
||
|
|
EXPORT_SYMBOL(CFG_TABLE_FLASH_ADDR);
|
||
|
|
|
||
|
|
unsigned char IC_CHECKSUM;
|
||
|
|
EXPORT_SYMBOL(IC_CHECKSUM);
|
||
|
|
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
u8 HX_EXCP_RESET_ACTIVATE;
|
||
|
|
EXPORT_SYMBOL(HX_EXCP_RESET_ACTIVATE);
|
||
|
|
|
||
|
|
int hx_EB_event_flag;
|
||
|
|
EXPORT_SYMBOL(hx_EB_event_flag);
|
||
|
|
|
||
|
|
int hx_EC_event_flag;
|
||
|
|
EXPORT_SYMBOL(hx_EC_event_flag);
|
||
|
|
|
||
|
|
int hx_EE_event_flag;
|
||
|
|
EXPORT_SYMBOL(hx_EE_event_flag);
|
||
|
|
|
||
|
|
int g_zero_event_count;
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static bool chip_test_r_flag;
|
||
|
|
u8 HX_HW_RESET_ACTIVATE;
|
||
|
|
|
||
|
|
static uint8_t AA_press;
|
||
|
|
static uint8_t EN_NoiseFilter;
|
||
|
|
static uint8_t Last_EN_NoiseFilter;
|
||
|
|
|
||
|
|
static int p_point_num = 0xFFFF;
|
||
|
|
static int probe_fail_flag;
|
||
|
|
#if defined(HX_USB_DETECT_GLOBAL)
|
||
|
|
bool USB_detect_flag;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_GESTURE_TRACK)
|
||
|
|
static int gest_pt_cnt;
|
||
|
|
static int gest_pt_x[GEST_PT_MAX_NUM];
|
||
|
|
static int gest_pt_y[GEST_PT_MAX_NUM];
|
||
|
|
static int gest_start_x, gest_start_y, gest_end_x, gest_end_y;
|
||
|
|
static int gest_width, gest_height, gest_mid_x, gest_mid_y;
|
||
|
|
static int hx_gesture_coor[16];
|
||
|
|
#endif
|
||
|
|
|
||
|
|
int g_ts_dbg;
|
||
|
|
EXPORT_SYMBOL(g_ts_dbg);
|
||
|
|
|
||
|
|
/* File node for Selftest, SMWP and HSEN - Start*/
|
||
|
|
#define HIMAX_PROC_SELF_TEST_FILE "self_test"
|
||
|
|
struct proc_dir_entry *himax_proc_self_test_file;
|
||
|
|
|
||
|
|
uint8_t HX_PROC_SEND_FLAG;
|
||
|
|
EXPORT_SYMBOL(HX_PROC_SEND_FLAG);
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
#define HIMAX_PROC_SMWP_FILE "SMWP"
|
||
|
|
struct proc_dir_entry *himax_proc_SMWP_file;
|
||
|
|
#define HIMAX_PROC_GESTURE_FILE "GESTURE"
|
||
|
|
struct proc_dir_entry *himax_proc_GESTURE_file;
|
||
|
|
uint8_t HX_SMWP_EN;
|
||
|
|
#if defined(HX_ULTRA_LOW_POWER)
|
||
|
|
#define HIMAX_PROC_PSENSOR_FILE "Psensor"
|
||
|
|
struct proc_dir_entry *himax_proc_psensor_file;
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_HIGH_SENSE)
|
||
|
|
#define HIMAX_PROC_HSEN_FILE "HSEN"
|
||
|
|
struct proc_dir_entry *himax_proc_HSEN_file;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define HIMAX_PROC_VENDOR_FILE "vendor"
|
||
|
|
struct proc_dir_entry *himax_proc_vendor_file;
|
||
|
|
|
||
|
|
#if defined(HX_PALM_REPORT)
|
||
|
|
static int himax_palm_detect(uint8_t *buf)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
int32_t loop_i;
|
||
|
|
int base = 0;
|
||
|
|
int x = 0, y = 0, w = 0;
|
||
|
|
|
||
|
|
loop_i = 0;
|
||
|
|
base = loop_i * 4;
|
||
|
|
x = buf[base] << 8 | buf[base + 1];
|
||
|
|
y = (buf[base + 2] << 8 | buf[base + 3]);
|
||
|
|
w = buf[(ts->nFinger_support * 4) + loop_i];
|
||
|
|
I(" %s HX_PALM_REPORT_loopi=%d,base=%x,X=%x,Y=%x,W=%x\n",
|
||
|
|
__func__, loop_i, base, x, y, w);
|
||
|
|
if ((!atomic_read(&ts->suspend_mode))
|
||
|
|
&& (x == 0xFA5A)
|
||
|
|
&& (y == 0xFA5A)
|
||
|
|
&& (w == 0x00))
|
||
|
|
return PALM_REPORT;
|
||
|
|
else
|
||
|
|
return NOT_REPORT;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static ssize_t himax_self_test(struct seq_file *s, void *v)
|
||
|
|
{
|
||
|
|
int val = 0x00;
|
||
|
|
size_t ret = 0;
|
||
|
|
|
||
|
|
I("%s: enter, %d\n", __func__, __LINE__);
|
||
|
|
|
||
|
|
if (private_ts->suspended == 1) {
|
||
|
|
E("%s: please do self test in normal active mode\n", __func__);
|
||
|
|
return HX_INIT_FAIL;
|
||
|
|
}
|
||
|
|
|
||
|
|
himax_int_enable(0);/* disable irq */
|
||
|
|
|
||
|
|
private_ts->in_self_test = 1;
|
||
|
|
|
||
|
|
val = g_core_fp.fp_chip_self_test(s, v);
|
||
|
|
/*
|
||
|
|
*#if defined(HX_EXCP_RECOVERY)
|
||
|
|
* HX_EXCP_RESET_ACTIVATE = 1;
|
||
|
|
*#endif
|
||
|
|
* himax_int_enable(1); //enable irq
|
||
|
|
*/
|
||
|
|
|
||
|
|
private_ts->in_self_test = 0;
|
||
|
|
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
HX_EXCP_RESET_ACTIVATE = 1;
|
||
|
|
#endif
|
||
|
|
himax_int_enable(1);
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void *himax_self_test_seq_start(struct seq_file *s, loff_t *pos)
|
||
|
|
{
|
||
|
|
if (*pos >= 1)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
|
||
|
|
return (void *)((unsigned long) *pos + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void *himax_self_test_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||
|
|
{
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void himax_self_test_seq_stop(struct seq_file *s, void *v)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
static int himax_self_test_seq_read(struct seq_file *s, void *v)
|
||
|
|
{
|
||
|
|
size_t ret = 0;
|
||
|
|
|
||
|
|
if (chip_test_r_flag) {
|
||
|
|
#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT)
|
||
|
|
if (g_rslt_data)
|
||
|
|
seq_printf(s, "%s", g_rslt_data);
|
||
|
|
else
|
||
|
|
#endif
|
||
|
|
seq_puts(s, "No chip test data.\n");
|
||
|
|
} else {
|
||
|
|
himax_self_test(s, v);
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct seq_operations himax_self_test_seq_ops = {
|
||
|
|
.start = himax_self_test_seq_start,
|
||
|
|
.next = himax_self_test_seq_next,
|
||
|
|
.stop = himax_self_test_seq_stop,
|
||
|
|
.show = himax_self_test_seq_read,
|
||
|
|
};
|
||
|
|
|
||
|
|
static int himax_self_test_proc_open(struct inode *inode, struct file *file)
|
||
|
|
{
|
||
|
|
return seq_open(file, &himax_self_test_seq_ops);
|
||
|
|
};
|
||
|
|
|
||
|
|
static ssize_t himax_self_test_write(struct file *filp, const char __user *buff,
|
||
|
|
size_t len, loff_t *data)
|
||
|
|
{
|
||
|
|
char buf[80];
|
||
|
|
|
||
|
|
if (len >= 80) {
|
||
|
|
I("%s: no command exceeds 80 chars.\n", __func__);
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (copy_from_user(buf, buff, len))
|
||
|
|
return -EFAULT;
|
||
|
|
|
||
|
|
if (buf[0] == 'r') {
|
||
|
|
chip_test_r_flag = true;
|
||
|
|
I("%s: Start to read chip test data.\n", __func__);
|
||
|
|
} else {
|
||
|
|
chip_test_r_flag = false;
|
||
|
|
I("%s: Back to do self test.\n", __func__);
|
||
|
|
}
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct file_operations himax_proc_self_test_ops = {
|
||
|
|
.owner = THIS_MODULE,
|
||
|
|
.open = himax_self_test_proc_open,
|
||
|
|
.read = seq_read,
|
||
|
|
.write = himax_self_test_write,
|
||
|
|
.release = seq_release,
|
||
|
|
};
|
||
|
|
|
||
|
|
#if defined(HX_HIGH_SENSE)
|
||
|
|
static ssize_t himax_HSEN_read(struct file *file, char *buf,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
size_t count = 0;
|
||
|
|
char *temp_buf = NULL;
|
||
|
|
|
||
|
|
if (!HX_PROC_SEND_FLAG) {
|
||
|
|
temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL);
|
||
|
|
if (temp_buf != NULL) {
|
||
|
|
count = snprintf(temp_buf, PAGE_SIZE, "%d\n",
|
||
|
|
ts->HSEN_enable);
|
||
|
|
|
||
|
|
if (copy_to_user(buf, temp_buf, len))
|
||
|
|
I("%s, here:%d\n", __func__, __LINE__);
|
||
|
|
|
||
|
|
kfree(temp_buf);
|
||
|
|
HX_PROC_SEND_FLAG = 1;
|
||
|
|
} else {
|
||
|
|
E("%s, Failed to allocate memory\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
HX_PROC_SEND_FLAG = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
static ssize_t himax_HSEN_write(struct file *file, const char *buff,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
char buf[80] = {0};
|
||
|
|
|
||
|
|
if (len >= 80) {
|
||
|
|
I("%s: no command exceeds 80 chars.\n", __func__);
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (copy_from_user(buf, buff, len))
|
||
|
|
return -EFAULT;
|
||
|
|
|
||
|
|
if (buf[0] == '0')
|
||
|
|
ts->HSEN_enable = 0;
|
||
|
|
else if (buf[0] == '1')
|
||
|
|
ts->HSEN_enable = 1;
|
||
|
|
else
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, ts->suspended);
|
||
|
|
I("%s: HSEN_enable = %d.\n", __func__, ts->HSEN_enable);
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct file_operations himax_proc_HSEN_ops = {
|
||
|
|
.owner = THIS_MODULE,
|
||
|
|
.read = himax_HSEN_read,
|
||
|
|
.write = himax_HSEN_write,
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
static ssize_t himax_SMWP_read(struct file *file, char *buf,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
size_t count = 0;
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
char *temp_buf = NULL;
|
||
|
|
|
||
|
|
if (!HX_PROC_SEND_FLAG) {
|
||
|
|
temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL);
|
||
|
|
if (temp_buf != NULL) {
|
||
|
|
count = snprintf(temp_buf, PAGE_SIZE, "%d\n",
|
||
|
|
ts->SMWP_enable);
|
||
|
|
|
||
|
|
if (copy_to_user(buf, temp_buf, len))
|
||
|
|
I("%s, here:%d\n", __func__, __LINE__);
|
||
|
|
|
||
|
|
kfree(temp_buf);
|
||
|
|
HX_PROC_SEND_FLAG = 1;
|
||
|
|
} else {
|
||
|
|
E("%s, Failed to allocate memory\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
HX_PROC_SEND_FLAG = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
static ssize_t himax_SMWP_write(struct file *file, const char *buff,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
char buf[80] = {0};
|
||
|
|
|
||
|
|
if (len >= 80) {
|
||
|
|
I("%s: no command exceeds 80 chars.\n", __func__);
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (copy_from_user(buf, buff, len))
|
||
|
|
return -EFAULT;
|
||
|
|
|
||
|
|
if (buf[0] == '0')
|
||
|
|
ts->SMWP_enable = 0;
|
||
|
|
else if (buf[0] == '1')
|
||
|
|
ts->SMWP_enable = 1;
|
||
|
|
else
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, ts->suspended);
|
||
|
|
HX_SMWP_EN = ts->SMWP_enable;
|
||
|
|
I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN);
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct file_operations himax_proc_SMWP_ops = {
|
||
|
|
.owner = THIS_MODULE,
|
||
|
|
.read = himax_SMWP_read,
|
||
|
|
.write = himax_SMWP_write,
|
||
|
|
};
|
||
|
|
|
||
|
|
static ssize_t himax_GESTURE_read(struct file *file, char *buf,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
int i = 0;
|
||
|
|
size_t ret = 0;
|
||
|
|
char *temp_buf = NULL;
|
||
|
|
|
||
|
|
if (!HX_PROC_SEND_FLAG) {
|
||
|
|
temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL);
|
||
|
|
if (temp_buf != NULL) {
|
||
|
|
for (i = 0; i < GEST_SUP_NUM; i++)
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"ges_en[%d]=%d\n",
|
||
|
|
i, ts->gesture_cust_en[i]);
|
||
|
|
|
||
|
|
if (copy_to_user(buf, temp_buf, len))
|
||
|
|
I("%s, here:%d\n", __func__, __LINE__);
|
||
|
|
|
||
|
|
kfree(temp_buf);
|
||
|
|
HX_PROC_SEND_FLAG = 1;
|
||
|
|
} else {
|
||
|
|
E("%s, Failed to allocate memory\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
HX_PROC_SEND_FLAG = 0;
|
||
|
|
ret = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static ssize_t himax_GESTURE_write(struct file *file, const char *buff,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
int i = 0;
|
||
|
|
int j = 0;
|
||
|
|
char buf[80] = {0};
|
||
|
|
|
||
|
|
if (len >= 80) {
|
||
|
|
I("%s: no command exceeds 80 chars.\n", __func__);
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (copy_from_user(buf, buff, len))
|
||
|
|
return -EFAULT;
|
||
|
|
|
||
|
|
I("himax_GESTURE_store= %s, len = %d\n", buf, (int)len);
|
||
|
|
|
||
|
|
for (i = 0; i < len; i++) {
|
||
|
|
if (buf[i] == '0' && j < GEST_SUP_NUM) {
|
||
|
|
ts->gesture_cust_en[j] = 0;
|
||
|
|
I("gesture en[%d]=%d\n", j, ts->gesture_cust_en[j]);
|
||
|
|
j++;
|
||
|
|
} else if (buf[i] == '1' && j < GEST_SUP_NUM) {
|
||
|
|
ts->gesture_cust_en[j] = 1;
|
||
|
|
I("gesture en[%d]=%d\n", j, ts->gesture_cust_en[j]);
|
||
|
|
j++;
|
||
|
|
} else
|
||
|
|
I("Not 0/1 or >=GEST_SUP_NUM : buf[%d] = %c\n",
|
||
|
|
i, buf[i]);
|
||
|
|
}
|
||
|
|
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct file_operations himax_proc_Gesture_ops = {
|
||
|
|
.owner = THIS_MODULE,
|
||
|
|
.read = himax_GESTURE_read,
|
||
|
|
.write = himax_GESTURE_write,
|
||
|
|
};
|
||
|
|
|
||
|
|
#if defined(HX_ULTRA_LOW_POWER)
|
||
|
|
static ssize_t himax_psensor_read(struct file *file, char *buf,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
size_t count = 0;
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
char *temp_buf = NULL;
|
||
|
|
|
||
|
|
if (!HX_PROC_SEND_FLAG) {
|
||
|
|
temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL);
|
||
|
|
if (temp_buf != NULL) {
|
||
|
|
count = snprintf(temp_buf, PAGE_SIZE,
|
||
|
|
"p-sensor flag = %d\n",
|
||
|
|
ts->psensor_flag);
|
||
|
|
|
||
|
|
if (copy_to_user(buf, temp_buf, len))
|
||
|
|
I("%s, here:%d\n", __func__, __LINE__);
|
||
|
|
|
||
|
|
kfree(temp_buf);
|
||
|
|
HX_PROC_SEND_FLAG = 1;
|
||
|
|
} else {
|
||
|
|
E("%s, Failed to allocate memory\n", __func__);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
HX_PROC_SEND_FLAG = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
static ssize_t himax_psensor_write(struct file *file, const char *buff,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
char buf[80] = {0};
|
||
|
|
|
||
|
|
if (len >= 80) {
|
||
|
|
I("%s: no command exceeds 80 chars.\n", __func__);
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (copy_from_user(buf, buff, len))
|
||
|
|
return -EFAULT;
|
||
|
|
|
||
|
|
if (buf[0] == '0' && ts->SMWP_enable == 1) {
|
||
|
|
ts->psensor_flag = false;
|
||
|
|
g_core_fp.fp_black_gest_ctrl(false);
|
||
|
|
} else if (buf[0] == '1' && ts->SMWP_enable == 1) {
|
||
|
|
ts->psensor_flag = true;
|
||
|
|
g_core_fp.fp_black_gest_ctrl(true);
|
||
|
|
} else if (ts->SMWP_enable == 0) {
|
||
|
|
I("%s: SMWP is disable, not supprot to ctrl p-sensor.\n",
|
||
|
|
__func__);
|
||
|
|
} else
|
||
|
|
return -EINVAL;
|
||
|
|
|
||
|
|
I("%s: psensor_flag = %d.\n", __func__, ts->psensor_flag);
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
static const struct file_operations himax_proc_psensor_ops = {
|
||
|
|
.owner = THIS_MODULE,
|
||
|
|
.read = himax_psensor_read,
|
||
|
|
.write = himax_psensor_write,
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static ssize_t himax_vendor_read(struct file *file, char *buf,
|
||
|
|
size_t len, loff_t *pos)
|
||
|
|
{
|
||
|
|
ssize_t ret = 0;
|
||
|
|
char *temp_buf = NULL;
|
||
|
|
|
||
|
|
if (!HX_PROC_SEND_FLAG) {
|
||
|
|
temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL);
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"IC = %s\n", private_ts->chip_name);
|
||
|
|
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver);
|
||
|
|
|
||
|
|
if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"CONFIG_VER = 0x%2.2X\n",
|
||
|
|
ic_data->vendor_config_ver);
|
||
|
|
} else {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"TOUCH_VER = 0x%2.2X\n",
|
||
|
|
ic_data->vendor_touch_cfg_ver);
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"DISPLAY_VER = 0x%2.2X\n",
|
||
|
|
ic_data->vendor_display_cfg_ver);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ic_data->vendor_cid_maj_ver < 0
|
||
|
|
&& ic_data->vendor_cid_min_ver < 0) {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"CID_VER = NULL\n");
|
||
|
|
} else {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"CID_VER = 0x%2.2X\n",
|
||
|
|
(ic_data->vendor_cid_maj_ver << 8 |
|
||
|
|
ic_data->vendor_cid_min_ver));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ic_data->vendor_panel_ver < 0) {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"PANEL_VER = NULL\n");
|
||
|
|
} else {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"PANEL_VER = 0x%2.2X\n",
|
||
|
|
ic_data->vendor_panel_ver);
|
||
|
|
}
|
||
|
|
if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) {
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"Cusomer = %s\n",
|
||
|
|
ic_data->vendor_cus_info);
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"Project = %s\n",
|
||
|
|
ic_data->vendor_proj_info);
|
||
|
|
}
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret, "\n");
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret,
|
||
|
|
"Himax Touch Driver Version:\n");
|
||
|
|
ret += snprintf(temp_buf + ret, len - ret, "%s\n",
|
||
|
|
HIMAX_DRIVER_VER);
|
||
|
|
|
||
|
|
if (copy_to_user(buf, temp_buf, len))
|
||
|
|
I("%s,here:%d\n", __func__, __LINE__);
|
||
|
|
|
||
|
|
kfree(temp_buf);
|
||
|
|
HX_PROC_SEND_FLAG = 1;
|
||
|
|
} else {
|
||
|
|
HX_PROC_SEND_FLAG = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
static const struct file_operations himax_proc_vendor_ops = {
|
||
|
|
.owner = THIS_MODULE,
|
||
|
|
.read = himax_vendor_read,
|
||
|
|
};
|
||
|
|
|
||
|
|
int himax_common_proc_init(void)
|
||
|
|
{
|
||
|
|
himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL);
|
||
|
|
|
||
|
|
if (himax_touch_proc_dir == NULL) {
|
||
|
|
E(" %s: himax_touch_proc_dir file create failed!\n", __func__);
|
||
|
|
return -ENOMEM;
|
||
|
|
}
|
||
|
|
#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT)
|
||
|
|
if (fp_himax_self_test_init != NULL)
|
||
|
|
fp_himax_self_test_init();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, 0444,
|
||
|
|
himax_touch_proc_dir, &himax_proc_self_test_ops);
|
||
|
|
if (himax_proc_self_test_file == NULL) {
|
||
|
|
E(" %s: proc self_test file create failed!\n", __func__);
|
||
|
|
goto fail_1;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_HIGH_SENSE)
|
||
|
|
himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, 0666,
|
||
|
|
himax_touch_proc_dir, &himax_proc_HSEN_ops);
|
||
|
|
|
||
|
|
if (himax_proc_HSEN_file == NULL) {
|
||
|
|
E(" %s: proc HSEN file create failed!\n", __func__);
|
||
|
|
goto fail_2;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, 0666,
|
||
|
|
himax_touch_proc_dir, &himax_proc_SMWP_ops);
|
||
|
|
|
||
|
|
if (himax_proc_SMWP_file == NULL) {
|
||
|
|
E(" %s: proc SMWP file create failed!\n", __func__);
|
||
|
|
goto fail_3;
|
||
|
|
}
|
||
|
|
|
||
|
|
himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, 0666,
|
||
|
|
himax_touch_proc_dir, &himax_proc_Gesture_ops);
|
||
|
|
|
||
|
|
if (himax_proc_GESTURE_file == NULL) {
|
||
|
|
E(" %s: proc GESTURE file create failed!\n", __func__);
|
||
|
|
goto fail_4;
|
||
|
|
}
|
||
|
|
#if defined(HX_ULTRA_LOW_POWER)
|
||
|
|
himax_proc_psensor_file = proc_create(HIMAX_PROC_PSENSOR_FILE, 0666,
|
||
|
|
himax_touch_proc_dir, &himax_proc_psensor_ops);
|
||
|
|
|
||
|
|
if (himax_proc_psensor_file == NULL) {
|
||
|
|
E(" %s: proc GESTURE file create failed!\n", __func__);
|
||
|
|
goto fail_5;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, 0444,
|
||
|
|
himax_touch_proc_dir, &himax_proc_vendor_ops);
|
||
|
|
if (himax_proc_vendor_file == NULL) {
|
||
|
|
E(" %s: proc vendor file create failed!\n", __func__);
|
||
|
|
goto fail_6;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
|
||
|
|
fail_6:
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
#if defined(HX_ULTRA_LOW_POWER)
|
||
|
|
remove_proc_entry(HIMAX_PROC_PSENSOR_FILE, himax_touch_proc_dir);
|
||
|
|
fail_5:
|
||
|
|
#endif
|
||
|
|
remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
|
||
|
|
fail_4:
|
||
|
|
remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
|
||
|
|
fail_3:
|
||
|
|
#endif
|
||
|
|
#if defined(HX_HIGH_SENSE)
|
||
|
|
remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
|
||
|
|
fail_2:
|
||
|
|
#endif
|
||
|
|
remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
|
||
|
|
fail_1:
|
||
|
|
return -ENOMEM;
|
||
|
|
}
|
||
|
|
|
||
|
|
void himax_common_proc_deinit(void)
|
||
|
|
{
|
||
|
|
remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
#if defined(HX_ULTRA_LOW_POWER)
|
||
|
|
remove_proc_entry(HIMAX_PROC_PSENSOR_FILE, himax_touch_proc_dir);
|
||
|
|
#endif
|
||
|
|
remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
|
||
|
|
remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
|
||
|
|
#endif
|
||
|
|
#if defined(HX_HIGH_SENSE)
|
||
|
|
remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
|
||
|
|
#endif
|
||
|
|
remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
|
||
|
|
|
||
|
|
remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* File node for SMWP and HSEN - End*/
|
||
|
|
|
||
|
|
void himax_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len)
|
||
|
|
{
|
||
|
|
/*I("%s: Entering!\n", __func__);*/
|
||
|
|
|
||
|
|
switch (len) {
|
||
|
|
case 1:
|
||
|
|
cmd[0] = addr;
|
||
|
|
/*I("%s: cmd[0] = 0x%02X\n", __func__, cmd[0]);*/
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 2:
|
||
|
|
cmd[0] = addr % 0x100;
|
||
|
|
cmd[1] = (addr >> 8) % 0x100;
|
||
|
|
/*I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X\n",*/
|
||
|
|
/* __func__, cmd[0], cmd[1]);*/
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 4:
|
||
|
|
cmd[0] = addr % 0x100;
|
||
|
|
cmd[1] = (addr >> 8) % 0x100;
|
||
|
|
cmd[2] = (addr >> 16) % 0x100;
|
||
|
|
cmd[3] = addr / 0x1000000;
|
||
|
|
/* I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X,*/
|
||
|
|
/*cmd[2] = 0x%02X,cmd[3] = 0x%02X\n", */
|
||
|
|
/* __func__, cmd[0], cmd[1], cmd[2], cmd[3]);*/
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
E("%s: input length fault,len = %d!\n", __func__, len);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
EXPORT_SYMBOL(himax_parse_assign_cmd);
|
||
|
|
|
||
|
|
int himax_input_register(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
int i = 0;
|
||
|
|
#endif
|
||
|
|
ret = himax_dev_set(ts);
|
||
|
|
|
||
|
|
if (ret < 0) {
|
||
|
|
I("%s, input device register fail!\n", __func__);
|
||
|
|
ret = INPUT_REGISTER_FAIL;
|
||
|
|
goto input_device_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
set_bit(EV_SYN, ts->input_dev->evbit);
|
||
|
|
set_bit(EV_ABS, ts->input_dev->evbit);
|
||
|
|
set_bit(EV_KEY, ts->input_dev->evbit);
|
||
|
|
set_bit(KEY_BACK, ts->input_dev->keybit);
|
||
|
|
set_bit(KEY_HOME, ts->input_dev->keybit);
|
||
|
|
set_bit(KEY_MENU, ts->input_dev->keybit);
|
||
|
|
set_bit(KEY_SEARCH, ts->input_dev->keybit);
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
for (i = 0; i < GEST_SUP_NUM; i++)
|
||
|
|
set_bit(gest_key_def[i], ts->input_dev->keybit);
|
||
|
|
#elif defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) || defined(HX_PALM_REPORT)
|
||
|
|
set_bit(KEY_POWER, ts->input_dev->keybit);
|
||
|
|
#endif
|
||
|
|
set_bit(BTN_TOUCH, ts->input_dev->keybit);
|
||
|
|
set_bit(KEY_APPSELECT, ts->input_dev->keybit);
|
||
|
|
set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
|
||
|
|
#if defined(HX_PROTOCOL_A)
|
||
|
|
/*ts->input_dev->mtsize = ts->nFinger_support;*/
|
||
|
|
input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 1, 10, 0, 0);
|
||
|
|
#else
|
||
|
|
set_bit(MT_TOOL_FINGER, ts->input_dev->keybit);
|
||
|
|
#if defined(HX_PROTOCOL_B_3PA)
|
||
|
|
input_mt_init_slots(ts->input_dev, ts->nFinger_support,
|
||
|
|
INPUT_MT_DIRECT);
|
||
|
|
#else
|
||
|
|
input_mt_init_slots(ts->input_dev, ts->nFinger_support);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n",
|
||
|
|
ts->pdata->abs_x_min,
|
||
|
|
ts->pdata->abs_x_max,
|
||
|
|
ts->pdata->abs_y_min,
|
||
|
|
ts->pdata->abs_y_max);
|
||
|
|
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
|
||
|
|
ts->pdata->abs_x_min, ts->pdata->abs_x_max,
|
||
|
|
ts->pdata->abs_x_fuzz, 0);
|
||
|
|
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
|
||
|
|
ts->pdata->abs_y_min, ts->pdata->abs_y_max,
|
||
|
|
ts->pdata->abs_y_fuzz, 0);
|
||
|
|
input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
|
||
|
|
ts->pdata->abs_pressure_min,
|
||
|
|
ts->pdata->abs_pressure_max,
|
||
|
|
ts->pdata->abs_pressure_fuzz, 0);
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,
|
||
|
|
ts->pdata->abs_pressure_min,
|
||
|
|
ts->pdata->abs_pressure_max,
|
||
|
|
ts->pdata->abs_pressure_fuzz, 0);
|
||
|
|
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
|
||
|
|
ts->pdata->abs_width_min,
|
||
|
|
ts->pdata->abs_width_max,
|
||
|
|
ts->pdata->abs_pressure_fuzz, 0);
|
||
|
|
#endif
|
||
|
|
/* input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0,*/
|
||
|
|
/* ((ts->pdata->abs_pressure_max << 16)*/
|
||
|
|
/* | ts->pdata->abs_width_max),*/
|
||
|
|
/* 0, 0);*/
|
||
|
|
/* input_set_abs_params(ts->input_dev, ABS_MT_POSITION,*/
|
||
|
|
/* 0, (BIT(31)*/
|
||
|
|
/* | (ts->pdata->abs_x_max << 16)*/
|
||
|
|
/* | ts->pdata->abs_y_max),*/
|
||
|
|
/* 0, 0);*/
|
||
|
|
|
||
|
|
if (himax_input_register_device(ts->input_dev) == 0) {
|
||
|
|
ret = NO_ERR;
|
||
|
|
} else {
|
||
|
|
E("%s: input register fail\n", __func__);
|
||
|
|
ret = INPUT_REGISTER_FAIL;
|
||
|
|
goto input_device_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!ic_data->HX_PEN_FUNC)
|
||
|
|
goto skip_pen_operation;
|
||
|
|
|
||
|
|
set_bit(EV_SYN, ts->hx_pen_dev->evbit);
|
||
|
|
set_bit(EV_ABS, ts->hx_pen_dev->evbit);
|
||
|
|
set_bit(EV_KEY, ts->hx_pen_dev->evbit);
|
||
|
|
set_bit(BTN_TOUCH, ts->hx_pen_dev->keybit);
|
||
|
|
set_bit(INPUT_PROP_DIRECT, ts->hx_pen_dev->propbit);
|
||
|
|
|
||
|
|
set_bit(BTN_TOOL_PEN, ts->hx_pen_dev->keybit);
|
||
|
|
set_bit(BTN_TOOL_RUBBER, ts->hx_pen_dev->keybit);
|
||
|
|
|
||
|
|
input_set_abs_params(ts->hx_pen_dev, ABS_PRESSURE, 0, 4095, 0, 0);
|
||
|
|
input_set_abs_params(ts->hx_pen_dev, ABS_DISTANCE, 0, 1, 0, 0);
|
||
|
|
input_set_abs_params(ts->hx_pen_dev, ABS_TILT_X, -60, 60, 0, 0);
|
||
|
|
input_set_abs_params(ts->hx_pen_dev, ABS_TILT_Y, -60, 60, 0, 0);
|
||
|
|
/*input_set_capability(ts->hx_pen_dev, EV_SW, SW_PEN_INSERT);*/
|
||
|
|
input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_TOUCH);
|
||
|
|
input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_STYLUS);
|
||
|
|
input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_STYLUS2);
|
||
|
|
|
||
|
|
input_set_abs_params(ts->hx_pen_dev, ABS_X, ts->pdata->abs_x_min,
|
||
|
|
ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0);
|
||
|
|
input_set_abs_params(ts->hx_pen_dev, ABS_Y, ts->pdata->abs_y_min,
|
||
|
|
ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0);
|
||
|
|
|
||
|
|
if (himax_input_register_device(ts->hx_pen_dev) == 0) {
|
||
|
|
ret = NO_ERR;
|
||
|
|
} else {
|
||
|
|
E("%s: input register pen fail\n", __func__);
|
||
|
|
ret = INPUT_REGISTER_FAIL;
|
||
|
|
goto input_device_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
skip_pen_operation:
|
||
|
|
|
||
|
|
I("%s, input device registered.\n", __func__);
|
||
|
|
|
||
|
|
input_device_fail:
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
EXPORT_SYMBOL(himax_input_register);
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
static int himax_auto_update_check(void)
|
||
|
|
{
|
||
|
|
int32_t ret;
|
||
|
|
|
||
|
|
I("%s: Entering!\n", __func__);
|
||
|
|
if (g_core_fp.fp_fw_ver_bin() == 0) {
|
||
|
|
if (((ic_data->vendor_fw_ver < g_i_FW_VER)
|
||
|
|
|| (ic_data->vendor_config_ver < g_i_CFG_VER))) {
|
||
|
|
I("%s: Need update\n", __func__);
|
||
|
|
ret = 0;
|
||
|
|
} else {
|
||
|
|
I("%s: Need not update!\n", __func__);
|
||
|
|
ret = 1;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
E("%s: FW bin fail!\n", __func__);
|
||
|
|
ret = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int i_get_FW(void)
|
||
|
|
{
|
||
|
|
int ret = -1;
|
||
|
|
int result = NO_ERR;
|
||
|
|
|
||
|
|
I("%s: file name = %s\n", __func__, BOOT_UPGRADE_FWNAME);
|
||
|
|
ret = request_firmware(&hxfw, BOOT_UPGRADE_FWNAME, private_ts->dev);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if defined(__EMBEDDED_FW__)
|
||
|
|
hxfw = &g_embedded_fw;
|
||
|
|
I("%s: Not find FW in userspace, use embedded FW(size:%zu)",
|
||
|
|
__func__, g_embedded_fw.size);
|
||
|
|
result = HX_EMBEDDED_FW;
|
||
|
|
#else
|
||
|
|
E("%s,%d: error code = %d\n", __func__, __LINE__, ret);
|
||
|
|
return OPEN_FILE_FAIL;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int i_update_FW(void)
|
||
|
|
{
|
||
|
|
#if !defined(HX_ZERO_FLASH)
|
||
|
|
int upgrade_times = 0;
|
||
|
|
int8_t ret = 0;
|
||
|
|
#endif
|
||
|
|
int8_t result = 0;
|
||
|
|
|
||
|
|
himax_int_enable(0);
|
||
|
|
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
|
||
|
|
g_core_fp.fp_firmware_update_0f(hxfw);
|
||
|
|
|
||
|
|
// g_core_fp.fp_reload_disable(0);
|
||
|
|
|
||
|
|
// g_core_fp.fp_power_on_init();
|
||
|
|
|
||
|
|
g_core_fp.fp_read_FW_ver();
|
||
|
|
|
||
|
|
g_core_fp.fp_touch_information();
|
||
|
|
|
||
|
|
g_core_fp.fp_calc_touch_data_size();
|
||
|
|
|
||
|
|
result = 1;/*upgrade success*/
|
||
|
|
|
||
|
|
#else
|
||
|
|
update_retry:
|
||
|
|
|
||
|
|
if (hxfw->size == FW_SIZE_32k)
|
||
|
|
ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k(
|
||
|
|
(unsigned char *)hxfw->data, hxfw->size, false);
|
||
|
|
else if (hxfw->size == FW_SIZE_60k)
|
||
|
|
ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k(
|
||
|
|
(unsigned char *)hxfw->data, hxfw->size, false);
|
||
|
|
else if (hxfw->size == FW_SIZE_64k)
|
||
|
|
ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k(
|
||
|
|
(unsigned char *)hxfw->data, hxfw->size, false);
|
||
|
|
else if (hxfw->size == FW_SIZE_124k)
|
||
|
|
ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k(
|
||
|
|
(unsigned char *)hxfw->data, hxfw->size, false);
|
||
|
|
else if (hxfw->size == FW_SIZE_128k)
|
||
|
|
ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k(
|
||
|
|
(unsigned char *)hxfw->data, hxfw->size, false);
|
||
|
|
|
||
|
|
if (ret == 0) {
|
||
|
|
upgrade_times++;
|
||
|
|
E("%s: TP upgrade error, upgrade_times = %d\n",
|
||
|
|
__func__, upgrade_times);
|
||
|
|
|
||
|
|
if (upgrade_times < 3)
|
||
|
|
goto update_retry;
|
||
|
|
else
|
||
|
|
result = -1;
|
||
|
|
|
||
|
|
|
||
|
|
} else {
|
||
|
|
g_core_fp.fp_power_on_init();
|
||
|
|
// g_core_fp.fp_power_on_init(NULL);
|
||
|
|
g_core_fp.fp_read_FW_ver();
|
||
|
|
g_core_fp.fp_touch_information();
|
||
|
|
g_core_fp.fp_calc_touch_data_size();
|
||
|
|
result = 1;/*upgrade success*/
|
||
|
|
I("%s: TP upgrade OK\n", __func__);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
himax_int_enable(1);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
/*
|
||
|
|
*static int himax_loadSensorConfig(struct himax_i2c_platform_data *pdata)
|
||
|
|
*{
|
||
|
|
* I("%s: initialization complete\n", __func__);
|
||
|
|
* return NO_ERR;
|
||
|
|
*}
|
||
|
|
*/
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
static void himax_excp_hw_reset(void)
|
||
|
|
{
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
int result = 0;
|
||
|
|
#endif
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering\n", __func__);
|
||
|
|
|
||
|
|
I("%s: START EXCEPTION Reset\n", __func__);
|
||
|
|
|
||
|
|
if (private_ts->in_self_test == 1) {
|
||
|
|
I("%s: In self test, not TP EXCEPTION Reset\n", __func__);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*g_core_fp.fp_excp_ic_reset();*/
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
I("%s: It will update fw after exception event in zero flash mode!\n",
|
||
|
|
__func__);
|
||
|
|
result = g_core_fp.fp_0f_operation_dirly();
|
||
|
|
if (result) {
|
||
|
|
E("%s: Something is wrong! Skip Update with zero flash!\n",
|
||
|
|
__func__);
|
||
|
|
goto ESCAPE_0F_UPDATE;
|
||
|
|
}
|
||
|
|
// g_core_fp.fp_reload_disable(0);
|
||
|
|
// g_core_fp.fp_sense_on(0x00);
|
||
|
|
himax_report_all_leave_event(private_ts);
|
||
|
|
himax_int_enable(1);
|
||
|
|
ESCAPE_0F_UPDATE:
|
||
|
|
#else
|
||
|
|
g_core_fp.fp_excp_ic_reset();
|
||
|
|
#endif
|
||
|
|
I("%s: END EXCEPTION Reset\n", __func__);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
#if defined(HX_GESTURE_TRACK)
|
||
|
|
static void gest_pt_log_coordinate(int rx, int tx)
|
||
|
|
{
|
||
|
|
/*driver report x y with range 0 - 255 , we scale it up to x/y pixel*/
|
||
|
|
gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255;
|
||
|
|
gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
static int himax_wake_event_parse(struct himax_ts_data *ts, int ts_status)
|
||
|
|
{
|
||
|
|
uint8_t *buf = wake_event_buffer;
|
||
|
|
#if defined(HX_GESTURE_TRACK)
|
||
|
|
int tmp_max_x = 0x00;
|
||
|
|
int tmp_min_x = 0xFFFF;
|
||
|
|
int tmp_max_y = 0x00;
|
||
|
|
int tmp_min_y = 0xFFFF;
|
||
|
|
int gest_len;
|
||
|
|
#endif
|
||
|
|
int i = 0, check_FC = 0, ret;
|
||
|
|
int j = 0, gesture_pos = 0, gesture_flag = 0;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering!, ts_status=%d\n", __func__, ts_status);
|
||
|
|
|
||
|
|
if (buf == NULL) {
|
||
|
|
ret = -ENOMEM;
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
memcpy(buf, hx_touch_data->hx_event_buf, hx_touch_data->event_size);
|
||
|
|
|
||
|
|
for (i = 0; i < GEST_PTLG_ID_LEN; i++) {
|
||
|
|
for (j = 0; j < GEST_SUP_NUM; j++) {
|
||
|
|
if (buf[i] == gest_event[j]) {
|
||
|
|
gesture_flag = buf[i];
|
||
|
|
gesture_pos = j;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
I("0x%2.2X ", buf[i]);
|
||
|
|
if (buf[i] == gesture_flag) {
|
||
|
|
check_FC++;
|
||
|
|
} else {
|
||
|
|
I("ID START at %x , value = 0x%2X skip the event\n",
|
||
|
|
i, buf[i]);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
I("Himax gesture_flag= %x\n", gesture_flag);
|
||
|
|
I("Himax check_FC is %d\n", check_FC);
|
||
|
|
|
||
|
|
if (check_FC != GEST_PTLG_ID_LEN) {
|
||
|
|
ret = 0;
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1
|
||
|
|
|| buf[GEST_PTLG_ID_LEN + 1] != GEST_PTLG_HDR_ID2) {
|
||
|
|
ret = 0;
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_GESTURE_TRACK)
|
||
|
|
|
||
|
|
if (buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1
|
||
|
|
&& buf[GEST_PTLG_ID_LEN + 1] == GEST_PTLG_HDR_ID2) {
|
||
|
|
gest_len = buf[GEST_PTLG_ID_LEN + 2];
|
||
|
|
I("gest_len = %d\n", gest_len);
|
||
|
|
i = 0;
|
||
|
|
gest_pt_cnt = 0;
|
||
|
|
I("gest doornidate start\n %s", __func__);
|
||
|
|
|
||
|
|
while (i < (gest_len + 1) / 2) {
|
||
|
|
gest_pt_log_coordinate(
|
||
|
|
buf[GEST_PTLG_ID_LEN + 4 + i * 2],
|
||
|
|
buf[GEST_PTLG_ID_LEN + 4 + i * 2 + 1]);
|
||
|
|
i++;
|
||
|
|
I("gest_pt_x[%d]=%d,gest_pt_y[%d]=%d\n",
|
||
|
|
gest_pt_cnt,
|
||
|
|
gest_pt_x[gest_pt_cnt],
|
||
|
|
gest_pt_cnt,
|
||
|
|
gest_pt_y[gest_pt_cnt]);
|
||
|
|
gest_pt_cnt += 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (gest_pt_cnt) {
|
||
|
|
for (i = 0; i < gest_pt_cnt; i++) {
|
||
|
|
if (tmp_max_x < gest_pt_x[i])
|
||
|
|
tmp_max_x = gest_pt_x[i];
|
||
|
|
if (tmp_min_x > gest_pt_x[i])
|
||
|
|
tmp_min_x = gest_pt_x[i];
|
||
|
|
if (tmp_max_y < gest_pt_y[i])
|
||
|
|
tmp_max_y = gest_pt_y[i];
|
||
|
|
if (tmp_min_y > gest_pt_y[i])
|
||
|
|
tmp_min_y = gest_pt_y[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
I("gest_point x_min=%d,x_max=%d,y_min=%d,y_max=%d\n",
|
||
|
|
tmp_min_x, tmp_max_x, tmp_min_y, tmp_max_y);
|
||
|
|
|
||
|
|
gest_start_x = gest_pt_x[0];
|
||
|
|
hx_gesture_coor[0] = gest_start_x;
|
||
|
|
gest_start_y = gest_pt_y[0];
|
||
|
|
hx_gesture_coor[1] = gest_start_y;
|
||
|
|
gest_end_x = gest_pt_x[gest_pt_cnt - 1];
|
||
|
|
hx_gesture_coor[2] = gest_end_x;
|
||
|
|
gest_end_y = gest_pt_y[gest_pt_cnt - 1];
|
||
|
|
hx_gesture_coor[3] = gest_end_y;
|
||
|
|
gest_width = tmp_max_x - tmp_min_x;
|
||
|
|
hx_gesture_coor[4] = gest_width;
|
||
|
|
gest_height = tmp_max_y - tmp_min_y;
|
||
|
|
hx_gesture_coor[5] = gest_height;
|
||
|
|
gest_mid_x = (tmp_max_x + tmp_min_x) / 2;
|
||
|
|
hx_gesture_coor[6] = gest_mid_x;
|
||
|
|
gest_mid_y = (tmp_max_y + tmp_min_y) / 2;
|
||
|
|
hx_gesture_coor[7] = gest_mid_y;
|
||
|
|
/*gest_up_x*/
|
||
|
|
hx_gesture_coor[8] = gest_mid_x;
|
||
|
|
/*gest_up_y*/
|
||
|
|
hx_gesture_coor[9] = gest_mid_y - gest_height / 2;
|
||
|
|
/*gest_down_x*/
|
||
|
|
hx_gesture_coor[10] = gest_mid_x;
|
||
|
|
/*gest_down_y*/
|
||
|
|
hx_gesture_coor[11] = gest_mid_y + gest_height / 2;
|
||
|
|
/*gest_left_x*/
|
||
|
|
hx_gesture_coor[12] = gest_mid_x - gest_width / 2;
|
||
|
|
/*gest_left_y*/
|
||
|
|
hx_gesture_coor[13] = gest_mid_y;
|
||
|
|
/*gest_right_x*/
|
||
|
|
hx_gesture_coor[14] = gest_mid_x + gest_width / 2;
|
||
|
|
/*gest_right_y*/
|
||
|
|
hx_gesture_coor[15] = gest_mid_y;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (!ts->gesture_cust_en[gesture_pos]) {
|
||
|
|
I("%s NOT report key [%d] = %d\n", __func__,
|
||
|
|
gesture_pos, gest_key_def[gesture_pos]);
|
||
|
|
g_target_report_data->SMWP_event_chk = 0;
|
||
|
|
ret = 0;
|
||
|
|
} else {
|
||
|
|
g_target_report_data->SMWP_event_chk =
|
||
|
|
gest_key_def[gesture_pos];
|
||
|
|
ret = gesture_pos;
|
||
|
|
}
|
||
|
|
END:
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void himax_wake_event_report(void)
|
||
|
|
{
|
||
|
|
int KEY_EVENT = g_target_report_data->SMWP_event_chk;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering!\n", __func__);
|
||
|
|
|
||
|
|
if (KEY_EVENT) {
|
||
|
|
I("%s SMART WAKEUP KEY event %d press\n", __func__, KEY_EVENT);
|
||
|
|
input_report_key(private_ts->input_dev, KEY_EVENT, 1);
|
||
|
|
input_sync(private_ts->input_dev);
|
||
|
|
I("%s SMART WAKEUP KEY event %d release\n",
|
||
|
|
__func__, KEY_EVENT);
|
||
|
|
input_report_key(private_ts->input_dev, KEY_EVENT, 0);
|
||
|
|
input_sync(private_ts->input_dev);
|
||
|
|
#if defined(HX_GESTURE_TRACK)
|
||
|
|
I("gest_start_x=%d,start_y=%d,end_x=%d,end_y=%d\n",
|
||
|
|
gest_start_x,
|
||
|
|
gest_start_y,
|
||
|
|
gest_end_x,
|
||
|
|
gest_end_y);
|
||
|
|
I("gest_width=%d,height=%d,mid_x=%d,mid_y=%d\n",
|
||
|
|
gest_width,
|
||
|
|
gest_height,
|
||
|
|
gest_mid_x,
|
||
|
|
gest_mid_y);
|
||
|
|
I("gest_up_x=%d,up_y=%d,down_x=%d,down_y=%d\n",
|
||
|
|
hx_gesture_coor[8],
|
||
|
|
hx_gesture_coor[9],
|
||
|
|
hx_gesture_coor[10],
|
||
|
|
hx_gesture_coor[11]);
|
||
|
|
I("gest_left_x=%d,left_y=%d,right_x=%d,right_y=%d\n",
|
||
|
|
hx_gesture_coor[12],
|
||
|
|
hx_gesture_coor[13],
|
||
|
|
hx_gesture_coor[14],
|
||
|
|
hx_gesture_coor[15]);
|
||
|
|
#endif
|
||
|
|
g_target_report_data->SMWP_event_chk = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
int himax_report_data_init(void)
|
||
|
|
{
|
||
|
|
if (hx_touch_data->hx_coord_buf != NULL) {
|
||
|
|
kfree(hx_touch_data->hx_coord_buf);
|
||
|
|
hx_touch_data->hx_coord_buf = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (hx_touch_data->hx_rawdata_buf != NULL) {
|
||
|
|
kfree(hx_touch_data->hx_rawdata_buf);
|
||
|
|
hx_touch_data->hx_rawdata_buf = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
hx_touch_data->event_size = g_core_fp.fp_get_touch_data_size();
|
||
|
|
|
||
|
|
if (hx_touch_data->hx_event_buf != NULL) {
|
||
|
|
kfree(hx_touch_data->hx_event_buf);
|
||
|
|
hx_touch_data->hx_event_buf = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (wake_event_buffer != NULL) {
|
||
|
|
kfree(wake_event_buffer);
|
||
|
|
wake_event_buffer = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (g_target_report_data != NULL) {
|
||
|
|
if (ic_data->HX_PEN_FUNC) {
|
||
|
|
kfree(g_target_report_data->p_on);
|
||
|
|
g_target_report_data->p_on = NULL;
|
||
|
|
kfree(g_target_report_data->p_tilt_y);
|
||
|
|
g_target_report_data->p_tilt_y = NULL;
|
||
|
|
kfree(g_target_report_data->p_btn2);
|
||
|
|
g_target_report_data->p_btn2 = NULL;
|
||
|
|
kfree(g_target_report_data->p_btn);
|
||
|
|
g_target_report_data->p_btn = NULL;
|
||
|
|
kfree(g_target_report_data->p_tilt_x);
|
||
|
|
g_target_report_data->p_tilt_x = NULL;
|
||
|
|
kfree(g_target_report_data->p_hover);
|
||
|
|
g_target_report_data->p_hover = NULL;
|
||
|
|
kfree(g_target_report_data->pen_id);
|
||
|
|
g_target_report_data->pen_id = NULL;
|
||
|
|
kfree(g_target_report_data->p_w);
|
||
|
|
g_target_report_data->p_w = NULL;
|
||
|
|
kfree(g_target_report_data->p_y);
|
||
|
|
g_target_report_data->p_y = NULL;
|
||
|
|
kfree(g_target_report_data->p_x);
|
||
|
|
g_target_report_data->p_x = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
kfree(g_target_report_data->finger_id);
|
||
|
|
g_target_report_data->finger_id = NULL;
|
||
|
|
kfree(g_target_report_data->w);
|
||
|
|
g_target_report_data->w = NULL;
|
||
|
|
kfree(g_target_report_data->y);
|
||
|
|
g_target_report_data->y = NULL;
|
||
|
|
kfree(g_target_report_data->x);
|
||
|
|
g_target_report_data->x = NULL;
|
||
|
|
kfree(g_target_report_data);
|
||
|
|
g_target_report_data = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
hx_touch_data->touch_all_size = g_core_fp.fp_get_touch_data_size();
|
||
|
|
hx_touch_data->raw_cnt_max = ic_data->HX_MAX_PT / 4;
|
||
|
|
hx_touch_data->raw_cnt_rmd = ic_data->HX_MAX_PT % 4;
|
||
|
|
/* more than 4 fingers */
|
||
|
|
if (hx_touch_data->raw_cnt_rmd != 0x00) {
|
||
|
|
hx_touch_data->rawdata_size =
|
||
|
|
g_core_fp.fp_cal_data_len(
|
||
|
|
hx_touch_data->raw_cnt_rmd,
|
||
|
|
ic_data->HX_MAX_PT,
|
||
|
|
hx_touch_data->raw_cnt_max);
|
||
|
|
|
||
|
|
hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT
|
||
|
|
+ hx_touch_data->raw_cnt_max + 2) * 4;
|
||
|
|
} else { /* less than 4 fingers */
|
||
|
|
hx_touch_data->rawdata_size =
|
||
|
|
g_core_fp.fp_cal_data_len(
|
||
|
|
hx_touch_data->raw_cnt_rmd,
|
||
|
|
ic_data->HX_MAX_PT,
|
||
|
|
hx_touch_data->raw_cnt_max);
|
||
|
|
|
||
|
|
hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT
|
||
|
|
+ hx_touch_data->raw_cnt_max + 1) * 4;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ic_data->HX_PEN_FUNC) {
|
||
|
|
hx_touch_data->touch_info_size += PEN_INFO_SZ;
|
||
|
|
hx_touch_data->rawdata_size -= PEN_INFO_SZ;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((ic_data->HX_TX_NUM
|
||
|
|
* ic_data->HX_RX_NUM
|
||
|
|
+ ic_data->HX_TX_NUM
|
||
|
|
+ ic_data->HX_RX_NUM)
|
||
|
|
% hx_touch_data->rawdata_size == 0)
|
||
|
|
hx_touch_data->rawdata_frame_size =
|
||
|
|
(ic_data->HX_TX_NUM
|
||
|
|
* ic_data->HX_RX_NUM
|
||
|
|
+ ic_data->HX_TX_NUM
|
||
|
|
+ ic_data->HX_RX_NUM)
|
||
|
|
/ hx_touch_data->rawdata_size;
|
||
|
|
else
|
||
|
|
hx_touch_data->rawdata_frame_size =
|
||
|
|
(ic_data->HX_TX_NUM
|
||
|
|
* ic_data->HX_RX_NUM
|
||
|
|
+ ic_data->HX_TX_NUM
|
||
|
|
+ ic_data->HX_RX_NUM)
|
||
|
|
/ hx_touch_data->rawdata_size
|
||
|
|
+ 1;
|
||
|
|
|
||
|
|
I("%s:rawdata_fsz = %d,HX_MAX_PT:%d,hx_raw_cnt_max:%d\n",
|
||
|
|
__func__,
|
||
|
|
hx_touch_data->rawdata_frame_size,
|
||
|
|
ic_data->HX_MAX_PT,
|
||
|
|
hx_touch_data->raw_cnt_max);
|
||
|
|
I("%s:hx_raw_cnt_rmd:%d,g_hx_rawdata_size:%d,touch_info_size:%d\n",
|
||
|
|
__func__,
|
||
|
|
hx_touch_data->raw_cnt_rmd,
|
||
|
|
hx_touch_data->rawdata_size,
|
||
|
|
hx_touch_data->touch_info_size);
|
||
|
|
|
||
|
|
hx_touch_data->hx_coord_buf = kzalloc(sizeof(uint8_t)
|
||
|
|
* (hx_touch_data->touch_info_size),
|
||
|
|
GFP_KERNEL);
|
||
|
|
|
||
|
|
if (hx_touch_data->hx_coord_buf == NULL)
|
||
|
|
goto mem_alloc_fail_coord_buf;
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
wake_event_buffer = kcalloc(hx_touch_data->event_size,
|
||
|
|
sizeof(uint8_t), GFP_KERNEL);
|
||
|
|
if (wake_event_buffer == NULL)
|
||
|
|
goto mem_alloc_fail_smwp;
|
||
|
|
|
||
|
|
hx_touch_data->hx_event_buf = kzalloc(sizeof(uint8_t)
|
||
|
|
* (hx_touch_data->event_size), GFP_KERNEL);
|
||
|
|
if (hx_touch_data->hx_event_buf == NULL)
|
||
|
|
goto mem_alloc_fail_event_buf;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
hx_touch_data->hx_rawdata_buf = kzalloc(sizeof(uint8_t)
|
||
|
|
* (hx_touch_data->touch_all_size
|
||
|
|
- hx_touch_data->touch_info_size),
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (hx_touch_data->hx_rawdata_buf == NULL)
|
||
|
|
goto mem_alloc_fail_rawdata_buf;
|
||
|
|
|
||
|
|
if (g_target_report_data == NULL) {
|
||
|
|
g_target_report_data =
|
||
|
|
kzalloc(sizeof(struct himax_target_report_data),
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data == NULL)
|
||
|
|
goto mem_alloc_fail_report_data;
|
||
|
|
/*
|
||
|
|
*#if defined(HX_SMART_WAKEUP)
|
||
|
|
* g_target_report_data->SMWP_event_chk = 0;
|
||
|
|
*#endif
|
||
|
|
* I("%s: SMWP_event_chk = %d\n", __func__,
|
||
|
|
* g_target_report_data->SMWP_event_chk);
|
||
|
|
*/
|
||
|
|
g_target_report_data->x = kzalloc(sizeof(int)
|
||
|
|
* (ic_data->HX_MAX_PT), GFP_KERNEL);
|
||
|
|
if (g_target_report_data->x == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_x;
|
||
|
|
|
||
|
|
g_target_report_data->y = kzalloc(sizeof(int)
|
||
|
|
* (ic_data->HX_MAX_PT), GFP_KERNEL);
|
||
|
|
if (g_target_report_data->y == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_y;
|
||
|
|
|
||
|
|
g_target_report_data->w = kzalloc(sizeof(int)
|
||
|
|
* (ic_data->HX_MAX_PT), GFP_KERNEL);
|
||
|
|
if (g_target_report_data->w == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_w;
|
||
|
|
|
||
|
|
g_target_report_data->finger_id = kzalloc(sizeof(int)
|
||
|
|
* (ic_data->HX_MAX_PT), GFP_KERNEL);
|
||
|
|
if (g_target_report_data->finger_id == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_fid;
|
||
|
|
|
||
|
|
if (!ic_data->HX_PEN_FUNC)
|
||
|
|
goto skip_pen_operation;
|
||
|
|
|
||
|
|
g_target_report_data->p_x = kzalloc(sizeof(int)*2, GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_x == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_px;
|
||
|
|
|
||
|
|
g_target_report_data->p_y = kzalloc(sizeof(int)*2, GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_y == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_py;
|
||
|
|
|
||
|
|
g_target_report_data->p_w = kzalloc(sizeof(int)*2, GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_w == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_pw;
|
||
|
|
|
||
|
|
g_target_report_data->pen_id = kzalloc(sizeof(int)*2,
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data->pen_id == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_pid;
|
||
|
|
|
||
|
|
g_target_report_data->p_hover = kzalloc(sizeof(int)*2,
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_hover == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_ph;
|
||
|
|
|
||
|
|
g_target_report_data->p_tilt_x = kzalloc(sizeof(int)*2,
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_tilt_x == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_ptx;
|
||
|
|
|
||
|
|
g_target_report_data->p_btn = kzalloc(sizeof(int)*2,
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_btn == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_pb;
|
||
|
|
|
||
|
|
g_target_report_data->p_btn2 = kzalloc(sizeof(int)*2,
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_btn2 == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_pb2;
|
||
|
|
|
||
|
|
g_target_report_data->p_tilt_y = kzalloc(sizeof(int)*2,
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_tilt_y == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_pty;
|
||
|
|
|
||
|
|
g_target_report_data->p_on = kzalloc(sizeof(int)*2, GFP_KERNEL);
|
||
|
|
if (g_target_report_data->p_on == NULL)
|
||
|
|
goto mem_alloc_fail_report_data_pon;
|
||
|
|
}
|
||
|
|
|
||
|
|
skip_pen_operation:
|
||
|
|
|
||
|
|
return NO_ERR;
|
||
|
|
|
||
|
|
mem_alloc_fail_report_data_pon:
|
||
|
|
kfree(g_target_report_data->p_tilt_y);
|
||
|
|
g_target_report_data->p_tilt_y = NULL;
|
||
|
|
mem_alloc_fail_report_data_pty:
|
||
|
|
kfree(g_target_report_data->p_btn2);
|
||
|
|
g_target_report_data->p_btn2 = NULL;
|
||
|
|
mem_alloc_fail_report_data_pb2:
|
||
|
|
kfree(g_target_report_data->p_btn);
|
||
|
|
g_target_report_data->p_btn = NULL;
|
||
|
|
mem_alloc_fail_report_data_pb:
|
||
|
|
kfree(g_target_report_data->p_tilt_x);
|
||
|
|
g_target_report_data->p_tilt_x = NULL;
|
||
|
|
mem_alloc_fail_report_data_ptx:
|
||
|
|
kfree(g_target_report_data->p_hover);
|
||
|
|
g_target_report_data->p_hover = NULL;
|
||
|
|
mem_alloc_fail_report_data_ph:
|
||
|
|
kfree(g_target_report_data->pen_id);
|
||
|
|
g_target_report_data->pen_id = NULL;
|
||
|
|
mem_alloc_fail_report_data_pid:
|
||
|
|
kfree(g_target_report_data->p_w);
|
||
|
|
g_target_report_data->p_w = NULL;
|
||
|
|
mem_alloc_fail_report_data_pw:
|
||
|
|
kfree(g_target_report_data->p_y);
|
||
|
|
g_target_report_data->p_y = NULL;
|
||
|
|
mem_alloc_fail_report_data_py:
|
||
|
|
kfree(g_target_report_data->p_x);
|
||
|
|
g_target_report_data->p_x = NULL;
|
||
|
|
mem_alloc_fail_report_data_px:
|
||
|
|
|
||
|
|
kfree(g_target_report_data->finger_id);
|
||
|
|
g_target_report_data->finger_id = NULL;
|
||
|
|
mem_alloc_fail_report_data_fid:
|
||
|
|
kfree(g_target_report_data->w);
|
||
|
|
g_target_report_data->w = NULL;
|
||
|
|
mem_alloc_fail_report_data_w:
|
||
|
|
kfree(g_target_report_data->y);
|
||
|
|
g_target_report_data->y = NULL;
|
||
|
|
mem_alloc_fail_report_data_y:
|
||
|
|
kfree(g_target_report_data->x);
|
||
|
|
g_target_report_data->x = NULL;
|
||
|
|
mem_alloc_fail_report_data_x:
|
||
|
|
kfree(g_target_report_data);
|
||
|
|
g_target_report_data = NULL;
|
||
|
|
mem_alloc_fail_report_data:
|
||
|
|
kfree(hx_touch_data->hx_rawdata_buf);
|
||
|
|
hx_touch_data->hx_rawdata_buf = NULL;
|
||
|
|
mem_alloc_fail_rawdata_buf:
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
kfree(hx_touch_data->hx_event_buf);
|
||
|
|
hx_touch_data->hx_event_buf = NULL;
|
||
|
|
mem_alloc_fail_event_buf:
|
||
|
|
kfree(wake_event_buffer);
|
||
|
|
wake_event_buffer = NULL;
|
||
|
|
mem_alloc_fail_smwp:
|
||
|
|
#endif
|
||
|
|
kfree(hx_touch_data->hx_coord_buf);
|
||
|
|
hx_touch_data->hx_coord_buf = NULL;
|
||
|
|
mem_alloc_fail_coord_buf:
|
||
|
|
|
||
|
|
E("%s: Failed to allocate memory\n", __func__);
|
||
|
|
return MEM_ALLOC_FAIL;
|
||
|
|
}
|
||
|
|
EXPORT_SYMBOL(himax_report_data_init);
|
||
|
|
|
||
|
|
void himax_report_data_deinit(void)
|
||
|
|
{
|
||
|
|
if (ic_data->HX_PEN_FUNC) {
|
||
|
|
kfree(g_target_report_data->p_on);
|
||
|
|
g_target_report_data->p_on = NULL;
|
||
|
|
kfree(g_target_report_data->p_tilt_y);
|
||
|
|
g_target_report_data->p_tilt_y = NULL;
|
||
|
|
kfree(g_target_report_data->p_btn2);
|
||
|
|
g_target_report_data->p_btn2 = NULL;
|
||
|
|
kfree(g_target_report_data->p_btn);
|
||
|
|
g_target_report_data->p_btn = NULL;
|
||
|
|
kfree(g_target_report_data->p_tilt_x);
|
||
|
|
g_target_report_data->p_tilt_x = NULL;
|
||
|
|
kfree(g_target_report_data->p_hover);
|
||
|
|
g_target_report_data->p_hover = NULL;
|
||
|
|
kfree(g_target_report_data->pen_id);
|
||
|
|
g_target_report_data->pen_id = NULL;
|
||
|
|
kfree(g_target_report_data->p_w);
|
||
|
|
g_target_report_data->p_w = NULL;
|
||
|
|
kfree(g_target_report_data->p_y);
|
||
|
|
g_target_report_data->p_y = NULL;
|
||
|
|
kfree(g_target_report_data->p_x);
|
||
|
|
g_target_report_data->p_x = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
kfree(g_target_report_data->finger_id);
|
||
|
|
g_target_report_data->finger_id = NULL;
|
||
|
|
kfree(g_target_report_data->w);
|
||
|
|
g_target_report_data->w = NULL;
|
||
|
|
kfree(g_target_report_data->y);
|
||
|
|
g_target_report_data->y = NULL;
|
||
|
|
kfree(g_target_report_data->x);
|
||
|
|
g_target_report_data->x = NULL;
|
||
|
|
kfree(g_target_report_data);
|
||
|
|
g_target_report_data = NULL;
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
kfree(wake_event_buffer);
|
||
|
|
wake_event_buffer = NULL;
|
||
|
|
kfree(hx_touch_data->hx_event_buf);
|
||
|
|
hx_touch_data->hx_event_buf = NULL;
|
||
|
|
#endif
|
||
|
|
kfree(hx_touch_data->hx_rawdata_buf);
|
||
|
|
hx_touch_data->hx_rawdata_buf = NULL;
|
||
|
|
kfree(hx_touch_data->hx_coord_buf);
|
||
|
|
hx_touch_data->hx_coord_buf = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*start ts_work*/
|
||
|
|
#if defined(HX_USB_DETECT_GLOBAL)
|
||
|
|
void himax_cable_detect_func(bool force_renew)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts;
|
||
|
|
|
||
|
|
/*u32 connect_status = 0;*/
|
||
|
|
uint8_t connect_status = 0;
|
||
|
|
|
||
|
|
connect_status = USB_detect_flag;/* upmu_is_chr_det(); */
|
||
|
|
ts = private_ts;
|
||
|
|
|
||
|
|
/* I("Touch: cable status=%d, cable_config=%p, usb_connected=%d\n",*/
|
||
|
|
/* connect_status, ts->cable_config, ts->usb_connected); */
|
||
|
|
if (ts->cable_config) {
|
||
|
|
if ((connect_status != ts->usb_connected) || force_renew) {
|
||
|
|
if (connect_status) {
|
||
|
|
ts->cable_config[1] = 0x01;
|
||
|
|
ts->usb_connected = 0x01;
|
||
|
|
} else {
|
||
|
|
ts->cable_config[1] = 0x00;
|
||
|
|
ts->usb_connected = 0x00;
|
||
|
|
}
|
||
|
|
|
||
|
|
g_core_fp.fp_usb_detect_set(ts->cable_config);
|
||
|
|
I("%s: Cable status change: 0x%2.2X\n", __func__,
|
||
|
|
ts->usb_connected);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*else*/
|
||
|
|
/* I("%s: Cable status is the same as*/
|
||
|
|
/* previous one, ignore.\n", __func__);*/
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static int himax_ts_work_status(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
/* 1: normal, 2:SMWP */
|
||
|
|
int result = HX_REPORT_COORD;
|
||
|
|
|
||
|
|
hx_touch_data->diag_cmd = ts->diag_cmd;
|
||
|
|
if (hx_touch_data->diag_cmd)
|
||
|
|
result = HX_REPORT_COORD_RAWDATA;
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
if (atomic_read(&ts->suspend_mode)
|
||
|
|
&& (ts->SMWP_enable)
|
||
|
|
&& (!hx_touch_data->diag_cmd))
|
||
|
|
result = HX_REPORT_SMWP_EVENT;
|
||
|
|
#endif
|
||
|
|
/* I("Now Status is %d\n", result); */
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int himax_touch_get(struct himax_ts_data *ts, uint8_t *buf,
|
||
|
|
int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
|
||
|
|
switch (ts_path) {
|
||
|
|
/*normal*/
|
||
|
|
case HX_REPORT_COORD:
|
||
|
|
if ((HX_HW_RESET_ACTIVATE)
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
|| (HX_EXCP_RESET_ACTIVATE)
|
||
|
|
#endif
|
||
|
|
) {
|
||
|
|
if (!g_core_fp.fp_read_event_stack(buf, 128)) {
|
||
|
|
E("%s: can't read data from chip!\n", __func__);
|
||
|
|
ts_status = HX_TS_GET_DATA_FAIL;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (!g_core_fp.fp_read_event_stack(buf,
|
||
|
|
hx_touch_data->touch_info_size)) {
|
||
|
|
E("%s: can't read data from chip!\n", __func__);
|
||
|
|
ts_status = HX_TS_GET_DATA_FAIL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
|
||
|
|
/*SMWP*/
|
||
|
|
case HX_REPORT_SMWP_EVENT:
|
||
|
|
__pm_wakeup_event(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
|
||
|
|
msleep(20);
|
||
|
|
g_core_fp.fp_burst_enable(0);
|
||
|
|
|
||
|
|
if (!g_core_fp.fp_read_event_stack(buf,
|
||
|
|
hx_touch_data->event_size)) {
|
||
|
|
E("%s: can't read data from chip!\n", __func__);
|
||
|
|
ts_status = HX_TS_GET_DATA_FAIL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
#endif
|
||
|
|
case HX_REPORT_COORD_RAWDATA:
|
||
|
|
if (!g_core_fp.fp_read_event_stack(buf, 128)) {
|
||
|
|
E("%s: can't read data from chip!\n", __func__);
|
||
|
|
ts_status = HX_TS_GET_DATA_FAIL;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* start error_control*/
|
||
|
|
static int himax_checksum_cal(struct himax_ts_data *ts, uint8_t *buf,
|
||
|
|
int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
uint16_t check_sum_cal = 0;
|
||
|
|
int32_t i = 0;
|
||
|
|
int length = 0;
|
||
|
|
int zero_cnt = 0;
|
||
|
|
int raw_data_sel = 0;
|
||
|
|
int ret_val = ts_status;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
|
||
|
|
/* Normal */
|
||
|
|
switch (ts_path) {
|
||
|
|
case HX_REPORT_COORD:
|
||
|
|
length = hx_touch_data->touch_info_size;
|
||
|
|
break;
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
/* SMWP */
|
||
|
|
case HX_REPORT_SMWP_EVENT:
|
||
|
|
length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN);
|
||
|
|
break;
|
||
|
|
#endif
|
||
|
|
case HX_REPORT_COORD_RAWDATA:
|
||
|
|
length = hx_touch_data->touch_info_size;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
I("%s, Neither Normal Nor SMWP error!\n", __func__);
|
||
|
|
ret_val = HX_PATH_FAIL;
|
||
|
|
goto END_FUNCTION;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < length; i++) {
|
||
|
|
check_sum_cal += buf[i];
|
||
|
|
if (buf[i] == 0x00)
|
||
|
|
zero_cnt++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (check_sum_cal % 0x100 != 0) {
|
||
|
|
I("point data_checksum not match check_sum_cal: 0x%02X",
|
||
|
|
check_sum_cal);
|
||
|
|
ret_val = HX_CHKSUM_FAIL;
|
||
|
|
} else if (zero_cnt == length) {
|
||
|
|
if (ts->use_irq)
|
||
|
|
I("[HIMAX TP MSG] All Zero event\n");
|
||
|
|
|
||
|
|
ret_val = HX_CHKSUM_FAIL;
|
||
|
|
} else {
|
||
|
|
raw_data_sel = buf[HX_TOUCH_INFO_POINT_CNT]>>4 & 0x0F;
|
||
|
|
/*I("%s:raw_out_sel=%x , hx_touch_data->diag_cmd=%x.\n",*/
|
||
|
|
/* __func__, raw_data_sel,*/
|
||
|
|
/* hx_touch_data->diag_cmd);*/
|
||
|
|
/*raw data out not match skip it*/
|
||
|
|
if ((raw_data_sel != 0x0F)
|
||
|
|
&& (raw_data_sel != hx_touch_data->diag_cmd)) {
|
||
|
|
/*I("%s:raw data out not match.\n", __func__);*/
|
||
|
|
if (!hx_touch_data->diag_cmd) {
|
||
|
|
/*Need to clear event stack here*/
|
||
|
|
g_core_fp.fp_read_event_stack(buf,
|
||
|
|
(128-hx_touch_data->touch_info_size));
|
||
|
|
/*I("%s: size =%d, buf[0]=%x ,buf[1]=%x,*/
|
||
|
|
/* buf[2]=%x, buf[3]=%x.\n",*/
|
||
|
|
/* __func__,*/
|
||
|
|
/* (128-hx_touch_data->touch_info_size),*/
|
||
|
|
/* buf[0], buf[1], buf[2], buf[3]);*/
|
||
|
|
/*I("%s:also clear event stack.\n", __func__);*/
|
||
|
|
}
|
||
|
|
ret_val = HX_READY_SERVE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
END_FUNCTION:
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: END, ret_val=%d!\n", __func__, ret_val);
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
void hx_update_dirly_0f(void)
|
||
|
|
{
|
||
|
|
I("It will update fw after exception event in zero flash mode!\n");
|
||
|
|
g_core_fp.fp_0f_operation_dirly();
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
static int himax_ts_event_check(struct himax_ts_data *ts,
|
||
|
|
uint8_t *buf, int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
uint32_t hx_EB_event = 0;
|
||
|
|
uint32_t hx_EC_event = 0;
|
||
|
|
uint32_t hx_EE_event = 0; /*This is from FW in 102e*/
|
||
|
|
uint32_t hx_ED_event = 0; /*This is from HW in 102e*/
|
||
|
|
uint32_t hx_excp_event = 0;
|
||
|
|
// uint32_t hx_zero_event = 0;
|
||
|
|
int shaking_ret = 0;
|
||
|
|
|
||
|
|
uint32_t loop_i = 0;
|
||
|
|
uint32_t length = 0;
|
||
|
|
int ret_val = ts_status;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
|
||
|
|
/* Normal */
|
||
|
|
switch (ts_path) {
|
||
|
|
case HX_REPORT_COORD:
|
||
|
|
length = hx_touch_data->touch_info_size;
|
||
|
|
break;
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
/* SMWP */
|
||
|
|
case HX_REPORT_SMWP_EVENT:
|
||
|
|
length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN);
|
||
|
|
// length = hx_touch_data->touch_info_size;
|
||
|
|
break;
|
||
|
|
#endif
|
||
|
|
case HX_REPORT_COORD_RAWDATA:
|
||
|
|
length = hx_touch_data->touch_info_size;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
I("%s, Neither Normal Nor SMWP error!\n", __func__);
|
||
|
|
ret_val = HX_PATH_FAIL;
|
||
|
|
goto END_FUNCTION;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("Now Path=%d, Now status=%d, length=%d\n",
|
||
|
|
ts_path, ts_status, length);
|
||
|
|
|
||
|
|
if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) {
|
||
|
|
if (ic_data->HX_PEN_FUNC)
|
||
|
|
length -= PEN_INFO_SZ;
|
||
|
|
for (loop_i = 0; loop_i < length; loop_i++) {
|
||
|
|
/* case 1 EXCEEPTION recovery flow */
|
||
|
|
if (buf[loop_i] == 0xEB) {
|
||
|
|
hx_EB_event++;
|
||
|
|
} else if (buf[loop_i] == 0xEC) {
|
||
|
|
hx_EC_event++;
|
||
|
|
} else if (buf[loop_i] == 0xEE) {
|
||
|
|
hx_EE_event++;
|
||
|
|
/* case 2 EXCEPTION recovery flow-Disable */
|
||
|
|
} else if (buf[loop_i] == 0xED) {
|
||
|
|
hx_ED_event++;
|
||
|
|
// } else if (buf[loop_i] == 0x00) {
|
||
|
|
// hx_zero_event++;
|
||
|
|
} else {
|
||
|
|
g_zero_event_count = 0;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*This is special for 102e since 0xED will be received after reset*/
|
||
|
|
// if (hx_ED_event == length)
|
||
|
|
// g_core_fp.fp_0f_reload_to_active();
|
||
|
|
/******************************************************************/
|
||
|
|
|
||
|
|
if (hx_EB_event == length) {
|
||
|
|
hx_excp_event = length;
|
||
|
|
hx_EB_event_flag++;
|
||
|
|
I("[HIMAX TP MSG]: EXCEPTION event checked - ALL 0xEB.\n");
|
||
|
|
} else if (hx_EC_event == length) {
|
||
|
|
hx_excp_event = length;
|
||
|
|
hx_EC_event_flag++;
|
||
|
|
I("[HIMAX TP MSG]: EXCEPTION event checked - ALL 0xEC.\n");
|
||
|
|
} else if (hx_EE_event == length) {
|
||
|
|
hx_excp_event = length;
|
||
|
|
hx_EE_event_flag++;
|
||
|
|
I("[HIMAX TP MSG]: EXCEPTION event checked - ALL 0xEE.\n");
|
||
|
|
} else if (hx_ED_event == length) {
|
||
|
|
g_core_fp.fp_0f_reload_to_active();
|
||
|
|
// } else {
|
||
|
|
// g_zero_event_count = 0;
|
||
|
|
}
|
||
|
|
/*#if defined(HX_ZERO_FLASH)
|
||
|
|
* //This is for previous version(a, b) because HW pull TSIX
|
||
|
|
* low continuely after watchdog timeout reset
|
||
|
|
* else if (hx_zero_event == length) {
|
||
|
|
* //check zero flash status
|
||
|
|
* if (g_core_fp.fp_0f_esd_check() < 0) {
|
||
|
|
* g_zero_event_count = 6;
|
||
|
|
* I("[HIMAX TP MSG]: ESD event checked
|
||
|
|
- ALL Zero in ZF.\n");
|
||
|
|
* } else {
|
||
|
|
* I("[HIMAX TP MSG]: Status check pass in ZF.\n");
|
||
|
|
* }
|
||
|
|
* }
|
||
|
|
*#endif
|
||
|
|
*/
|
||
|
|
|
||
|
|
// if ((hx_excp_event == length || hx_zero_event == length || hx_ED_event == length)
|
||
|
|
if ((hx_excp_event == length || hx_ED_event == length)
|
||
|
|
&& (HX_HW_RESET_ACTIVATE == 0)
|
||
|
|
&& (HX_EXCP_RESET_ACTIVATE == 0)
|
||
|
|
&& (hx_touch_data->diag_cmd == 0)
|
||
|
|
&& (ts->in_self_test == 0)) {
|
||
|
|
shaking_ret = g_core_fp.fp_ic_excp_recovery(
|
||
|
|
// hx_excp_event, hx_zero_event, length);
|
||
|
|
hx_excp_event, hx_ED_event, length);
|
||
|
|
|
||
|
|
if (shaking_ret == HX_EXCP_EVENT) {
|
||
|
|
g_core_fp.fp_read_FW_status();
|
||
|
|
himax_excp_hw_reset();
|
||
|
|
ret_val = HX_EXCP_EVENT;
|
||
|
|
} else if (shaking_ret == HX_ZERO_EVENT_COUNT) {
|
||
|
|
g_core_fp.fp_read_FW_status();
|
||
|
|
ret_val = HX_ZERO_EVENT_COUNT;
|
||
|
|
} else {
|
||
|
|
I("I2C running. Nothing to be done!\n");
|
||
|
|
ret_val = HX_IC_RUNNING;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* drop 1st interrupts after chip reset */
|
||
|
|
} else if (HX_EXCP_RESET_ACTIVATE) {
|
||
|
|
HX_EXCP_RESET_ACTIVATE = 0;
|
||
|
|
I("%s: Skip by HX_EXCP_RESET_ACTIVATE.\n", __func__);
|
||
|
|
ret_val = HX_EXCP_REC_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
END_FUNCTION:
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: END, ret_val=%d!\n", __func__, ret_val);
|
||
|
|
|
||
|
|
return ret_val;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static int himax_err_ctrl(struct himax_ts_data *ts,
|
||
|
|
uint8_t *buf, int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
#if defined(HX_RST_PIN_FUNC)
|
||
|
|
if (HX_HW_RESET_ACTIVATE) {
|
||
|
|
/* drop 1st interrupts after chip reset */
|
||
|
|
HX_HW_RESET_ACTIVATE = 0;
|
||
|
|
I("[HX_HW_RESET_ACTIVATE]%s:Back from reset,ready to serve.\n",
|
||
|
|
__func__);
|
||
|
|
ts_status = HX_RST_OK;
|
||
|
|
goto END_FUNCTION;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ts_status = himax_checksum_cal(ts, buf, ts_path, ts_status);
|
||
|
|
if (ts_status == HX_CHKSUM_FAIL) {
|
||
|
|
goto CHK_FAIL;
|
||
|
|
} else {
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
/* continuous N times record, not total N times. */
|
||
|
|
g_zero_event_count = 0;
|
||
|
|
#endif
|
||
|
|
goto END_FUNCTION;
|
||
|
|
}
|
||
|
|
|
||
|
|
CHK_FAIL:
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
ts_status = himax_ts_event_check(ts, buf, ts_path, ts_status);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
END_FUNCTION:
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: END, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
/* end error_control*/
|
||
|
|
|
||
|
|
/* start distribute_data*/
|
||
|
|
static int himax_distribute_touch_data(uint8_t *buf,
|
||
|
|
int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
uint8_t hx_state_info_pos = hx_touch_data->touch_info_size - 3;
|
||
|
|
|
||
|
|
if (ic_data->HX_PEN_FUNC)
|
||
|
|
hx_state_info_pos -= PEN_INFO_SZ;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
|
||
|
|
if (ts_path == HX_REPORT_COORD) {
|
||
|
|
memcpy(hx_touch_data->hx_coord_buf, &buf[0],
|
||
|
|
hx_touch_data->touch_info_size);
|
||
|
|
|
||
|
|
if (buf[hx_state_info_pos] != 0xFF
|
||
|
|
&& buf[hx_state_info_pos + 1] != 0xFF)
|
||
|
|
memcpy(hx_touch_data->hx_state_info,
|
||
|
|
&buf[hx_state_info_pos], 2);
|
||
|
|
else
|
||
|
|
memset(hx_touch_data->hx_state_info, 0x00,
|
||
|
|
sizeof(hx_touch_data->hx_state_info));
|
||
|
|
|
||
|
|
if ((HX_HW_RESET_ACTIVATE)
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
|| (HX_EXCP_RESET_ACTIVATE)
|
||
|
|
#endif
|
||
|
|
) {
|
||
|
|
memcpy(hx_touch_data->hx_rawdata_buf,
|
||
|
|
&buf[hx_touch_data->touch_info_size],
|
||
|
|
hx_touch_data->touch_all_size
|
||
|
|
- hx_touch_data->touch_info_size);
|
||
|
|
}
|
||
|
|
} else if (ts_path == HX_REPORT_COORD_RAWDATA) {
|
||
|
|
memcpy(hx_touch_data->hx_coord_buf, &buf[0],
|
||
|
|
hx_touch_data->touch_info_size);
|
||
|
|
|
||
|
|
if (buf[hx_state_info_pos] != 0xFF
|
||
|
|
&& buf[hx_state_info_pos + 1] != 0xFF)
|
||
|
|
memcpy(hx_touch_data->hx_state_info,
|
||
|
|
&buf[hx_state_info_pos], 2);
|
||
|
|
else
|
||
|
|
memset(hx_touch_data->hx_state_info, 0x00,
|
||
|
|
sizeof(hx_touch_data->hx_state_info));
|
||
|
|
|
||
|
|
memcpy(hx_touch_data->hx_rawdata_buf,
|
||
|
|
&buf[hx_touch_data->touch_info_size],
|
||
|
|
hx_touch_data->touch_all_size
|
||
|
|
- hx_touch_data->touch_info_size);
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
} else if (ts_path == HX_REPORT_SMWP_EVENT) {
|
||
|
|
memcpy(hx_touch_data->hx_event_buf, buf,
|
||
|
|
hx_touch_data->event_size);
|
||
|
|
#endif
|
||
|
|
} else {
|
||
|
|
E("%s, Fail Path!\n", __func__);
|
||
|
|
ts_status = HX_PATH_FAIL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: End, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
/* end assign_data*/
|
||
|
|
|
||
|
|
/* start parse_report_data*/
|
||
|
|
int himax_parse_report_points(struct himax_ts_data *ts,
|
||
|
|
int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
int x = 0, y = 0, w = 0;
|
||
|
|
|
||
|
|
uint8_t p_hover = 0, p_btn = 0, p_btn2 = 0;
|
||
|
|
int8_t p_tilt_x = 0, p_tilt_y = 0;
|
||
|
|
int p_x = 0, p_y = 0, p_w = 0;
|
||
|
|
static uint8_t p_p_on;
|
||
|
|
|
||
|
|
int base = 0;
|
||
|
|
int32_t loop_i = 0;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: start!\n", __func__);
|
||
|
|
|
||
|
|
base = hx_touch_data->touch_info_size;
|
||
|
|
|
||
|
|
if (!ic_data->HX_PEN_FUNC)
|
||
|
|
goto skip_pen_operation;
|
||
|
|
|
||
|
|
p_p_on = 0;
|
||
|
|
base -= PEN_INFO_SZ;
|
||
|
|
|
||
|
|
p_x = hx_touch_data->hx_coord_buf[base] << 8
|
||
|
|
| hx_touch_data->hx_coord_buf[base + 1];
|
||
|
|
p_y = (hx_touch_data->hx_coord_buf[base + 2] << 8
|
||
|
|
| hx_touch_data->hx_coord_buf[base + 3]);
|
||
|
|
p_w = (hx_touch_data->hx_coord_buf[base + 4] << 8
|
||
|
|
| hx_touch_data->hx_coord_buf[base + 5]);
|
||
|
|
p_tilt_x = (int8_t)hx_touch_data->hx_coord_buf[base + 6];
|
||
|
|
p_hover = hx_touch_data->hx_coord_buf[base + 7];
|
||
|
|
p_btn = hx_touch_data->hx_coord_buf[base + 8];
|
||
|
|
p_btn2 = hx_touch_data->hx_coord_buf[base + 9];
|
||
|
|
p_tilt_y = (int8_t)hx_touch_data->hx_coord_buf[base + 10];
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0) {
|
||
|
|
D("%s: p_x=%d, p_y=%d, p_w=%d,p_tilt_x=%d, p_hover=%d\n",
|
||
|
|
__func__, p_x, p_y, p_w, p_tilt_x, p_hover);
|
||
|
|
D("%s: p_btn=%d, p_btn2=%d, p_tilt_y=%d\n",
|
||
|
|
__func__, p_btn, p_btn2, p_tilt_y);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (p_x >= 0
|
||
|
|
&& p_x <= ts->pdata->abs_x_max
|
||
|
|
&& p_y >= 0
|
||
|
|
&& p_y <= ts->pdata->abs_y_max) {
|
||
|
|
g_target_report_data->p_x[0] = p_x;
|
||
|
|
g_target_report_data->p_y[0] = p_y;
|
||
|
|
g_target_report_data->p_w[0] = p_w;
|
||
|
|
g_target_report_data->p_hover[0] = p_hover;
|
||
|
|
g_target_report_data->pen_id[0] = 1;
|
||
|
|
g_target_report_data->p_btn[0] = p_btn;
|
||
|
|
g_target_report_data->p_btn2[0] = p_btn2;
|
||
|
|
g_target_report_data->p_tilt_x[0] = p_tilt_x;
|
||
|
|
g_target_report_data->p_tilt_y[0] = p_tilt_y;
|
||
|
|
g_target_report_data->p_on[0] = 1;
|
||
|
|
ts->hx_point_num++;
|
||
|
|
} else {/* report coordinates */
|
||
|
|
g_target_report_data->p_x[0] = 0;
|
||
|
|
g_target_report_data->p_y[0] = 0;
|
||
|
|
g_target_report_data->p_w[0] = 0;
|
||
|
|
g_target_report_data->p_hover[0] = 0;
|
||
|
|
g_target_report_data->pen_id[0] = 0;
|
||
|
|
g_target_report_data->p_btn[0] = 0;
|
||
|
|
g_target_report_data->p_btn2[0] = 0;
|
||
|
|
g_target_report_data->p_tilt_x[0] = 0;
|
||
|
|
g_target_report_data->p_tilt_y[0] = 0;
|
||
|
|
g_target_report_data->p_on[0] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0) {
|
||
|
|
if (p_p_on != g_target_report_data->p_on[0]) {
|
||
|
|
I("p_on[0] = %d, hx_point_num=%d\n",
|
||
|
|
g_target_report_data->p_on[0],
|
||
|
|
ts->hx_point_num);
|
||
|
|
p_p_on = g_target_report_data->p_on[0];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
skip_pen_operation:
|
||
|
|
|
||
|
|
ts->old_finger = ts->pre_finger_mask;
|
||
|
|
if (ts->hx_point_num == 0) {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: hx_point_num = 0!\n", __func__);
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
ts->pre_finger_mask = 0;
|
||
|
|
hx_touch_data->finger_num =
|
||
|
|
hx_touch_data->hx_coord_buf[base - 4] & 0x0F;
|
||
|
|
hx_touch_data->finger_on = 1;
|
||
|
|
AA_press = 1;
|
||
|
|
|
||
|
|
g_target_report_data->finger_num = hx_touch_data->finger_num;
|
||
|
|
g_target_report_data->finger_on = hx_touch_data->finger_on;
|
||
|
|
g_target_report_data->ig_count =
|
||
|
|
hx_touch_data->hx_coord_buf[base - 5];
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s:finger_num = 0x%2X, finger_on = %d\n", __func__,
|
||
|
|
g_target_report_data->finger_num,
|
||
|
|
g_target_report_data->finger_on);
|
||
|
|
|
||
|
|
for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
|
||
|
|
base = loop_i * 4;
|
||
|
|
x = hx_touch_data->hx_coord_buf[base] << 8
|
||
|
|
| hx_touch_data->hx_coord_buf[base + 1];
|
||
|
|
y = (hx_touch_data->hx_coord_buf[base + 2] << 8
|
||
|
|
| hx_touch_data->hx_coord_buf[base + 3]);
|
||
|
|
w = hx_touch_data->hx_coord_buf[(ts->nFinger_support * 4)
|
||
|
|
+ loop_i];
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
D("%s: now parsing[%d]:x=%d, y=%d, w=%d\n", __func__,
|
||
|
|
loop_i, x, y, w);
|
||
|
|
|
||
|
|
if (x >= 0
|
||
|
|
&& x <= ts->pdata->abs_x_max
|
||
|
|
&& y >= 0
|
||
|
|
&& y <= ts->pdata->abs_y_max) {
|
||
|
|
hx_touch_data->finger_num--;
|
||
|
|
|
||
|
|
g_target_report_data->x[loop_i] = x;
|
||
|
|
g_target_report_data->y[loop_i] = y;
|
||
|
|
g_target_report_data->w[loop_i] = w;
|
||
|
|
g_target_report_data->finger_id[loop_i] = 1;
|
||
|
|
|
||
|
|
/*I("%s: g_target_report_data->x[loop_i]=%d,*/
|
||
|
|
/*g_target_report_data->y[loop_i]=%d,*/
|
||
|
|
/*g_target_report_data->w[loop_i]=%d",*/
|
||
|
|
/*__func__, g_target_report_data->x[loop_i],*/
|
||
|
|
/*g_target_report_data->y[loop_i],*/
|
||
|
|
/*g_target_report_data->w[loop_i]); */
|
||
|
|
|
||
|
|
|
||
|
|
if (!ts->first_pressed) {
|
||
|
|
ts->first_pressed = 1;
|
||
|
|
I("S1@%d, %d\n", x, y);
|
||
|
|
}
|
||
|
|
|
||
|
|
ts->pre_finger_data[loop_i][0] = x;
|
||
|
|
ts->pre_finger_data[loop_i][1] = y;
|
||
|
|
|
||
|
|
ts->pre_finger_mask = ts->pre_finger_mask
|
||
|
|
+ (1 << loop_i);
|
||
|
|
} else {/* report coordinates */
|
||
|
|
g_target_report_data->x[loop_i] = x;
|
||
|
|
g_target_report_data->y[loop_i] = y;
|
||
|
|
g_target_report_data->w[loop_i] = w;
|
||
|
|
g_target_report_data->finger_id[loop_i] = 0;
|
||
|
|
|
||
|
|
if (loop_i == 0 && ts->first_pressed == 1) {
|
||
|
|
ts->first_pressed = 2;
|
||
|
|
I("E1@%d, %d\n", ts->pre_finger_data[0][0],
|
||
|
|
ts->pre_finger_data[0][1]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0) {
|
||
|
|
for (loop_i = 0; loop_i < 10; loop_i++)
|
||
|
|
D("DBG X=%d Y=%d ID=%d\n",
|
||
|
|
g_target_report_data->x[loop_i],
|
||
|
|
g_target_report_data->y[loop_i],
|
||
|
|
g_target_report_data->finger_id[loop_i]);
|
||
|
|
|
||
|
|
D("DBG finger number %d\n", g_target_report_data->finger_num);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: end!\n", __func__);
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int himax_parse_report_data(struct himax_ts_data *ts,
|
||
|
|
int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: start now_status=%d!\n", __func__, ts_status);
|
||
|
|
|
||
|
|
|
||
|
|
EN_NoiseFilter =
|
||
|
|
(hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3);
|
||
|
|
/* I("EN_NoiseFilter=%d\n", EN_NoiseFilter); */
|
||
|
|
EN_NoiseFilter = EN_NoiseFilter & 0x01;
|
||
|
|
/* I("EN_NoiseFilter2=%d\n", EN_NoiseFilter); */
|
||
|
|
p_point_num = ts->hx_point_num;
|
||
|
|
|
||
|
|
if (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] == 0xff)
|
||
|
|
ts->hx_point_num = 0;
|
||
|
|
else
|
||
|
|
ts->hx_point_num =
|
||
|
|
hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT]
|
||
|
|
& 0x0f;
|
||
|
|
|
||
|
|
switch (ts_path) {
|
||
|
|
case HX_REPORT_COORD:
|
||
|
|
ts_status = himax_parse_report_points(ts, ts_path, ts_status);
|
||
|
|
break;
|
||
|
|
case HX_REPORT_COORD_RAWDATA:
|
||
|
|
/* touch monitor rawdata */
|
||
|
|
if (debug_data != NULL) {
|
||
|
|
if (debug_data->fp_set_diag_cmd(ic_data, hx_touch_data))
|
||
|
|
I("%s:raw data_checksum not match\n", __func__);
|
||
|
|
} else {
|
||
|
|
E("%s,There is no init set_diag_cmd\n", __func__);
|
||
|
|
}
|
||
|
|
ts_status = himax_parse_report_points(ts, ts_path, ts_status);
|
||
|
|
break;
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
case HX_REPORT_SMWP_EVENT:
|
||
|
|
himax_wake_event_parse(ts, ts_status);
|
||
|
|
break;
|
||
|
|
#endif
|
||
|
|
default:
|
||
|
|
E("%s:Fail Path!\n", __func__);
|
||
|
|
ts_status = HX_PATH_FAIL;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: end now_status=%d!\n", __func__, ts_status);
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* end parse_report_data*/
|
||
|
|
|
||
|
|
static void himax_report_all_leave_event(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
int loop_i = 0;
|
||
|
|
|
||
|
|
for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
input_mt_slot(ts->input_dev, loop_i);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
|
||
|
|
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
input_report_key(ts->input_dev, BTN_TOUCH, 0);
|
||
|
|
input_sync(ts->input_dev);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* start report_point*/
|
||
|
|
static void himax_finger_report(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
int i = 0;
|
||
|
|
bool valid = false;
|
||
|
|
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0) {
|
||
|
|
I("%s:start hx_touch_data->finger_num=%d\n",
|
||
|
|
__func__, hx_touch_data->finger_num);
|
||
|
|
}
|
||
|
|
for (i = 0; i < ts->nFinger_support; i++) {
|
||
|
|
if (g_target_report_data->x[i] >= 0
|
||
|
|
&& g_target_report_data->x[i] <= ts->pdata->abs_x_max
|
||
|
|
&& g_target_report_data->y[i] >= 0
|
||
|
|
&& g_target_report_data->y[i] <= ts->pdata->abs_y_max)
|
||
|
|
valid = true;
|
||
|
|
else
|
||
|
|
valid = false;
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("valid=%d\n", valid);
|
||
|
|
if (valid) {
|
||
|
|
if (g_ts_dbg != 0) {
|
||
|
|
I("report_data->x[i]=%d,y[i]=%d,w[i]=%d",
|
||
|
|
g_target_report_data->x[i],
|
||
|
|
g_target_report_data->y[i],
|
||
|
|
g_target_report_data->w[i]);
|
||
|
|
}
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
input_mt_slot(ts->input_dev, i);
|
||
|
|
#else
|
||
|
|
input_report_key(ts->input_dev, BTN_TOUCH, 1);
|
||
|
|
#endif
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
|
||
|
|
g_target_report_data->w[i]);
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
|
||
|
|
g_target_report_data->w[i]);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
|
||
|
|
g_target_report_data->w[i]);
|
||
|
|
#else
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID,
|
||
|
|
i + 1);
|
||
|
|
#endif
|
||
|
|
tpd_rotate_180(&g_target_report_data->x[i], &g_target_report_data->y[i]);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
|
||
|
|
g_target_report_data->x[i]);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
|
||
|
|
g_target_report_data->y[i]);
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
ts->last_slot = i;
|
||
|
|
input_mt_report_slot_state(ts->input_dev,
|
||
|
|
MT_TOOL_FINGER, 1);
|
||
|
|
#else
|
||
|
|
input_mt_sync(ts->input_dev);
|
||
|
|
#endif
|
||
|
|
} else {
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
input_mt_slot(ts->input_dev, i);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
|
||
|
|
input_mt_report_slot_state(ts->input_dev,
|
||
|
|
MT_TOOL_FINGER, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
input_report_key(ts->input_dev, BTN_TOUCH, 1);
|
||
|
|
#endif
|
||
|
|
input_sync(ts->input_dev);
|
||
|
|
|
||
|
|
if (!ic_data->HX_PEN_FUNC)
|
||
|
|
goto skip_pen_operation;
|
||
|
|
|
||
|
|
valid = false;
|
||
|
|
|
||
|
|
if (g_target_report_data->p_x[0] >= 0
|
||
|
|
&& g_target_report_data->p_x[0] <= ts->pdata->abs_x_max
|
||
|
|
&& g_target_report_data->p_y[0] >= 0
|
||
|
|
&& g_target_report_data->p_y[0] <= ts->pdata->abs_y_max
|
||
|
|
&& (g_target_report_data->p_on[0] == 1))
|
||
|
|
valid = true;
|
||
|
|
else
|
||
|
|
valid = false;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("pen valid=%d\n", valid);
|
||
|
|
|
||
|
|
if (valid) {/*Pen down*/
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("p_x[i]=%d, p_y[i]=%d, p_w[i]=%d\n",
|
||
|
|
g_target_report_data->p_x[0],
|
||
|
|
g_target_report_data->p_y[0],
|
||
|
|
g_target_report_data->p_w[0]);
|
||
|
|
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_X,
|
||
|
|
g_target_report_data->p_x[0]);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_Y,
|
||
|
|
g_target_report_data->p_y[0]);
|
||
|
|
|
||
|
|
if (g_target_report_data->p_btn[0] !=
|
||
|
|
g_target_report_data->pre_p_btn) {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("BTN_STYLUS:%d\n",
|
||
|
|
g_target_report_data->p_btn[0]);
|
||
|
|
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_STYLUS,
|
||
|
|
g_target_report_data->p_btn[0]);
|
||
|
|
|
||
|
|
g_target_report_data->pre_p_btn =
|
||
|
|
g_target_report_data->p_btn[0];
|
||
|
|
} else {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("BTN_STYLUS status no change, value=%d!\n",
|
||
|
|
g_target_report_data->p_btn[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_target_report_data->p_btn2[0]
|
||
|
|
!= g_target_report_data->pre_p_btn2) {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("BTN_STYLUS2:%d\n",
|
||
|
|
g_target_report_data->p_btn2[0]);
|
||
|
|
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_STYLUS2,
|
||
|
|
g_target_report_data->p_btn2[0]);
|
||
|
|
|
||
|
|
g_target_report_data->pre_p_btn2 =
|
||
|
|
g_target_report_data->p_btn2[0];
|
||
|
|
} else {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("BTN_STYLUS2 status no change, value=%d!\n",
|
||
|
|
g_target_report_data->p_btn2[0]);
|
||
|
|
}
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_TILT_X,
|
||
|
|
g_target_report_data->p_tilt_x[0]);
|
||
|
|
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_TILT_Y,
|
||
|
|
g_target_report_data->p_tilt_y[0]);
|
||
|
|
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 1);
|
||
|
|
|
||
|
|
if (g_target_report_data->p_hover[0] == 0) {
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOUCH, 1);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_PRESSURE,
|
||
|
|
g_target_report_data->p_w[0]);
|
||
|
|
} else {
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 1);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0);
|
||
|
|
}
|
||
|
|
} else {/*Pen up*/
|
||
|
|
g_target_report_data->pre_p_btn = 0;
|
||
|
|
g_target_report_data->pre_p_btn2 = 0;
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_STYLUS, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_STYLUS2, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0);
|
||
|
|
input_sync(ts->hx_pen_dev);
|
||
|
|
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOOL_RUBBER, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0);
|
||
|
|
}
|
||
|
|
input_sync(ts->hx_pen_dev);
|
||
|
|
|
||
|
|
skip_pen_operation:
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s:end\n", __func__);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void himax_finger_leave(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
int32_t loop_i = 0;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: start!\n", __func__);
|
||
|
|
#if defined(HX_PALM_REPORT)
|
||
|
|
if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_REPORT) {
|
||
|
|
I(" %s HX_PALM_REPORT KEY power event press\n", __func__);
|
||
|
|
input_report_key(ts->input_dev, KEY_POWER, 1);
|
||
|
|
input_sync(ts->input_dev);
|
||
|
|
msleep(100);
|
||
|
|
|
||
|
|
I(" %s HX_PALM_REPORT KEY power event release\n", __func__);
|
||
|
|
input_report_key(ts->input_dev, KEY_POWER, 0);
|
||
|
|
input_sync(ts->input_dev);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
hx_touch_data->finger_on = 0;
|
||
|
|
g_target_report_data->finger_on = 0;
|
||
|
|
g_target_report_data->finger_num = 0;
|
||
|
|
AA_press = 0;
|
||
|
|
|
||
|
|
#if defined(HX_PROTOCOL_A)
|
||
|
|
input_mt_sync(ts->input_dev);
|
||
|
|
#endif
|
||
|
|
#if !defined(HX_PROTOCOL_A)
|
||
|
|
for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
|
||
|
|
input_mt_slot(ts->input_dev, loop_i);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
|
||
|
|
input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
|
||
|
|
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
if (ts->pre_finger_mask > 0)
|
||
|
|
ts->pre_finger_mask = 0;
|
||
|
|
|
||
|
|
if (ts->first_pressed == 1) {
|
||
|
|
ts->first_pressed = 2;
|
||
|
|
I("E1@%d, %d\n", ts->pre_finger_data[0][0],
|
||
|
|
ts->pre_finger_data[0][1]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*if (ts->debug_log_level & BIT(1))*/
|
||
|
|
/* himax_log_touch_event(x, y, w, loop_i, EN_NoiseFilter,*/
|
||
|
|
/* HX_FINGER_LEAVE); */
|
||
|
|
|
||
|
|
input_report_key(ts->input_dev, BTN_TOUCH, 0);
|
||
|
|
input_sync(ts->input_dev);
|
||
|
|
|
||
|
|
if (ic_data->HX_PEN_FUNC) {
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_STYLUS, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0);
|
||
|
|
input_sync(ts->hx_pen_dev);
|
||
|
|
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_TILT_X, 0);
|
||
|
|
input_report_abs(ts->hx_pen_dev, ABS_TILT_Y, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOOL_RUBBER, 0);
|
||
|
|
input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 0);
|
||
|
|
input_sync(ts->hx_pen_dev);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: end!\n", __func__);
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
static void himax_report_points(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: start!\n", __func__);
|
||
|
|
|
||
|
|
if (ts->hx_point_num != 0)
|
||
|
|
himax_finger_report(ts);
|
||
|
|
else
|
||
|
|
himax_finger_leave(ts);
|
||
|
|
|
||
|
|
Last_EN_NoiseFilter = EN_NoiseFilter;
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: end!\n", __func__);
|
||
|
|
}
|
||
|
|
/* end report_points*/
|
||
|
|
|
||
|
|
int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: Entering, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
|
||
|
|
if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) {
|
||
|
|
/* Touch Point information */
|
||
|
|
himax_report_points(ts);
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
} else if (ts_path == HX_REPORT_SMWP_EVENT) {
|
||
|
|
himax_wake_event_report();
|
||
|
|
#endif
|
||
|
|
} else {
|
||
|
|
E("%s:Fail Path!\n", __func__);
|
||
|
|
ts_status = HX_PATH_FAIL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("%s: END, ts_status=%d!\n", __func__, ts_status);
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
/* end report_data */
|
||
|
|
|
||
|
|
static int himax_ts_operation(struct himax_ts_data *ts,
|
||
|
|
int ts_path, int ts_status)
|
||
|
|
{
|
||
|
|
uint8_t hw_reset_check[2];
|
||
|
|
|
||
|
|
memset(ts->xfer_buff, 0x00, 128 * sizeof(uint8_t));
|
||
|
|
memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
|
||
|
|
|
||
|
|
ts_status = himax_touch_get(ts, ts->xfer_buff, ts_path, ts_status);
|
||
|
|
if (ts_status == HX_TS_GET_DATA_FAIL)
|
||
|
|
goto END_FUNCTION;
|
||
|
|
|
||
|
|
ts_status = himax_distribute_touch_data(ts->xfer_buff,
|
||
|
|
ts_path, ts_status);
|
||
|
|
ts_status = himax_err_ctrl(ts, ts->xfer_buff, ts_path, ts_status);
|
||
|
|
if (ts_status == HX_REPORT_DATA || ts_status == HX_TS_NORMAL_END)
|
||
|
|
ts_status = himax_parse_report_data(ts, ts_path, ts_status);
|
||
|
|
else
|
||
|
|
goto END_FUNCTION;
|
||
|
|
|
||
|
|
|
||
|
|
ts_status = himax_report_data(ts, ts_path, ts_status);
|
||
|
|
|
||
|
|
|
||
|
|
END_FUNCTION:
|
||
|
|
return ts_status;
|
||
|
|
}
|
||
|
|
|
||
|
|
void himax_ts_work(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
|
||
|
|
int ts_status = HX_TS_NORMAL_END;
|
||
|
|
int ts_path = 0;
|
||
|
|
|
||
|
|
if (debug_data != NULL) {
|
||
|
|
if (debug_data->is_checking_irq) {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("Now checking IRQ, skip it!\n");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
debug_data->fp_ts_dbg_func(ts, HX_FINGER_ON);
|
||
|
|
}
|
||
|
|
if (ts->notouch_frame > 0) {
|
||
|
|
if (g_ts_dbg != 0)
|
||
|
|
I("Skipit=%d\n", ts->notouch_frame--);
|
||
|
|
else
|
||
|
|
ts->notouch_frame--;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_USB_DETECT_GLOBAL)
|
||
|
|
himax_cable_detect_func(false);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ts_path = himax_ts_work_status(ts);
|
||
|
|
switch (ts_path) {
|
||
|
|
case HX_REPORT_COORD:
|
||
|
|
ts_status = himax_ts_operation(ts, ts_path, ts_status);
|
||
|
|
break;
|
||
|
|
case HX_REPORT_SMWP_EVENT:
|
||
|
|
ts_status = himax_ts_operation(ts, ts_path, ts_status);
|
||
|
|
break;
|
||
|
|
case HX_REPORT_COORD_RAWDATA:
|
||
|
|
ts_status = himax_ts_operation(ts, ts_path, ts_status);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
E("%s:Path Fault! value=%d\n", __func__, ts_path);
|
||
|
|
goto END_FUNCTION;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ts_status == HX_TS_GET_DATA_FAIL)
|
||
|
|
goto GET_TOUCH_FAIL;
|
||
|
|
else
|
||
|
|
goto END_FUNCTION;
|
||
|
|
|
||
|
|
GET_TOUCH_FAIL:
|
||
|
|
I("%s: Now reset the Touch chip.\n", __func__);
|
||
|
|
#if defined(HX_RST_PIN_FUNC)
|
||
|
|
g_core_fp.fp_ic_reset(false, true);
|
||
|
|
#else
|
||
|
|
g_core_fp.fp_system_reset();
|
||
|
|
#endif
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
if (g_core_fp.fp_0f_reload_to_active)
|
||
|
|
g_core_fp.fp_0f_reload_to_active();
|
||
|
|
#endif
|
||
|
|
END_FUNCTION:
|
||
|
|
if (debug_data != NULL)
|
||
|
|
debug_data->fp_ts_dbg_func(ts, HX_FINGER_LEAVE);
|
||
|
|
|
||
|
|
}
|
||
|
|
/*end ts_work*/
|
||
|
|
enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts;
|
||
|
|
|
||
|
|
|
||
|
|
ts = container_of(timer, struct himax_ts_data, timer);
|
||
|
|
queue_work(ts->himax_wq, &ts->work);
|
||
|
|
hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
|
||
|
|
return HRTIMER_NORESTART;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
static void himax_boot_upgrade(struct work_struct *work)
|
||
|
|
{
|
||
|
|
int fw_sts = -1;
|
||
|
|
|
||
|
|
fw_sts = i_get_FW();
|
||
|
|
if (fw_sts < NO_ERR)
|
||
|
|
return;
|
||
|
|
|
||
|
|
g_core_fp.fp_bin_desc_get((unsigned char *)hxfw->data, HX1K);
|
||
|
|
|
||
|
|
if (g_boot_upgrade_flag == true) {
|
||
|
|
I("%s: Forced upgrade\n", __func__);
|
||
|
|
goto UPDATE_FW;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (himax_auto_update_check() != 0)
|
||
|
|
goto SKIP_UPDATE_FW;
|
||
|
|
|
||
|
|
UPDATE_FW:
|
||
|
|
if (i_update_FW() <= 0)
|
||
|
|
E("%s: Update FW fail\n", __func__);
|
||
|
|
else
|
||
|
|
I("%s: Update FW success\n", __func__);
|
||
|
|
|
||
|
|
SKIP_UPDATE_FW:
|
||
|
|
if (fw_sts == NO_ERR)
|
||
|
|
release_firmware(hxfw);
|
||
|
|
hxfw = NULL;
|
||
|
|
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if !defined(HX_ZERO_FLASH)
|
||
|
|
static int hx_chk_flash_sts(void)
|
||
|
|
{
|
||
|
|
int rslt = 0;
|
||
|
|
|
||
|
|
I("%s: Entering\n", __func__);
|
||
|
|
|
||
|
|
rslt = (!g_core_fp.fp_calculateChecksum(false, FW_SIZE_128k));
|
||
|
|
/*avoid the FW is full of zero*/
|
||
|
|
rslt |= g_core_fp.fp_flash_lastdata_check(FW_SIZE_128k);
|
||
|
|
|
||
|
|
return rslt;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_CONFIG_FB) || defined(HX_CONFIG_DRM)
|
||
|
|
static void himax_fb_register(struct work_struct *work)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
|
||
|
|
struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
|
||
|
|
work_att.work);
|
||
|
|
|
||
|
|
I("%s in\n", __func__);
|
||
|
|
#if defined(HX_CONFIG_FB)
|
||
|
|
ts->fb_notif.notifier_call = fb_notifier_callback;
|
||
|
|
ret = fb_register_client(&ts->fb_notif);
|
||
|
|
#elif defined(HX_CONFIG_DRM)
|
||
|
|
#if defined(__HIMAX_MOD__)
|
||
|
|
hx_msm_drm_register_client =
|
||
|
|
(void *)kallsyms_lookup_name("msm_drm_register_client");
|
||
|
|
if (hx_msm_drm_register_client != NULL) {
|
||
|
|
ts->fb_notif.notifier_call = drm_notifier_callback;
|
||
|
|
ret = hx_msm_drm_register_client(&ts->fb_notif);
|
||
|
|
} else
|
||
|
|
E("hx_msm_drm_register_client is NULL\n");
|
||
|
|
#else
|
||
|
|
ts->fb_notif.notifier_call = drm_notifier_callback;
|
||
|
|
ret = msm_drm_register_client(&ts->fb_notif);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
if (ret)
|
||
|
|
E("Unable to register fb_notifier: %d\n", ret);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_CONTAINER_SPEED_UP)
|
||
|
|
static void himax_resume_work_func(struct work_struct *work)
|
||
|
|
{
|
||
|
|
himax_chip_common_resume(private_ts);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
int himax_chip_common_init(void)
|
||
|
|
{
|
||
|
|
|
||
|
|
int i = 0, ret = 0, idx = 0;
|
||
|
|
int err = PROBE_FAIL;
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
struct himax_i2c_platform_data *pdata;
|
||
|
|
struct himax_chip_entry *entry;
|
||
|
|
|
||
|
|
I("Prepare kernel fp\n");
|
||
|
|
kp_getname_kernel = (void *)kallsyms_lookup_name("getname_kernel");
|
||
|
|
if (!kp_getname_kernel) {
|
||
|
|
E("prepare kp_getname_kernel failed!\n");
|
||
|
|
/*goto err_xfer_buff_fail;*/
|
||
|
|
}
|
||
|
|
kp_file_open_name = (void *)kallsyms_lookup_name("file_open_name");
|
||
|
|
if (!kp_file_open_name) {
|
||
|
|
E("prepare kp_file_open_name failed!\n");
|
||
|
|
goto err_xfer_buff_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(__EMBEDDED_FW__)
|
||
|
|
g_embedded_fw.size = (size_t)_binary___Himax_firmware_bin_end -
|
||
|
|
(size_t)_binary___Himax_firmware_bin_start;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ts->xfer_buff = devm_kzalloc(ts->dev, 128 * sizeof(uint8_t),
|
||
|
|
GFP_KERNEL);
|
||
|
|
if (ts->xfer_buff == NULL) {
|
||
|
|
err = -ENOMEM;
|
||
|
|
goto err_xfer_buff_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
I("PDATA START\n");
|
||
|
|
pdata = kzalloc(sizeof(struct himax_i2c_platform_data), GFP_KERNEL);
|
||
|
|
|
||
|
|
if (pdata == NULL) { /*Allocate Platform data space*/
|
||
|
|
err = -ENOMEM;
|
||
|
|
goto err_dt_platform_data_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
I("ic_data START\n");
|
||
|
|
ic_data = kzalloc(sizeof(struct himax_ic_data), GFP_KERNEL);
|
||
|
|
if (ic_data == NULL) { /*Allocate IC data space*/
|
||
|
|
err = -ENOMEM;
|
||
|
|
goto err_dt_ic_data_fail;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* allocate report data */
|
||
|
|
hx_touch_data = kzalloc(sizeof(struct himax_report_data), GFP_KERNEL);
|
||
|
|
if (hx_touch_data == NULL) {
|
||
|
|
err = -ENOMEM;
|
||
|
|
goto err_alloc_touch_data_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
ts->pdata = pdata;
|
||
|
|
|
||
|
|
if (himax_parse_dt(ts, pdata) < 0) {
|
||
|
|
I(" pdata is NULL for DT\n");
|
||
|
|
goto err_alloc_dt_pdata_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pdata->virtual_key)
|
||
|
|
ts->button = pdata->virtual_key;
|
||
|
|
|
||
|
|
#if defined(HX_RST_PIN_FUNC)
|
||
|
|
ts->rst_gpio = pdata->gpio_reset;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
himax_gpio_power_config(pdata);
|
||
|
|
|
||
|
|
#if !defined(CONFIG_OF)
|
||
|
|
if (pdata->power) {
|
||
|
|
ret = pdata->power(1);
|
||
|
|
|
||
|
|
if (ret < 0) {
|
||
|
|
E("%s: power on failed\n", __func__);
|
||
|
|
goto err_power_failed;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(CONFIG_OF)
|
||
|
|
ts->power = pdata->power;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
g_hx_chip_inited = 0;
|
||
|
|
idx = himax_get_ksym_idx();
|
||
|
|
if (idx >= 0) {
|
||
|
|
if (isEmpty(idx) != 0) {
|
||
|
|
I("%s: no chip registered, please insmod ic.ko!\n",
|
||
|
|
__func__);
|
||
|
|
goto error_ic_detect_failed;
|
||
|
|
}
|
||
|
|
entry = get_chip_entry_by_index(idx);
|
||
|
|
|
||
|
|
for (i = 0; i < entry->hx_ic_dt_num; i++) {
|
||
|
|
if (entry->core_chip_dt[i].fp_chip_detect != NULL) {
|
||
|
|
if (entry->core_chip_dt[i].fp_chip_detect()) {
|
||
|
|
I("%s: chip found! list_num=%d\n",
|
||
|
|
__func__, i);
|
||
|
|
goto found_hx_chip;
|
||
|
|
} else {
|
||
|
|
I("%s:num=%d,chip NOT found! go Next\n",
|
||
|
|
__func__, i);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
I("%s: No available chip exist!\n", __func__);
|
||
|
|
goto error_ic_detect_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (i == entry->hx_ic_dt_num) {
|
||
|
|
E("%s: chip detect failed!\n", __func__);
|
||
|
|
goto error_ic_detect_failed;
|
||
|
|
}
|
||
|
|
private_ts->notouch_frame = 0;
|
||
|
|
private_ts->ic_notouch_frame = 0;
|
||
|
|
found_hx_chip:
|
||
|
|
if (g_core_fp.fp_chip_init != NULL) {
|
||
|
|
g_core_fp.fp_chip_init();
|
||
|
|
} else {
|
||
|
|
E("%s: function point of chip_init is NULL!\n", __func__);
|
||
|
|
goto error_ic_detect_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_ZERO_FLASH)
|
||
|
|
g_boot_upgrade_flag = 1;
|
||
|
|
#else
|
||
|
|
if (hx_chk_flash_sts() == 1) {
|
||
|
|
E("%s: check flash fail, please upgrade FW\n", __func__);
|
||
|
|
#if defined(HX_BOOT_UPGRADE)
|
||
|
|
g_boot_upgrade_flag = 1;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_ZERO_FLASH) || defined(HX_BOOT_UPGRADE)
|
||
|
|
if (!g_boot_upgrade_flag) {
|
||
|
|
#endif
|
||
|
|
g_core_fp.fp_power_on_init();
|
||
|
|
// g_core_fp.fp_power_on_init(NULL);
|
||
|
|
g_core_fp.fp_read_FW_ver();
|
||
|
|
#if defined(HX_ZERO_FLASH) || defined(HX_BOOT_UPGRADE)
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
g_core_fp.fp_touch_information();
|
||
|
|
g_core_fp.fp_calc_touch_data_size();
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
ts->himax_boot_upgrade_wq =
|
||
|
|
create_singlethread_workqueue("HX_boot_upgrade");
|
||
|
|
if (!ts->himax_boot_upgrade_wq) {
|
||
|
|
E("allocate himax_boot_upgrade_wq failed\n");
|
||
|
|
err = -ENOMEM;
|
||
|
|
goto err_boot_upgrade_wq_failed;
|
||
|
|
}
|
||
|
|
INIT_DELAYED_WORK(&ts->work_boot_upgrade, himax_boot_upgrade);
|
||
|
|
queue_delayed_work(ts->himax_boot_upgrade_wq, &ts->work_boot_upgrade,
|
||
|
|
msecs_to_jiffies(2000));
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_CONTAINER_SPEED_UP)
|
||
|
|
ts->ts_int_workqueue =
|
||
|
|
create_singlethread_workqueue("himax_ts_resume_wq");
|
||
|
|
if (!ts->ts_int_workqueue) {
|
||
|
|
E("%s: create ts_resume workqueue failed\n", __func__);
|
||
|
|
goto err_create_ts_resume_wq_failed;
|
||
|
|
}
|
||
|
|
INIT_DELAYED_WORK(&ts->ts_int_work, himax_resume_work_func);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/*Himax Power On and Load Config*/
|
||
|
|
/* if (himax_loadSensorConfig(pdata)) {
|
||
|
|
* E("%s: Load Sesnsor configuration failed, unload driver.\n",
|
||
|
|
* __func__);
|
||
|
|
* goto err_detect_failed;
|
||
|
|
* }
|
||
|
|
*/
|
||
|
|
|
||
|
|
#if defined(CONFIG_OF)
|
||
|
|
ts->pdata->abs_pressure_min = 0;
|
||
|
|
ts->pdata->abs_pressure_max = 200;
|
||
|
|
ts->pdata->abs_width_min = 0;
|
||
|
|
ts->pdata->abs_width_max = 200;
|
||
|
|
pdata->cable_config[0] = 0xF0;
|
||
|
|
pdata->cable_config[1] = 0x00;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
ts->suspended = false;
|
||
|
|
|
||
|
|
#if defined(HX_USB_DETECT_GLOBAL)
|
||
|
|
ts->usb_connected = 0x00;
|
||
|
|
ts->cable_config = pdata->cable_config;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_PROTOCOL_A)
|
||
|
|
ts->protocol_type = PROTOCOL_TYPE_A;
|
||
|
|
#else
|
||
|
|
ts->protocol_type = PROTOCOL_TYPE_B;
|
||
|
|
#endif
|
||
|
|
I("%s: Use Protocol Type %c\n", __func__,
|
||
|
|
ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B');
|
||
|
|
|
||
|
|
ret = himax_input_register(ts);
|
||
|
|
if (ret) {
|
||
|
|
E("%s: Unable to register %s input device\n",
|
||
|
|
__func__, ts->input_dev->name);
|
||
|
|
goto err_input_register_device_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
spin_lock_init(&ts->irq_lock);
|
||
|
|
ts->initialized = true;
|
||
|
|
|
||
|
|
#if defined(HX_CONFIG_FB) || defined(HX_CONFIG_DRM)
|
||
|
|
ts->himax_att_wq = create_singlethread_workqueue("HMX_ATT_request");
|
||
|
|
|
||
|
|
if (!ts->himax_att_wq) {
|
||
|
|
E(" allocate himax_att_wq failed\n");
|
||
|
|
err = -ENOMEM;
|
||
|
|
goto err_get_intr_bit_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
INIT_DELAYED_WORK(&ts->work_att, himax_fb_register);
|
||
|
|
queue_delayed_work(ts->himax_att_wq, &ts->work_att,
|
||
|
|
msecs_to_jiffies(15000));
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
ts->SMWP_enable = 0;
|
||
|
|
wakeup_source_init(&ts->ts_SMWP_wake_lock, HIMAX_common_NAME);
|
||
|
|
#endif
|
||
|
|
#if defined(HX_HIGH_SENSE)
|
||
|
|
ts->HSEN_enable = 0;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (himax_common_proc_init()) {
|
||
|
|
E(" %s: himax_common proc_init failed!\n", __func__);
|
||
|
|
goto err_creat_proc_file_failed;
|
||
|
|
}
|
||
|
|
|
||
|
|
himax_ts_register_interrupt();
|
||
|
|
|
||
|
|
#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
|
||
|
|
if (himax_debug_init())
|
||
|
|
E(" %s: debug initial failed!\n", __func__);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
if (g_boot_upgrade_flag)
|
||
|
|
himax_int_enable(0);
|
||
|
|
#endif
|
||
|
|
g_hx_chip_inited = true;
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
err_creat_proc_file_failed:
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
wakeup_source_trash(&ts->ts_SMWP_wake_lock);
|
||
|
|
#endif
|
||
|
|
#if defined(HX_CONFIG_FB) || defined(HX_CONFIG_DRM)
|
||
|
|
cancel_delayed_work_sync(&ts->work_att);
|
||
|
|
destroy_workqueue(ts->himax_att_wq);
|
||
|
|
err_get_intr_bit_failed:
|
||
|
|
#endif
|
||
|
|
err_input_register_device_failed:
|
||
|
|
input_free_device(ts->input_dev);
|
||
|
|
/*err_detect_failed:*/
|
||
|
|
|
||
|
|
#if defined(HX_CONTAINER_SPEED_UP)
|
||
|
|
cancel_delayed_work_sync(&ts->ts_int_work);
|
||
|
|
destroy_workqueue(ts->ts_int_workqueue);
|
||
|
|
err_create_ts_resume_wq_failed:
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
cancel_delayed_work_sync(&ts->work_boot_upgrade);
|
||
|
|
destroy_workqueue(ts->himax_boot_upgrade_wq);
|
||
|
|
err_boot_upgrade_wq_failed:
|
||
|
|
#endif
|
||
|
|
|
||
|
|
error_ic_detect_failed:
|
||
|
|
himax_gpio_power_deconfig(pdata);
|
||
|
|
#if !defined(CONFIG_OF)
|
||
|
|
err_power_failed:
|
||
|
|
#endif
|
||
|
|
err_alloc_dt_pdata_failed:
|
||
|
|
kfree(hx_touch_data);
|
||
|
|
hx_touch_data = NULL;
|
||
|
|
err_alloc_touch_data_failed:
|
||
|
|
kfree(ic_data);
|
||
|
|
ic_data = NULL;
|
||
|
|
err_dt_ic_data_fail:
|
||
|
|
kfree(pdata);
|
||
|
|
pdata = NULL;
|
||
|
|
err_dt_platform_data_fail:
|
||
|
|
devm_kfree(ts->dev, ts->xfer_buff);
|
||
|
|
ts->xfer_buff = NULL;
|
||
|
|
err_xfer_buff_fail:
|
||
|
|
probe_fail_flag = 1;
|
||
|
|
return err;
|
||
|
|
}
|
||
|
|
|
||
|
|
void himax_chip_common_deinit(void)
|
||
|
|
{
|
||
|
|
struct himax_ts_data *ts = private_ts;
|
||
|
|
|
||
|
|
himax_ts_unregister_interrupt();
|
||
|
|
|
||
|
|
#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT)
|
||
|
|
himax_inspect_data_clear();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
|
||
|
|
himax_debug_remove();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
himax_common_proc_deinit();
|
||
|
|
himax_report_data_deinit();
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
wakeup_source_trash(&ts->ts_SMWP_wake_lock);
|
||
|
|
#endif
|
||
|
|
#if defined(HX_CONFIG_FB)
|
||
|
|
if (fb_unregister_client(&ts->fb_notif))
|
||
|
|
E("Error occurred while unregistering fb_notifier.\n");
|
||
|
|
cancel_delayed_work_sync(&ts->work_att);
|
||
|
|
destroy_workqueue(ts->himax_att_wq);
|
||
|
|
#elif defined(HX_CONFIG_DRM)
|
||
|
|
#if defined(__HIMAX_MOD__)
|
||
|
|
hx_msm_drm_unregister_client =
|
||
|
|
(void *)kallsyms_lookup_name("msm_drm_unregister_client");
|
||
|
|
if (hx_msm_drm_unregister_client != NULL) {
|
||
|
|
if (hx_msm_drm_unregister_client(&ts->fb_notif))
|
||
|
|
E("Error occurred while unregistering drm_notifier.\n");
|
||
|
|
} else
|
||
|
|
E("hx_msm_drm_unregister_client is NULL\n");
|
||
|
|
#else
|
||
|
|
if (msm_drm_unregister_client(&ts->fb_notif))
|
||
|
|
E("Error occurred while unregistering drm_notifier.\n");
|
||
|
|
#endif
|
||
|
|
cancel_delayed_work_sync(&ts->work_att);
|
||
|
|
destroy_workqueue(ts->himax_att_wq);
|
||
|
|
#endif
|
||
|
|
input_free_device(ts->input_dev);
|
||
|
|
#if defined(HX_CONTAINER_SPEED_UP)
|
||
|
|
cancel_delayed_work_sync(&ts->ts_int_work);
|
||
|
|
destroy_workqueue(ts->ts_int_workqueue);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_BOOT_UPGRADE) || defined(HX_ZERO_FLASH)
|
||
|
|
cancel_delayed_work_sync(&ts->work_boot_upgrade);
|
||
|
|
destroy_workqueue(ts->himax_boot_upgrade_wq);
|
||
|
|
#endif
|
||
|
|
himax_gpio_power_deconfig(ts->pdata);
|
||
|
|
if (himax_mcu_cmd_struct_free)
|
||
|
|
himax_mcu_cmd_struct_free();
|
||
|
|
|
||
|
|
kfree(hx_touch_data);
|
||
|
|
hx_touch_data = NULL;
|
||
|
|
kfree(ic_data);
|
||
|
|
ic_data = NULL;
|
||
|
|
kfree(ts->pdata->virtual_key);
|
||
|
|
ts->pdata->virtual_key = NULL;
|
||
|
|
devm_kfree(ts->dev, ts->xfer_buff);
|
||
|
|
ts->xfer_buff = NULL;
|
||
|
|
kfree(ts->pdata);
|
||
|
|
ts->pdata = NULL;
|
||
|
|
kfree(ts);
|
||
|
|
ts = NULL;
|
||
|
|
probe_fail_flag = 0;
|
||
|
|
|
||
|
|
I("%s: Common section deinited!\n", __func__);
|
||
|
|
}
|
||
|
|
|
||
|
|
int himax_chip_common_suspend(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
if (ts->suspended) {
|
||
|
|
I("%s: Already suspended. Skipped.\n", __func__);
|
||
|
|
goto END;
|
||
|
|
} else {
|
||
|
|
ts->suspended = true;
|
||
|
|
I("%s: enter\n", __func__);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (debug_data != NULL && debug_data->flash_dump_going == true) {
|
||
|
|
I("[himax] %s: Flash dump is going, reject suspend\n",
|
||
|
|
__func__);
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_SMART_WAKEUP)\
|
||
|
|
|| defined(HX_HIGH_SENSE)\
|
||
|
|
|| defined(HX_USB_DETECT_GLOBAL)
|
||
|
|
#if !defined(HX_RESUME_SEND_CMD)
|
||
|
|
g_core_fp.fp_resend_cmd_func(ts->suspended);
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#if defined(HX_SMART_WAKEUP)
|
||
|
|
|
||
|
|
if (ts->SMWP_enable) {
|
||
|
|
#if 0//defined(HX_CODE_OVERLAY)
|
||
|
|
if (ts->in_self_test == 0)
|
||
|
|
g_core_fp.fp_0f_overlay(2, 0);
|
||
|
|
#endif
|
||
|
|
if (g_core_fp._ap_notify_fw_sus != NULL)
|
||
|
|
g_core_fp._ap_notify_fw_sus(1);
|
||
|
|
atomic_set(&ts->suspend_mode, 1);
|
||
|
|
ts->pre_finger_mask = 0;
|
||
|
|
I("[himax] %s: SMART_WAKEUP enable, reject suspend\n",
|
||
|
|
__func__);
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
himax_int_enable(0);
|
||
|
|
if (g_core_fp.fp_suspend_ic_action != NULL)
|
||
|
|
g_core_fp.fp_suspend_ic_action();
|
||
|
|
|
||
|
|
if (!ts->use_irq) {
|
||
|
|
int32_t cancel_state;
|
||
|
|
|
||
|
|
cancel_state = cancel_work_sync(&ts->work);
|
||
|
|
if (cancel_state)
|
||
|
|
himax_int_enable(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*ts->first_pressed = 0;*/
|
||
|
|
atomic_set(&ts->suspend_mode, 1);
|
||
|
|
ts->pre_finger_mask = 0;
|
||
|
|
|
||
|
|
if (ts->pdata)
|
||
|
|
if (ts->pdata->powerOff3V3 && ts->pdata->power)
|
||
|
|
ts->pdata->power(0);
|
||
|
|
|
||
|
|
END:
|
||
|
|
if (ts->in_self_test == 1)
|
||
|
|
ts->suspend_resume_done = 1;
|
||
|
|
|
||
|
|
I("%s: END\n", __func__);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int himax_chip_common_resume(struct himax_ts_data *ts)
|
||
|
|
{
|
||
|
|
#if defined(HX_RESUME_SET_FW)
|
||
|
|
int result = 0;
|
||
|
|
#endif
|
||
|
|
I("%s: enter\n", __func__);
|
||
|
|
|
||
|
|
if (ts->suspended == false) {
|
||
|
|
I("%s: It had entered resume, skip this step\n", __func__);
|
||
|
|
goto END;
|
||
|
|
} else {
|
||
|
|
ts->suspended = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if defined(HX_EXCP_RECOVERY)
|
||
|
|
/* continuous N times record, not total N times. */
|
||
|
|
g_zero_event_count = 0;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
atomic_set(&ts->suspend_mode, 0);
|
||
|
|
ts->diag_cmd = 0;
|
||
|
|
|
||
|
|
if (ts->pdata)
|
||
|
|
if (ts->pdata->powerOff3V3 && ts->pdata->power)
|
||
|
|
ts->pdata->power(1);
|
||
|
|
#if defined(HX_RST_PIN_FUNC) && defined(HX_RESUME_HW_RESET)
|
||
|
|
if (g_core_fp.fp_ic_reset != NULL)
|
||
|
|
g_core_fp.fp_ic_reset(false, false);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if defined(HX_RESUME_SET_FW)
|
||
|
|
#if defined(HX_SMART_WAKEUP) && !defined(HX_SWU_RESUME_SET_FW)
|
||
|
|
if (!ts->SMWP_enable) {
|
||
|
|
#endif
|
||
|
|
I("It will update fw after resume in zero flash mode!\n");
|
||
|
|
if (g_core_fp.fp_0f_operation_dirly != NULL) {
|
||
|
|
result = g_core_fp.fp_0f_operation_dirly();
|
||
|
|
if (result) {
|
||
|
|
E("Something wrong! Skip Update zero flash!\n");
|
||
|
|
goto ESCAPE_0F_UPDATE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// if (g_core_fp.fp_reload_disable != NULL)
|
||
|
|
// g_core_fp.fp_reload_disable(0);
|
||
|
|
// if (g_core_fp.fp_sense_on != NULL)
|
||
|
|
// g_core_fp.fp_sense_on(0x00);
|
||
|
|
#if defined(HX_SMART_WAKEUP) && !defined(HX_SWU_RESUME_SET_FW)
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
#if defined(HX_SMART_WAKEUP)\
|
||
|
|
|| defined(HX_HIGH_SENSE)\
|
||
|
|
|| defined(HX_USB_DETECT_GLOBAL)
|
||
|
|
if (g_core_fp.fp_resend_cmd_func != NULL)
|
||
|
|
g_core_fp.fp_resend_cmd_func(ts->suspended);
|
||
|
|
|
||
|
|
#if 0//defined(HX_CODE_OVERLAY) && defined(HX_SMART_WAKEUP)
|
||
|
|
if (ts->SMWP_enable && ts->in_self_test == 0)
|
||
|
|
g_core_fp.fp_0f_overlay(3, 0);
|
||
|
|
#endif
|
||
|
|
if (g_core_fp._ap_notify_fw_sus != NULL)
|
||
|
|
g_core_fp._ap_notify_fw_sus(0);
|
||
|
|
#endif
|
||
|
|
himax_report_all_leave_event(ts);
|
||
|
|
|
||
|
|
if (g_core_fp.fp_resume_ic_action != NULL)
|
||
|
|
g_core_fp.fp_resume_ic_action();
|
||
|
|
|
||
|
|
himax_int_enable(1);
|
||
|
|
#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW)
|
||
|
|
ESCAPE_0F_UPDATE:
|
||
|
|
#endif
|
||
|
|
END:
|
||
|
|
if (ts->in_self_test == 1)
|
||
|
|
ts->suspend_resume_done = 1;
|
||
|
|
|
||
|
|
I("%s: END\n", __func__);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|