diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c index 8112305adc1b..0ca5a77dd993 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c @@ -743,6 +743,10 @@ static int fts_read_parse_touchdata(struct fts_ts_data *ts_data, u8 *touch_buf) memset(touch_buf, 0xFF, FTS_MAX_TOUCH_BUF); ts_data->ta_size = ts_data->touch_size; +#ifdef FOCALTECH_SENSOR_EN + fts_read_report_fod_event(ts_data); +#endif + /*read touch data*/ ret = fts_read_touchdata(ts_data, touch_buf); if (ret < 0) { @@ -1191,6 +1195,10 @@ static int fts_input_init(struct fts_ts_data *ts_data) input_dev->id.bustype = BUS_SPI; input_dev->dev.parent = ts_data->dev; + input_dev->id.product = 0xDEAD; + input_dev->id.vendor = 0xBEEF; + input_dev->id.version = 10427; + input_set_drvdata(input_dev, ts_data); __set_bit(EV_SYN, input_dev->evbit); @@ -1205,6 +1213,11 @@ static int fts_input_init(struct fts_ts_data *ts_data) input_set_capability(input_dev, EV_KEY, pdata->keys[key_num]); } +#ifdef FOCALTECH_SENSOR_EN + input_set_capability(input_dev, EV_KEY, BTN_TRIGGER_HAPPY1); + input_set_capability(input_dev, EV_KEY, BTN_TRIGGER_HAPPY2); +#endif + #if FTS_MT_PROTOCOL_B_EN input_mt_init_slots(input_dev, pdata->max_touch_number, INPUT_MT_DIRECT); #else @@ -2379,6 +2392,20 @@ static int fts_ts_remove_entry(struct fts_ts_data *ts_data) return 0; } +#ifdef FOCALTECH_SENSOR_EN +bool fts_is_fod_resume(struct fts_ts_data *ts_data) +{ + unsigned long fod_timeout = msecs_to_jiffies(3000); + + fod_timeout += ts_data->fod_jiffies; + if (time_before(jiffies, fod_timeout)) { + return true; + } + + return false; +} +#endif + #ifndef CONFIG_INPUT_TOUCHSCREEN_MMI static int fts_ts_suspend(struct device *dev) { diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h index d714a0eab82e..ffff53ae435c 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h @@ -277,6 +277,11 @@ struct fts_ts_data { #ifdef FOCALTECH_SENSOR_EN bool wakeable; + bool fod_suspended; + unsigned char gesture_type; + int zerotap_data[1]; + int zero_enable; + unsigned long fod_jiffies; #endif u8 gsx_cmd; @@ -358,6 +363,9 @@ void fts_gesture_recovery(struct fts_ts_data *ts_data); int fts_gesture_readdata(struct fts_ts_data *ts_data, u8 *data); int fts_gesture_suspend(struct fts_ts_data *ts_data); int fts_gesture_resume(struct fts_ts_data *ts_data); +#ifdef FOCALTECH_SENSOR_EN +void fts_read_report_fod_event(struct fts_ts_data *ts_data); +#endif /* Apk and functions */ int fts_create_apk_debug_channel(struct fts_ts_data *); @@ -407,4 +415,7 @@ int fts_ex_mode_recovery(struct fts_ts_data *ts_data); void fts_irq_disable(void); void fts_irq_enable(void); int fts_power_source_ctrl(struct fts_ts_data *ts_data, int enable); +#ifdef FOCALTECH_SENSOR_EN +bool fts_is_fod_resume(struct fts_ts_data *ts_data); +#endif #endif /* __LINUX_FOCALTECH_CORE_H__ */ diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_gesture.c b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_gesture.c index 54584269aa21..4a8f49bd46be 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_gesture.c +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_gesture.c @@ -257,6 +257,122 @@ static int fts_create_gesture_sysfs(struct device *dev) return 0; } +#ifdef FOCALTECH_SENSOR_EN +void fts_read_report_fod_event(struct fts_ts_data *ts_data) +{ + u8 cmd = 0xE1; + u8 fod_data[9] = {0}; + u16 fod_x = 0; + u16 fod_y = 0; + u8 fod_id = 0; + u8 fod_down = 0; + int ret = 0; + static bool last_fod_down = false; + struct gesture_event_data event; + int fod_down_interval = 0; + static unsigned long start = 0; + + ret = fts_read(&cmd, 1, fod_data, 9); + if (ret < 0) + { + FTS_ERROR("read fod data fail"); + return; + } + fod_id = fod_data[1]; + fod_x = (fod_data[4] << 8) + fod_data[5]; + fod_y = (fod_data[6] << 8) + fod_data[7]; + fod_down = fod_data[8]; //1 up, 0 down + + FTS_INFO("fod_id = %02x, fod_down = %d", fod_id, fod_down); + if (fod_id != 0x26) + { + return; + } + + if (ts_data->fod_suspended) + { + if (fod_down == 0) + { + fod_down_interval = (int)jiffies_to_msecs(jiffies - start); + event.evcode = 2; + event.evdata.x = fod_x; + event.evdata.y = fod_y; + FTS_INFO("Get FOD-DOWN gesture:%d interval:%d", ts_data->zerotap_data[0], fod_down_interval); + if (fod_down_interval > 2000) + ts_data->zerotap_data[0] = 0; + + if (fod_down_interval > 0 && fod_down_interval < 250 && ts_data->zerotap_data[0]) + { + return; + } + start = jiffies; + ts_data->fod_jiffies = jiffies; + if (ts_data->zerotap_data[0] > 6) + { + FTS_INFO("FOD-DOWN too many times %d", ts_data->zerotap_data[0]); + } + else + { + ret = fts_data->imports->report_gesture(&event); + FTS_INFO("report fod down event %d", ts_data->zerotap_data[0]); + if (!ret) + { +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_timeout(&gesture_wakelock, msecs_to_jiffies(3000)); +#else + PM_WAKEUP_EVENT(gesture_wakelock, 3000); +#endif + } + ts_data->zerotap_data[0]++; + } + } + else if (fod_down == 1) + { + FTS_INFO("Get FOD-UP gesture"); + event.evcode = 3; + event.evdata.x = 0; + event.evdata.y = 0; + ret = fts_data->imports->report_gesture(&event); + if (!ret) + { +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_timeout(&gesture_wakelock, msecs_to_jiffies(3000)); +#else + PM_WAKEUP_EVENT(gesture_wakelock, 3000); +#endif + } + ts_data->zerotap_data[0] = 0; + } + } + else + { + if (fod_down == 1) + { + FTS_INFO("Get FOD-UP normal"); + input_report_key(ts_data->input_dev, BTN_TRIGGER_HAPPY2, 1); + input_sync(ts_data->input_dev); + input_report_key(ts_data->input_dev, BTN_TRIGGER_HAPPY2, 0); + input_sync(ts_data->input_dev); + FTS_INFO("report BTN_TRIGGER_HAPPY2"); + last_fod_down = false; + } + else if (fod_down == 0) + { + FTS_INFO("Get FOD-DOWN normal"); + if (last_fod_down == false) + { + input_report_key(ts_data->input_dev, BTN_TRIGGER_HAPPY1, 1); + input_sync(ts_data->input_dev); + input_report_key(ts_data->input_dev, BTN_TRIGGER_HAPPY1, 0); + input_sync(ts_data->input_dev); + last_fod_down = true; + FTS_INFO("report BTN_TRIGGER_HAPPY1"); + } + } + } +} +#endif + static void fts_gesture_report(struct input_dev *input_dev, int gesture_id) { int gesture; @@ -474,6 +590,12 @@ int fts_gesture_suspend(struct fts_ts_data *ts_data) #else fts_write_reg(0xD1, 0xFF); #endif + +#ifdef FOCALTECH_SENSOR_EN + if(fts_data->zero_enable) { + fts_write_reg(0xCF, 0x02); + } +#endif fts_write_reg(0xD2, 0xFF); fts_write_reg(0xD5, 0xFF); fts_write_reg(0xD6, 0xFF); diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c index b3ac33002efa..0cbdfa8e5b5e 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c @@ -258,6 +258,9 @@ static int fts_mmi_panel_state(struct device *dev, GET_TS_DATA(dev); pdata = ts_data->pdata; +#ifdef FOCALTECH_SENSOR_EN + ts_data->zero_enable = 0; +#endif switch (to) { case TS_MMI_PM_DEEPSLEEP: @@ -281,6 +284,12 @@ static int fts_mmi_panel_state(struct device *dev, gesture_command |= (1 << 4); FTS_INFO("Enable GESTURE_CLI_DOUBLE command: %02x", gesture_command); } + if (gesture_type & TS_MMI_GESTURE_ZERO) { +#ifdef FOCALTECH_SENSOR_EN + ts_data->zero_enable = 1; +#endif + FTS_INFO("Enable GESTURE_CLI_ZERO command: %02x", gesture_command); + } FTS_INFO("CLI GESTURE SWITCH command: %02x", gesture_command); ts_data->gsx_cmd = gesture_command; @@ -340,9 +349,18 @@ static int fts_mmi_post_resume(struct device *dev) GET_TS_DATA(dev); +#ifdef FOCALTECH_SENSOR_EN + ts_data->fod_suspended = false; +#endif if (ts_data->gesture_support == true) { +#ifdef FOCALTECH_SENSOR_EN + if(!fts_is_fod_resume(ts_data)) { +#endif FTS_INFO("Reset IC in resume"); fts_reset_proc(200); +#ifdef FOCALTECH_SENSOR_EN + } +#endif } fts_tp_state_recovery(ts_data); @@ -354,6 +372,8 @@ static int fts_mmi_post_resume(struct device *dev) #if FTS_GESTURE_EN #ifdef FOCALTECH_SENSOR_EN if (ts_data->wakeable) { + fts_write_reg(0xCF, 0x02); + FTS_INFO("Enable fod report for normal mode in %s", __func__); #endif if (fts_gesture_resume(ts_data) == 0) { #ifdef FOCALTECH_SENSOR_EN @@ -430,6 +450,7 @@ static int fts_mmi_post_suspend(struct device *dev) fts_release_all_finger(); #ifdef FOCALTECH_SENSOR_EN } + ts_data->fod_suspended = true; #endif ts_data->suspended = true;