mako: touch: use MT protocol type B
- not applied to hard key function, so removed hard key stuff
- jitter and accuracy filter function also changed but not used at the moment
- corrected some wrong error handling in touch_probe and synaptics_ts_probe
Change-Id: I1af3032612cdedbfac9da9c5df17eeb861344226
diff --git a/drivers/input/touchscreen/lge_touch_core.c b/drivers/input/touchscreen/lge_touch_core.c
index d2c0cbf..58a3c4b 100644
--- a/drivers/input/touchscreen/lge_touch_core.c
+++ b/drivers/input/touchscreen/lge_touch_core.c
@@ -19,7 +19,7 @@
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
-#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -73,36 +73,6 @@
#define MAX_RETRY_COUNT 3
#define MAX_GHOST_CHECK_COUNT 3
-#define INPUT_REPORT_ABS(_d_,_c_) \
-do { \
- input_report_abs(_d_, ABS_MT_POSITION_X, (_c_)->x_position); \
- input_report_abs(_d_, ABS_MT_POSITION_Y, (_c_)->y_position); \
- if (is_pressure) \
- input_report_abs(_d_, ABS_MT_PRESSURE, (_c_)->pressure); \
- if (is_width) { \
- input_report_abs(_d_, ABS_MT_WIDTH_MAJOR, \
- (_c_)->width_major); \
- input_report_abs(_d_, ABS_MT_WIDTH_MINOR, \
- (_c_)->width_minor); \
- input_report_abs(_d_, ABS_MT_ORIENTATION, \
- (_c_)->width_orientation); \
- } \
- if (is_id) \
- input_report_abs(_d_, ABS_MT_TRACKING_ID, (_c_)->id); \
- input_mt_sync(_d_); \
- \
- if (unlikely(touch_debug_mask & DEBUG_ABS)) \
- TOUCH_INFO_MSG("<%d> pos[%4d,%4d] w_m[%2d] w_n[%2d] " \
- "w_o[%2d] p[%3d]\n", \
- is_id ? (_c_)->id : 0, \
- (_c_)->x_position, \
- (_c_)->y_position, \
- is_width ? (_c_)->width_major: 0, \
- is_width ? (_c_)->width_minor: 0, \
- is_width ? (_c_)->width_orientation: 0, \
- is_pressure ? (_c_)->pressure : 0); \
-} while(0)
-
#if defined(CONFIG_HAS_EARLYSUSPEND)
static void touch_early_suspend(struct early_suspend *h);
static void touch_late_resume(struct early_suspend *h);
@@ -274,54 +244,16 @@
*/
static void release_all_ts_event(struct lge_touch_data *ts)
{
- if (ts->pdata->role->key_type == TOUCH_HARD_KEY) {
- if (ts->ts_data.prev_total_num) {
- input_mt_sync(ts->input_dev);
- if (likely(touch_debug_mask &
- (DEBUG_ABS | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("touch finger position released\n");
- }
+ int id;
- if (ts->ts_data.prev_button.state == BUTTON_PRESSED) {
- input_report_key(ts->input_dev,
- ts->ts_data.prev_button.key_code,
- BUTTON_RELEASED);
+ for (id = 0; id < MAX_FINGER; id++) {
+ if (!ts->ts_data.curr_data[id].state)
+ continue;
- if (likely(touch_debug_mask &
- (DEBUG_BUTTON | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("Touch KEY[%d] is released\n",
- ts->ts_data.prev_button.key_code);
- }
+ input_mt_slot(ts->input_dev, id);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+ ts->ts_data.curr_data[id].state = 0;
}
- else if (ts->pdata->role->key_type == VIRTUAL_KEY) {
- if (ts->ts_data.prev_total_num) {
- input_mt_sync(ts->input_dev);
-
- if (likely(touch_debug_mask &
- (DEBUG_ABS | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("touch finger position released\n");
- }
- }
- else if (ts->pdata->role->key_type == TOUCH_SOFT_KEY) {
- if (ts->ts_data.state == ABS_PRESS) {
- input_mt_sync(ts->input_dev);
-
- if (likely(touch_debug_mask &
- (DEBUG_ABS | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("touch finger position released\n");
- } else if (ts->ts_data.state == BUTTON_PRESS) {
- input_report_key(ts->input_dev,
- ts->ts_data.prev_button.key_code,
- BUTTON_RELEASED);
-
- if (likely(touch_debug_mask &
- (DEBUG_BUTTON | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("Touch KEY[%d] is released\n",
- ts->ts_data.prev_button.key_code);
- }
- }
-
- ts->ts_data.prev_total_num = 0;
input_sync(ts->input_dev);
}
@@ -579,8 +511,7 @@
ts->gf_ctrl.count = 0;
}
else if (ts->ts_data.total_num == 1 &&
- ts->ts_data.curr_button.state == 0 &&
- ts->ts_data.curr_data[0].id == 0) {
+ ts->ts_data.curr_button.state == 0) {
ts->gf_ctrl.count++;
if (unlikely(touch_debug_mask & DEBUG_GHOST))
TOUCH_INFO_MSG("ghost_stage_1: int_count[%d/%d]\n",
@@ -668,8 +599,7 @@
if (ts->accuracy_filter.finish_filter == 1 &&
(ts->accuracy_filter.his_data.count >
ts->accuracy_filter.touch_max_count ||
- ts->ts_data.total_num != 1 ||
- ts->ts_data.curr_data[0].id != 0)) {
+ ts->ts_data.total_num != 1)) {
ts->accuracy_filter.finish_filter = 0;
ts->accuracy_filter.his_data.count = 0;
}
@@ -709,8 +639,7 @@
}
/* if 'delta' > delta_max or id != 0, remove the modify-value. */
- if (ts->ts_data.curr_data[0].id != 0 ||
- (ts->accuracy_filter.his_data.count != 1 &&
+ if ((ts->accuracy_filter.his_data.count != 1 &&
(jitter_abs(delta_x) > ts->accuracy_filter.delta_max ||
jitter_abs(delta_y) > ts->accuracy_filter.delta_max))) {
ts->accuracy_filter.his_data.mod_x = 0;
@@ -721,19 +650,17 @@
if (ts->accuracy_filter.finish_filter == 0
&& ts->accuracy_filter.his_data.count == 0
&& ts->ts_data.total_num == 1
- && ts->accuracy_filter.his_data.prev_total_num == 0
- && ts->ts_data.curr_data[0].id == 0) {
+ && ts->accuracy_filter.his_data.prev_total_num == 0) {
ts->accuracy_filter.finish_filter = 1;
memset(&ts->accuracy_filter.his_data, 0,
sizeof(ts->accuracy_filter.his_data));
}
if (unlikely(touch_debug_mask & DEBUG_ACCURACY)) {
- TOUCH_INFO_MSG("AccuracyFilter: <%d> pos[%4d,%4d] "
+ TOUCH_INFO_MSG("AccuracyFilter: <0> pos[%4d,%4d] "
"new[%4d,%4d] his[%4d,%4d] delta[%3d,%3d] "
"mod[%3d,%3d] p[%d,%3d,%3d] axis[%2d,%2d] "
"count[%2d/%2d] total_num[%d,%d] finish[%d]\n",
- ts->ts_data.curr_data[0].id,
ts->ts_data.curr_data[0].x_position,
ts->ts_data.curr_data[0].y_position,
check_boundary((int)ts->ts_data.curr_data[0].x_position + ts->accuracy_filter.his_data.mod_x, ts->pdata->caps->x_max),
@@ -773,7 +700,7 @@
static int jitter_filter_func(struct lge_touch_data *ts)
{
- int i = 0;
+ int id;
int jitter_count = 0;
u16 new_id_mask = 0;
u16 bit_mask = 0;
@@ -783,9 +710,13 @@
if (ts->accuracy_filter.finish_filter)
return 0;
- for (i = 0; i < ts->ts_data.total_num; i++) {
- u16 id = ts->ts_data.curr_data[i].id;
- u16 width = ts->ts_data.curr_data[i].width_major;
+ for (id = 0; id < MAX_FINGER; id++) {
+ u16 width;
+
+ if (!ts->ts_data.curr_data[id].state)
+ continue;
+
+ width = ts->ts_data.curr_data[id].width_major;
new_id_mask |= (1 << id);
if (ts->jitter_filter.id_mask & (1 << id)) {
@@ -794,34 +725,34 @@
int adjust_x, adjust_y;
if (ts->jitter_filter.adjust_margin > 0) {
- adjust_x = (int)ts->ts_data.curr_data[i].x_position - (int)ts->jitter_filter.his_data[id].x;
- adjust_y = (int)ts->ts_data.curr_data[i].y_position - (int)ts->jitter_filter.his_data[id].y;
+ adjust_x = (int)ts->ts_data.curr_data[id].x_position - (int)ts->jitter_filter.his_data[id].x;
+ adjust_y = (int)ts->ts_data.curr_data[id].y_position - (int)ts->jitter_filter.his_data[id].y;
if (jitter_abs(adjust_x) > ts->jitter_filter.adjust_margin) {
- adjust_x = (int)ts->ts_data.curr_data[i].x_position + (adjust_x >> 2);
- ts->ts_data.curr_data[i].x_position =
+ adjust_x = (int)ts->ts_data.curr_data[id].x_position + (adjust_x >> 2);
+ ts->ts_data.curr_data[id].x_position =
check_boundary(adjust_x,
ts->pdata->caps->x_max);
}
if (jitter_abs(adjust_y) > ts->jitter_filter.adjust_margin) {
- adjust_y = (int)ts->ts_data.curr_data[i].y_position + (adjust_y >> 2);
- ts->ts_data.curr_data[i].y_position =
+ adjust_y = (int)ts->ts_data.curr_data[id].y_position + (adjust_y >> 2);
+ ts->ts_data.curr_data[id].y_position =
check_boundary(adjust_y,
ts->pdata->caps->y_max);
}
}
- ts->ts_data.curr_data[i].x_position =
- (ts->ts_data.curr_data[i].x_position +
+ ts->ts_data.curr_data[id].x_position =
+ (ts->ts_data.curr_data[id].x_position +
ts->jitter_filter.his_data[id].x) >> 1;
- ts->ts_data.curr_data[i].y_position =
- (ts->ts_data.curr_data[i].y_position +
+ ts->ts_data.curr_data[id].y_position =
+ (ts->ts_data.curr_data[id].y_position +
ts->jitter_filter.his_data[id].y) >> 1;
- delta_x = (int)ts->ts_data.curr_data[i].x_position -
+ delta_x = (int)ts->ts_data.curr_data[id].x_position -
(int)ts->jitter_filter.his_data[id].x;
- delta_y = (int)ts->ts_data.curr_data[i].y_position -
+ delta_y = (int)ts->ts_data.curr_data[id].y_position -
(int)ts->jitter_filter.his_data[id].y;
ts->jitter_filter.his_data[id].delta_x = delta_x * curr_ratio + ((ts->jitter_filter.his_data[id].delta_x * (128 - curr_ratio)) >> 7);
@@ -831,8 +762,8 @@
TOUCH_INFO_MSG("JitterFilter: <%d> pos[%d,%d] "
"h_pos[%d,%d] delta[%d,%d] "
"h_delta[%d,%d] j_fil[%d]\n",
- id, ts->ts_data.curr_data[i].x_position,
- ts->ts_data.curr_data[i].y_position,
+ id, ts->ts_data.curr_data[id].x_position,
+ ts->ts_data.curr_data[id].y_position,
ts->jitter_filter.his_data[id].x,
ts->jitter_filter.his_data[id].y,
delta_x, delta_y,
@@ -847,23 +778,25 @@
bit_mask = ts->jitter_filter.id_mask ^ new_id_mask;
- for (i = 0, bit_id = 1; i < MAX_FINGER; i++) {
+ for (id = 0, bit_id = 1; id < MAX_FINGER; id++) {
if ((ts->jitter_filter.id_mask & bit_id) &&
!(new_id_mask & bit_id)) {
if (unlikely(touch_debug_mask & DEBUG_JITTER))
TOUCH_INFO_MSG("JitterFilter: released - "
"id[%d] mask[0x%x]\n",
bit_id, ts->jitter_filter.id_mask);
- memset(&ts->jitter_filter.his_data[i], 0,
- sizeof(ts->jitter_filter.his_data[i]));
+ memset(&ts->jitter_filter.his_data[id], 0,
+ sizeof(ts->jitter_filter.his_data[id]));
}
bit_id = bit_id << 1;
}
- for (i = 0; i < ts->ts_data.total_num; i++) {
- u16 id = ts->ts_data.curr_data[i].id;
+ for (id = 0; id < MAX_FINGER; id++) {
+ if (!ts->ts_data.curr_data[id].state)
+ continue;
+
ts->jitter_filter.his_data[id].pressure =
- ts->ts_data.curr_data[i].pressure;
+ ts->ts_data.curr_data[id].pressure;
}
if (!bit_mask && ts->ts_data.total_num &&
@@ -876,12 +809,14 @@
return -1;
}
- for (i = 0; i < ts->ts_data.total_num; i++) {
- u16 id = ts->ts_data.curr_data[i].id;
+ for (id = 0; id < MAX_FINGER; id++) {
+ if (!ts->ts_data.curr_data[id].state)
+ continue;
+
ts->jitter_filter.his_data[id].x =
- ts->ts_data.curr_data[i].x_position;
+ ts->ts_data.curr_data[id].x_position;
ts->jitter_filter.his_data[id].y =
- ts->ts_data.curr_data[i].y_position;
+ ts->ts_data.curr_data[id].y_position;
}
ts->jitter_filter.id_mask = new_id_mask;
@@ -907,280 +842,49 @@
touch_ic_init(ts);
}
-static void touch_lock_func(struct work_struct *work_touch_lock)
+static void touch_input_report(struct lge_touch_data *ts)
{
- struct lge_touch_data *ts =
- container_of(to_delayed_work(work_touch_lock),
- struct lge_touch_data, work_touch_lock);
+ int id;
- if (unlikely(touch_debug_mask & DEBUG_TRACE))
- TOUCH_DEBUG_MSG("\n");
+ for (id = 0; id < MAX_FINGER; id++) {
+ if (!ts->ts_data.curr_data[id].state)
+ continue;
- ts->ts_data.state = DO_NOT_ANYTHING;
-}
+ input_mt_slot(ts->input_dev, id);
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+ ts->ts_data.curr_data[id].state != ABS_RELEASE);
-/* touch_work_func_hardkey
- *
- * HARD_TOUCH_KEY
- */
-static void touch_work_func_hardkey(struct work_struct *work)
-{
- struct lge_touch_data *ts =
- container_of(work, struct lge_touch_data, work);
- u8 report_enable = 0;
- int int_pin = 0;
- int next_work = 0;
- struct t_data *cur;
+ if (ts->ts_data.curr_data[id].state != ABS_RELEASE) {
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+ ts->ts_data.curr_data[id].x_position);
+ input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+ ts->ts_data.curr_data[id].y_position);
+ if (is_pressure)
+ input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+ ts->ts_data.curr_data[id].pressure);
- atomic_dec(&ts->next_work);
- ts->ts_data.total_num = 0;
-
- if (unlikely(ts->work_sync_err_cnt >= MAX_RETRY_COUNT)) {
- TOUCH_ERR_MSG("Work Sync Failed: Irq-pin has some unknown problems\n");
- goto err_out_critical;
- }
-
-#ifdef LGE_TOUCH_TIME_DEBUG
- do_gettimeofday(&t_debug[TIME_WORKQUEUE_START]);
-#endif
-
- if (unlikely(touch_debug_mask & DEBUG_TRACE))
- TOUCH_DEBUG_MSG("\n");
-
- if (touch_device_func->data(ts->client, ts->ts_data.curr_data,
- &ts->ts_data.curr_button, &ts->ts_data.total_num) < 0) {
- TOUCH_ERR_MSG("get data fail\n");
- goto err_out_critical;
- }
-
- if (likely(ts->pdata->role->operation_mode == INTERRUPT_MODE))
- int_pin = gpio_get_value(ts->pdata->int_pin);
-
- /* Ghost finger solution */
- if (unlikely(ts->gf_ctrl.stage)) {
- if (ghost_finger_solution(ts)) {
- TOUCH_ERR_MSG("ghost_finger_solution was failed\n");
- goto err_out_critical;
+ /* Only support circle region */
+ if (is_width)
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ ts->ts_data.curr_data[id].width_major);
+ }
+ else {
+ ts->ts_data.curr_data[id].state = 0;
}
}
- /* Accuracy Solution */
- if (likely(ts->pdata->role->accuracy_filter_enable)) {
- if (accuracy_filter_func(ts) < 0)
- goto out;
- }
-
- /* Jitter Solution */
- if (likely(ts->pdata->role->jitter_filter_enable)) {
- if (jitter_filter_func(ts) < 0)
- goto out;
- }
-
- /* Finger handle */
- if (ts->ts_data.state != TOUCH_ABS_LOCK) {
- if (!ts->ts_data.total_num) {
- input_mt_sync(ts->input_dev);
- report_enable = 1;
-
- queue_delayed_work(touch_wq, &ts->work_touch_lock,
- msecs_to_jiffies(200));
-
- if (likely(touch_debug_mask &
- (DEBUG_BASE_INFO | DEBUG_ABS))) {
- if (ts->ts_data.prev_total_num)
- TOUCH_INFO_MSG("touch_release : x[%4d] y[%4d]\n", ts->ts_data.prev_data[0].x_position, ts->ts_data.prev_data[0].y_position);
- }
- ts->ts_data.prev_total_num = 0;
- } else if (ts->ts_data.total_num <= MAX_FINGER) {
- cancel_delayed_work_sync(&ts->work_touch_lock);
-
- if (ts->gf_ctrl.stage == GHOST_STAGE_CLEAR ||
- ts->gf_ctrl.stage == GHOST_STAGE_3)
- ts->ts_data.state = TOUCH_BUTTON_LOCK;
-
- /* key button cancel */
- if (ts->ts_data.prev_button.state == BUTTON_PRESSED) {
- input_report_key(ts->input_dev,
- ts->ts_data.prev_button.key_code,
- BUTTON_CANCLED);
-
- if (likely(touch_debug_mask &
- (DEBUG_BUTTON | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("Touch KEY[%d] is canceled\n", ts->ts_data.prev_button.key_code);
-
- memset(&ts->ts_data.prev_button, 0x0,
- sizeof(ts->ts_data.prev_button));
- }
-
- if (likely(touch_debug_mask &
- (DEBUG_BASE_INFO | DEBUG_ABS))) {
- if (ts->ts_data.prev_total_num !=
- ts->ts_data.total_num)
- TOUCH_INFO_MSG("%d finger pressed\n", ts->ts_data.total_num);
- }
-
- ts->ts_data.prev_total_num = ts->ts_data.total_num;
-
- while (ts->ts_data.total_num--) {
- cur = &ts->ts_data.curr_data[ts->ts_data.total_num];
- INPUT_REPORT_ABS(ts->input_dev, cur);
- }
- report_enable = 1;
-
- memcpy(ts->ts_data.prev_data, ts->ts_data.curr_data,
- sizeof(ts->ts_data.curr_data));
- }
-
- /* Reset finger position data */
- memset(&ts->ts_data.curr_data, 0x0,
- sizeof(ts->ts_data.curr_data));
-
- if (report_enable)
- input_sync(ts->input_dev);
- }
-
- /* Button handle */
- if (ts->ts_data.state != TOUCH_BUTTON_LOCK) {
- /* do not check when there is no pressed button at error case
- * - if you check it, sometimes touch is locked because
- * button pressed via IC error.
- */
- if (ts->work_sync_err_cnt > 0 &&
- ts->ts_data.prev_button.state == BUTTON_RELEASED) {
- /* Do nothing */
- } else {
- report_enable = 0;
-
- if (unlikely(touch_debug_mask & DEBUG_BUTTON))
- TOUCH_INFO_MSG("Cur. button -code: %d "
- "state: %d, Prev. button -"
- "code: %d state: %d\n",
- ts->ts_data.curr_button.key_code,
- ts->ts_data.curr_button.state,
- ts->ts_data.prev_button.key_code,
- ts->ts_data.prev_button.state);
-
- if (ts->ts_data.curr_button.state == BUTTON_PRESSED &&
- ts->ts_data.prev_button.state == BUTTON_RELEASED) {
- /* button pressed */
- cancel_delayed_work_sync(&ts->work_touch_lock);
-
- if (ts->gf_ctrl.stage == GHOST_STAGE_CLEAR ||
- ts->gf_ctrl.stage == GHOST_STAGE_3)
- ts->ts_data.state = TOUCH_ABS_LOCK;
-
- queue_delayed_work(touch_wq,
- &ts->work_touch_lock,
- msecs_to_jiffies(200));
-
- input_report_key(ts->input_dev,
- ts->ts_data.curr_button.key_code,
- BUTTON_PRESSED);
-
- if (likely(touch_debug_mask &
- (DEBUG_BUTTON | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("Touch KEY[%d] is pressed\n", ts->ts_data.curr_button.key_code);
-
- memcpy(&ts->ts_data.prev_button,
- &ts->ts_data.curr_button,
- sizeof(ts->ts_data.curr_button));
-
- report_enable = 1;
- } else if (ts->ts_data.curr_button.state == BUTTON_PRESSED
- && ts->ts_data.prev_button.state == BUTTON_PRESSED
- && ts->ts_data.prev_button.key_code !=
- ts->ts_data.curr_button.key_code) {
- /* exception case - multi press button handle */
- queue_delayed_work(touch_wq,
- &ts->work_touch_lock,
- msecs_to_jiffies(200));
-
- /* release previous pressed button */
- input_report_key(ts->input_dev,
- ts->ts_data.prev_button.key_code,
- BUTTON_RELEASED);
-
- ts->ts_data.prev_button.state = BUTTON_RELEASED;
-
- if (likely(touch_debug_mask &
- (DEBUG_BUTTON | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("Touch KEY[%d] is released\n", ts->ts_data.prev_button.key_code);
-
- report_enable = 1;
- } else if (ts->ts_data.curr_button.state == BUTTON_RELEASED
- && ts->ts_data.prev_button.state == BUTTON_PRESSED
- && ts->ts_data.prev_button.key_code ==
- ts->ts_data.curr_button.key_code) {
- /* button release */
- input_report_key(ts->input_dev,
- ts->ts_data.prev_button.key_code, BUTTON_RELEASED);
-
- if (likely(touch_debug_mask &
- (DEBUG_BUTTON | DEBUG_BASE_INFO)))
- TOUCH_INFO_MSG("Touch KEY[%d] is released\n", ts->ts_data.prev_button.key_code);
-
- memset(&ts->ts_data.prev_button, 0x0,
- sizeof(ts->ts_data.prev_button));
- memset(&ts->ts_data.curr_button, 0x0,
- sizeof(ts->ts_data.curr_button));
-
- report_enable = 1;
- }
-
- if (report_enable)
- input_sync(ts->input_dev);
- }
- }
-
-out:
- if (likely(ts->pdata->role->operation_mode == INTERRUPT_MODE)) {
- next_work = atomic_read(&ts->next_work);
-
- if (unlikely(int_pin != 1 && next_work <= 0)) {
- TOUCH_INFO_MSG("WARN: Interrupt pin is low - "
- "next_work: %d, try_count: %d]\n",
- next_work, ts->work_sync_err_cnt);
- goto err_out_retry;
- }
- }
-
-#ifdef LGE_TOUCH_TIME_DEBUG
- do_gettimeofday(&t_debug[TIME_WORKQUEUE_END]);
- if (next_work)
- memset(t_debug, 0x0, sizeof(t_debug));
- time_profile_result(ts);
-#endif
-
- ts->work_sync_err_cnt = 0;
-
- return;
-
-err_out_retry:
- ts->work_sync_err_cnt++;
- atomic_inc(&ts->next_work);
- queue_work(touch_wq, &ts->work);
-
- return;
-
-err_out_critical:
- ts->work_sync_err_cnt = 0;
- safety_reset(ts);
- touch_ic_init(ts);
-
- return;
+ input_sync(ts->input_dev);
}
/*
- * Touch without Key Support
+ * Touch work function
*/
static void touch_work_func(struct work_struct *work)
{
struct lge_touch_data *ts =
container_of(work, struct lge_touch_data, work);
- u8 report_enable = 0;
int int_pin = 0;
int next_work = 0;
- struct t_data *cur;
atomic_dec(&ts->next_work);
ts->ts_data.total_num = 0;
@@ -1225,42 +929,7 @@
goto out;
}
- if (!ts->ts_data.total_num) {
- input_mt_sync(ts->input_dev);
- report_enable = 1;
-
- if (likely(touch_debug_mask & (DEBUG_BASE_INFO | DEBUG_ABS))) {
- if (ts->ts_data.prev_total_num)
- TOUCH_INFO_MSG("touch_release : x[%4d] y[%4d]\n",
- ts->ts_data.prev_data[0].x_position,
- ts->ts_data.prev_data[0].y_position);
- }
-
- ts->ts_data.prev_total_num = 0;
- } else if (ts->ts_data.total_num <= MAX_FINGER) {
- if (likely(touch_debug_mask & (DEBUG_BASE_INFO | DEBUG_ABS))) {
- if (ts->ts_data.prev_total_num != ts->ts_data.total_num)
- TOUCH_INFO_MSG("%d finger pressed\n",
- ts->ts_data.total_num);
- }
-
- ts->ts_data.prev_total_num = ts->ts_data.total_num;
-
- while (ts->ts_data.total_num--) {
- cur = &ts->ts_data.curr_data[ts->ts_data.total_num];
- INPUT_REPORT_ABS(ts->input_dev, cur);
- }
- report_enable = 1;
-
- memcpy(ts->ts_data.prev_data, ts->ts_data.curr_data,
- sizeof(ts->ts_data.curr_data));
- }
-
- /* Reset finger position data */
- memset(&ts->ts_data.curr_data, 0x0, sizeof(ts->ts_data.curr_data));
-
- if (report_enable)
- input_sync(ts->input_dev);
+ touch_input_report(ts);
out:
if (likely(ts->pdata->role->operation_mode == INTERRUPT_MODE)) {
@@ -1283,6 +952,7 @@
ts->work_sync_err_cnt = 0;
return;
+
err_out_retry:
ts->work_sync_err_cnt++;
atomic_inc(&ts->next_work);
@@ -1391,7 +1061,6 @@
t_debug[TIME_FW_UPGRADE_START].tv_usec));
}
#endif
-
goto out;
err_out:
@@ -1545,7 +1214,7 @@
sc->panel.bottom = pdata->caps->y_button_boundary;
if (pdata->caps->button_support) {
- sc->b_width = pdata->caps->x_max /
+ sc->b_width = pdata->caps->x_max /
pdata->caps->number_of_button;
sc->b_margin = sc->b_width * pdata->caps->button_margin / 100;
sc->b_inner_width = sc->b_width - (2 * sc->b_margin);
@@ -2108,12 +1777,7 @@
msleep(ts->pdata->role->booting_delay);
/* init work_queue */
- if (ts->pdata->role->key_type == TOUCH_HARD_KEY) {
- INIT_WORK(&ts->work, touch_work_func_hardkey);
- INIT_DELAYED_WORK(&ts->work_touch_lock, touch_lock_func);
- } else {
- INIT_WORK(&ts->work, touch_work_func);
- }
+ INIT_WORK(&ts->work, touch_work_func);
INIT_DELAYED_WORK(&ts->work_init, touch_init_func);
INIT_WORK(&ts->work_fw_upgrade, touch_fw_upgrade_func);
@@ -2134,13 +1798,14 @@
set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
#endif
- if (ts->pdata->caps->button_support && ts->pdata->role->key_type != VIRTUAL_KEY) {
+ if (ts->pdata->caps->button_support) {
set_bit(EV_KEY, ts->input_dev->evbit);
for (ret = 0; ret < ts->pdata->caps->number_of_button; ret++) {
set_bit(ts->pdata->caps->button_name[ret], ts->input_dev->keybit);
}
}
+ input_mt_init_slots(ts->input_dev, MAX_FINGER);
input_set_abs_params(ts->input_dev,
ABS_MT_POSITION_X, 0, ts->pdata->caps->x_max, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
@@ -2154,21 +1819,17 @@
is_width = ts->pdata->caps->is_width_supported;
is_id = ts->pdata->caps->is_id_supported;
- if (ts->pdata->caps->is_pressure_supported)
+ if (is_pressure)
input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,
0, ts->pdata->caps->max_pressure, 0, 0);
if (ts->pdata->caps->is_width_supported) {
+ /* Only circle supported */
+ input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, ts->pdata->caps->max_width, 0, 0);
input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
0, ts->pdata->caps->max_width, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MINOR,
- 0, ts->pdata->caps->max_width, 0, 0);
- input_set_abs_params(ts->input_dev, ABS_MT_ORIENTATION,
- 0, 1, 0, 0);
}
- if (ts->pdata->caps->is_id_supported)
- input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
- 0, ts->pdata->caps->max_id, 0, 0);
ret = input_register_device(ts->input_dev);
if (ret < 0) {
@@ -2192,6 +1853,7 @@
if (ret < 0) {
TOUCH_ERR_MSG("request_irq failed. use polling mode\n");
+ gpio_free(ts->pdata->int_pin);
goto err_interrupt_failed;
}
} else { /* polling mode */
@@ -2259,15 +1921,17 @@
return 0;
err_lge_touch_sysfs_init_and_add:
- kobject_del(&ts->lge_touch_kobj);
-err_lge_touch_sys_dev_register:
sysdev_unregister(&lge_touch_sys_device);
-err_lge_touch_sys_class_register:
+err_lge_touch_sys_dev_register:
sysdev_class_unregister(&lge_touch_sys_class);
+err_lge_touch_sys_class_register:
unregister_early_suspend(&ts->early_suspend);
-err_interrupt_failed:
- if (ts->pdata->role->operation_mode == INTERRUPT_MODE)
+ if (ts->pdata->role->operation_mode == INTERRUPT_MODE) {
+ gpio_free(ts->pdata->int_pin);
free_irq(ts->client->irq, ts);
+ }
+err_interrupt_failed:
+ input_unregister_device(ts->input_dev);
err_input_register_device_failed:
input_free_device(ts->input_dev);
err_input_dev_alloc_failed:
@@ -2300,12 +1964,16 @@
unregister_early_suspend(&ts->early_suspend);
- if (ts->pdata->role->operation_mode == INTERRUPT_MODE)
+ if (ts->pdata->role->operation_mode == INTERRUPT_MODE) {
+ gpio_free(ts->pdata->int_pin);
free_irq(client->irq, ts);
- else
+ }
+ else {
hrtimer_cancel(&ts->timer);
+ }
input_unregister_device(ts->input_dev);
+ input_free_device(ts->input_dev);
kfree(ts);
return 0;
diff --git a/drivers/input/touchscreen/touch_synaptics.c b/drivers/input/touchscreen/touch_synaptics.c
index 4ab0e65..040d727 100644
--- a/drivers/input/touchscreen/touch_synaptics.c
+++ b/drivers/input/touchscreen/touch_synaptics.c
@@ -175,15 +175,21 @@
_bit_mask &= ~(_bit_mask & (1<<(_index))); \
} while (0)
+
+#define FINGER_STATE_NO_PRESENT 0
+#define FINGER_STATE_PRESENT_VALID 1
+#define FINGER_STATE_PRESENT_NOVALID 2
+#define FINGER_STATE_REVSERVED 3
+
int synaptics_ts_get_data(struct i2c_client *client, struct t_data* data,
struct b_data* button, u8* total_num)
{
struct synaptics_ts_data* ts =
(struct synaptics_ts_data*)get_touch_handle(client);
- u16 touch_finger_bit_mask=0;
+ u32 finger_status=0;
u8 finger_index=0;
- u8 index=0;
+ u8 id=0;
u8 cnt;
if (unlikely(touch_debug_mask & DEBUG_TRACE))
@@ -234,7 +240,6 @@
goto err_synaptics_device_damage;
}
-//printk("[S:%x,M:%x", ts->ts_data.interrupt_status_reg, ts->interrupt_mask.abs);
/* Finger */
if (likely(ts->ts_data.interrupt_status_reg & ts->interrupt_mask.abs)) {
if (unlikely(touch_i2c_read(client, FINGER_STATE_REG,
@@ -244,129 +249,106 @@
goto err_synaptics_getdata;
}
- touch_finger_bit_mask = GET_BIT_MASK(ts->ts_data.finger.finger_status_reg);
-//printk("F:%x", touch_finger_bit_mask);
+ finger_status = ts->ts_data.finger.finger_status_reg[0] |
+ ts->ts_data.finger.finger_status_reg[1] << 8 |
+ (ts->ts_data.finger.finger_status_reg[2] & 0xF) << 16;
+
if (unlikely(touch_debug_mask & DEBUG_GET_DATA)) {
TOUCH_INFO_MSG("Finger_status : 0x%x, 0x%x, 0x%x\n",
ts->ts_data.finger.finger_status_reg[0],
ts->ts_data.finger.finger_status_reg[1],
ts->ts_data.finger.finger_status_reg[2]);
- TOUCH_INFO_MSG("Touch_bit_mask: 0x%x\n", touch_finger_bit_mask);
+ TOUCH_INFO_MSG("Touch_bit_mask: 0x%x\n", finger_status);
}
- while (touch_finger_bit_mask) {
- GET_INDEX_FROM_MASK(finger_index, touch_finger_bit_mask,
- MAX_NUM_OF_FINGERS);
- if (unlikely(touch_i2c_read(ts->client,
- FINGER_DATA_REG_START + (NUM_OF_EACH_FINGER_DATA_REG * finger_index),
+ for (id = 0; id < MAX_FINGER; id++) {
+ switch (((finger_status >> (id*2)) & 0x3)) {
+ case FINGER_STATE_PRESENT_VALID:
+ touch_i2c_read(ts->client,
+ FINGER_DATA_REG_START + NUM_OF_EACH_FINGER_DATA_REG * id,
NUM_OF_EACH_FINGER_DATA_REG,
- ts->ts_data.finger.finger_reg[index]) < 0)) {
- TOUCH_ERR_MSG("FINGER_DATA_REG read fail\n");
- goto err_synaptics_getdata;
+ ts->ts_data.finger.finger_reg[id]);
+ data[id].state = ABS_PRESS;
+ data[id].x_position = TS_SNTS_GET_X_POSITION(
+ ts->ts_data.finger.finger_reg[id][REG_X_POSITION],
+ ts->ts_data.finger.finger_reg[id][REG_YX_POSITION]);
+ data[id].y_position = TS_SNTS_GET_Y_POSITION(ts->ts_data.finger.finger_reg[id][REG_Y_POSITION], ts->ts_data.finger.finger_reg[id][REG_YX_POSITION]);
+ data[id].width_major = TS_SNTS_GET_WIDTH_MAJOR(ts->ts_data.finger.finger_reg[id][REG_WY_WX]);
+ data[id].width_minor = TS_SNTS_GET_WIDTH_MINOR(ts->ts_data.finger.finger_reg[id][REG_WY_WX]);
+ data[id].width_orientation = TS_SNTS_GET_ORIENTATION(ts->ts_data.finger.finger_reg[id][REG_WY_WX]);
+ data[id].pressure = TS_SNTS_GET_PRESSURE(ts->ts_data.finger.finger_reg[id][REG_Z]);
+
+ if (unlikely(touch_debug_mask & DEBUG_GET_DATA))
+ TOUCH_INFO_MSG("[%d] pos(%4d,%4d) w_m[%2d] w_n[%2d] w_o[%2d] p[%2d]\n",
+ finger_index,
+ data[id].x_position,
+ data[id].y_position,
+ data[id].width_major,
+ data[id].width_minor,
+ data[id].width_orientation,
+ data[id].pressure);
+ (*total_num)++;
+ break;
+
+ case FINGER_STATE_NO_PRESENT:
+ if (data[id].state == ABS_PRESS)
+ data[id].state = ABS_RELEASE;
+ break;
+
+ default:
+ /* Do nothing including inacurate data */
+ break;
}
- data[index].id = finger_index;
- data[index].x_position = TS_SNTS_GET_X_POSITION(
- ts->ts_data.finger.finger_reg[index][REG_X_POSITION],
- ts->ts_data.finger.finger_reg[index][REG_YX_POSITION]);
- data[index].y_position = TS_SNTS_GET_Y_POSITION(
- ts->ts_data.finger.finger_reg[index][REG_Y_POSITION],
- ts->ts_data.finger.finger_reg[index][REG_YX_POSITION]);
- data[index].width_major = TS_SNTS_GET_WIDTH_MAJOR(
- ts->ts_data.finger.finger_reg[index][REG_WY_WX]);
- data[index].width_minor = TS_SNTS_GET_WIDTH_MINOR(
- ts->ts_data.finger.finger_reg[index][REG_WY_WX]);
- data[index].width_orientation = TS_SNTS_GET_ORIENTATION(
- ts->ts_data.finger.finger_reg[index][REG_WY_WX]);
- data[index].pressure = TS_SNTS_GET_PRESSURE(
- ts->ts_data.finger.finger_reg[index][REG_Z]);
-
- if (unlikely(touch_debug_mask & DEBUG_GET_DATA))
- TOUCH_INFO_MSG("[%d] pos(%4d,%4d) w_m[%2d] "
- "w_n[%2d] w_o[%2d] p[%2d]\n",
- finger_index,
- data[index].x_position,
- data[index].y_position,
- data[index].width_major,
- data[index].width_minor,
- data[index].width_orientation,
- data[index].pressure);
-
- index++;
}
- *total_num = index;
-//printk(" -> %d]", index);
if (unlikely(touch_debug_mask & DEBUG_GET_DATA))
TOUCH_INFO_MSG("Total_num: %d\n", *total_num);
}
-//printk("button_id = %d\n", ts->button_dsc.id);
/* Button */
- if (unlikely(ts->button_dsc.id != 0)) {
- if (likely(ts->ts_data.interrupt_status_reg &
+ if ((ts->button_dsc.id != 0) && (ts->ts_data.interrupt_status_reg &
ts->interrupt_mask.button)) {
-#if defined(CONFIG_TOUCH_REG_MAP_TM2000) || defined(CONFIG_TOUCH_REG_MAP_TM2372)
- if (unlikely(touch_i2c_write_byte(client,
- PAGE_SELECT_REG, 0x02) < 0)) {
- TOUCH_ERR_MSG("PAGE_SELECT_REG write fail\n");
- return -EIO;
- }
+ if (unlikely(touch_i2c_write_byte(client,
+ PAGE_SELECT_REG, 0x02) < 0)) {
+ TOUCH_ERR_MSG("PAGE_SELECT_REG write fail\n");
+ return -EIO;
+ }
- if (unlikely(touch_i2c_read(client, BUTTON_DATA_REG,
- sizeof(ts->ts_data.button_data_reg),
- &ts->ts_data.button_data_reg) < 0)) {
- TOUCH_ERR_MSG("BUTTON_DATA_REG read fail\n");
- goto err_synaptics_getdata;
- }
+ if (unlikely(touch_i2c_read(client, BUTTON_DATA_REG,
+ sizeof(ts->ts_data.button_data_reg),
+ &ts->ts_data.button_data_reg) < 0)) {
+ TOUCH_ERR_MSG("BUTTON_DATA_REG read fail\n");
+ goto err_synaptics_getdata;
+ }
- if (unlikely(touch_i2c_write_byte(client,
- PAGE_SELECT_REG, 0x00) < 0)) {
- TOUCH_ERR_MSG("PAGE_SELECT_REG write fail\n");
- return -EIO;
- }
-#else
- if (unlikely(touch_i2c_read(client, BUTTON_DATA_REG,
- sizeof(ts->ts_data.button_data_reg),
- &ts->ts_data.button_data_reg) < 0)) {
- TOUCH_ERR_MSG("BUTTON_DATA_REG read fail\n");
- goto err_synaptics_getdata;
- }
-#endif
- if (unlikely(touch_debug_mask & DEBUG_BUTTON))
- TOUCH_DEBUG_MSG("Button register: 0x%x\n",
- ts->ts_data.button_data_reg);
+ if (unlikely(touch_i2c_write_byte(client,
+ PAGE_SELECT_REG, 0x00) < 0)) {
+ TOUCH_ERR_MSG("PAGE_SELECT_REG write fail\n");
+ return -EIO;
+ }
- if (ts->ts_data.button_data_reg) {
- /* pressed - find first one */
- for (cnt = 0; cnt < ts->pdata->caps->number_of_button; cnt++) {
-#if defined(CONFIG_TOUCH_REG_MAP_TM2000)
- if (((ts->ic_panel_type == IC7020_GFF ||
- ts->ic_panel_type == IC7020_G2 ||
- ts->ic_panel_type == IC7020_G2_H_PTN) &&
- ((ts->ts_data.button_data_reg >> cnt)
- & 0x1)) ||
- ((ts->ic_panel_type == IC3203_G2) &&
- ((ts->ts_data.button_data_reg >>
- (cnt << 1)) & 0x3))) {
-#elif defined(CONFIG_TOUCH_REG_MAP_TM2372)
- if ((ts->ts_data.button_data_reg >> cnt) & 0x1) {
-#else
- if ((ts->ts_data.button_data_reg >> cnt) & 0x1) {
-#endif
- ts->ts_data.button.key_code =
- ts->pdata->caps->button_name[cnt];
- button->key_code =
- ts->ts_data.button.key_code;
- button->state = 1;
- break;
- }
+ if (unlikely(touch_debug_mask & DEBUG_BUTTON))
+ TOUCH_DEBUG_MSG("Button register: 0x%x\n",
+ ts->ts_data.button_data_reg);
+
+ if (ts->ts_data.button_data_reg) {
+ /* pressed - find first one */
+ for (cnt = 0; cnt < ts->pdata->caps->number_of_button; cnt++) {
+ if ((ts->ts_data.button_data_reg >> cnt) & 1)
+ {
+ ts->ts_data.button.key_code =
+ ts->pdata->caps->button_name[cnt];
+ button->key_code =
+ ts->ts_data.button.key_code;
+ button->state = 1;
+ break;
}
- } else {
- /* release */
- button->key_code = ts->ts_data.button.key_code;
- button->state = 0;
}
+ } else {
+ /* release */
+ button->key_code = ts->ts_data.button.key_code;
+ button->state = 0;
}
}
@@ -663,8 +645,30 @@
}
#if defined(CONFIG_TOUCH_REG_MAP_TM2000) || defined(CONFIG_TOUCH_REG_MAP_TM2372)
- /* do nothing */
+ if (ts->pdata->role->report_mode == CONTINUOUS_REPORT_MODE) {
+ if (unlikely(touch_i2c_write_byte(client, TWO_D_REPORTING_MODE,
+ REPORT_MODE_CONTINUOUS) < 0)) {
+ TOUCH_ERR_MSG("TWO_D_REPORTING_MODE write fail\n");
+ return -EIO;
+ }
+ } else { /* REDUCED_REPORT_MODE */
+ if (unlikely(touch_i2c_write_byte(client, TWO_D_REPORTING_MODE,
+ REPORT_MODE_REDUCED) < 0)) {
+ TOUCH_ERR_MSG("TWO_D_REPORTING_MODE write fail\n");
+ return -EIO;
+ }
+ if (unlikely(touch_i2c_write_byte(client, DELTA_X_THRESH_REG,
+ ts->pdata->role->delta_pos_threshold) < 0)) {
+ TOUCH_ERR_MSG("DELTA_X_THRESH_REG write fail\n");
+ return -EIO;
+ }
+ if (unlikely(touch_i2c_write_byte(client, DELTA_Y_THRESH_REG,
+ ts->pdata->role->delta_pos_threshold) < 0)) {
+ TOUCH_ERR_MSG("DELTA_Y_THRESH_REG write fail\n");
+ return -EIO;
+ }
+ }
#else
if (unlikely(touch_i2c_write_byte(client,
GESTURE_ENABLE_1_REG, 0x00) < 0)) {
@@ -826,32 +830,42 @@
ret = regulator_set_voltage(ts->regulator_vdd,
ts->pdata->pwr->vdd_voltage,
ts->pdata->pwr->vdd_voltage);
- if (ret < 0)
+ if (ret < 0) {
TOUCH_ERR_MSG("FAIL: VDD voltage setting"
" - (%duV)\n",
ts->pdata->pwr->vdd_voltage);
+ ret = -EPERM;
+ goto err_set_voltage;
+ }
}
if (ts->pdata->pwr->vio_voltage > 0) {
ret = regulator_set_voltage(ts->regulator_vio,
ts->pdata->pwr->vio_voltage,
ts->pdata->pwr->vio_voltage);
- if (ret < 0)
+ if (ret < 0) {
TOUCH_ERR_MSG("FAIL: VIO voltage setting"
" - (%duV)\n",
ts->pdata->pwr->vio_voltage);
+ ret = -EPERM;
+ goto err_set_voltage;
+ }
}
}
return ret;
+err_set_voltage:
+ if (ts->pdata->pwr->use_regulator) {
+ regulator_put(ts->regulator_vio);
+ }
err_get_vio_failed:
if (ts->pdata->pwr->use_regulator) {
regulator_put(ts->regulator_vdd);
}
err_get_vdd_failed:
-err_alloc_data_failed:
kfree(ts);
+err_alloc_data_failed:
return ret;
}