From: Ziggy471 Date: Wed, 22 Dec 2010 15:51:43 +0000 (-0500) Subject: Update cm3602, crucial, and synaptics touchscreen to glacier X-Git-Url: https://projects.ziggy471.com/git/gitweb.cgi?p=ziggy471-frankenstein-kernel.git;a=commitdiff;h=29731e289616e51bac4d453256b39d366f511573 Update cm3602, crucial, and synaptics touchscreen to glacier --- --- a/drivers/input/misc/capella_cm3602.c +++ b/drivers/input/misc/capella_cm3602.c @@ -31,13 +31,9 @@ struct wake_lock proximity_wake_lock; -static void ps_irq_do_work(struct work_struct *work); -static DECLARE_WORK(ps_irq_work, ps_irq_do_work); - static struct capella_cm3602_data { struct input_dev *input_dev; struct capella_cm3602_platform_data *pdata; - struct workqueue_struct *ps_wq; int enabled; } the_data; @@ -73,18 +69,10 @@ static int capella_cm3602_report(struct return val; } -static void ps_irq_do_work(struct work_struct *work) -{ - capella_cm3602_report(&the_data); - enable_irq(the_data.pdata->irq); -} - static irqreturn_t capella_cm3602_irq_handler(int irq, void *data) { - disable_irq_nosync(irq); - - queue_work(the_data.ps_wq, &ps_irq_work); - + struct capella_cm3602_data *ip = data; + capella_cm3602_report(ip); return IRQ_HANDLED; } @@ -183,14 +171,7 @@ static int capella_cm3602_setup(struct c __func__, pdata->p_out, rc); goto fail_free_p_en; } - - the_data.ps_wq = create_singlethread_workqueue("proximity_wq"); - if (!the_data.ps_wq) { - pr_err("%s: can't create workqueue\n", __func__); - rc = -ENOMEM; - goto fail_free_p_en; - } - + set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); rc = request_irq(irq, capella_cm3602_irq_handler, IRQF_TRIGGER_LOW | IRQF_TRIGGER_HIGH, @@ -200,13 +181,11 @@ static int capella_cm3602_setup(struct c pr_err("%s: request_irq(%d) failed for gpio %d (%d)\n", __func__, irq, pdata->p_out, rc); - goto fail_free_wq; + goto fail_free_p_en; } goto done; -fail_free_wq: - destroy_workqueue(the_data.ps_wq); fail_free_p_en: gpio_free(pdata->p_en); fail_free_p_out: @@ -330,8 +309,6 @@ err_unregister_input_device: err_free_input_device: input_free_device(input_dev); done: - if (ip->pdata && ip->pdata->irq) - disable_irq(ip->pdata->irq); return rc; } --- a/drivers/input/opticaljoystick/curcial.c +++ b/drivers/input/opticaljoystick/curcial.c @@ -238,8 +238,8 @@ static void curcial_oj_work_func(struct bool out = false; uint8_t pxsum; uint16_t sht; - int16_t x_sum; - int16_t y_sum; + int16_t x_sum, x_idx; + int16_t y_sum, y_idx; curcial_oj_polling_mode(OJ_POLLING_DISABLE); @@ -317,8 +317,15 @@ static void curcial_oj_work_func(struct } } - x_count = oj->Xsteps[abs(x_sum) / normal_th]; - y_count = oj->Ysteps[abs(y_sum) / normal_th]; + x_idx = abs(x_sum) / normal_th; + y_idx = abs(y_sum) / normal_th; + if (x_idx >= ARRAY_SIZE(oj->Xsteps)) + x_idx = ARRAY_SIZE(oj->Xsteps) - 1; + if (y_idx >= ARRAY_SIZE(oj->Ysteps)) + y_idx = ARRAY_SIZE(oj->Ysteps) - 1; + + x_count = oj->Xsteps[x_idx]; + y_count = oj->Ysteps[y_idx]; if (evtKey == OJ_KEY_LEFT) { for (j = 0; j < x_count; j++) { input_report_rel(oj->input_dev, REL_X, -1); @@ -362,7 +369,7 @@ static void curcial_oj_work_func(struct mDeltaX = 0; mDeltaY = 0; if (polling_delay) - msleep(polling_delay);/*hr_msleep(polling_delay);*/ + hr_msleep(polling_delay); } while ((data[0] & 0x80) && (!atomic_read(&suspend_flag))); --- a/drivers/input/touchscreen/synaptics_i2c_rmi.c +++ b/drivers/input/touchscreen/synaptics_i2c_rmi.c @@ -24,6 +24,8 @@ #include #include +#define ENABLE_IME_IMPROVEMENT + static struct workqueue_struct *synaptics_wq; struct synaptics_ts_data { @@ -45,8 +47,28 @@ struct synaptics_ts_data { uint32_t flags; int reported_finger_count; int8_t sensitivity_adjust; + uint32_t dup_threshold; int (*power)(int on); struct early_suspend early_suspend; + int display_width; /* display width in pixel */ + int display_height; /* display height in pixel */ + int ts_raw_pos[4]; /* raw data pos of left, right, top, and bottom */ + int ts_raw_width; + int ts_raw_height; +#ifdef ENABLE_IME_IMPROVEMENT + int ime_threshold_pixel; /* threshold in pixel */ + int ime_threshold[2]; /* threshold X & Y in raw data */ + int ime_area_pixel[4]; /* ime area in pixel */ + int ime_area_pos[4]; /* ime area in raw data */ +#endif + int margin_inactive_pixel[4]; /* margin area in pixel */ + int margin_inactive_raw[4]; /* margin area in raw data */ + uint8_t disable_margin_filter[2]; /* local margin filter. enable/disable time by time */ + uint8_t last_finger2_pressed; + uint8_t last_finger_result; + uint8_t key_pressed[2]; + uint8_t debug_log_level; + uint8_t grip_suppression[2]; }; #ifdef CONFIG_HAS_EARLYSUSPEND @@ -54,6 +76,363 @@ static void synaptics_ts_early_suspend(s static void synaptics_ts_late_resume(struct early_suspend *h); #endif +static struct synaptics_ts_data *gl_ts; +static const char SYNAPTICSNAME[] = "Synaptics_T1007"; +static uint32_t syn_panel_version; + +static ssize_t touch_vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + sprintf(buf, "%s_%#x\n", SYNAPTICSNAME, syn_panel_version); + ret = strlen(buf) + 1; + + return ret; +} + +static DEVICE_ATTR(vendor, 0444, touch_vendor_show, NULL); + +static struct kobject *android_touch_kobj; + +static ssize_t debug_level_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_ts_data *ts = gl_ts; + + return sprintf(buf, "%d\n", ts->debug_log_level); +} + +static ssize_t debug_level_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct synaptics_ts_data *ts = gl_ts; + + if (buf[0] >= '0' && buf[0] <= '9' && buf[1] == '\n') + ts->debug_log_level = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(debug_level, 0644, debug_level_show, debug_level_store); + +#ifdef ENABLE_IME_IMPROVEMENT +static ssize_t ime_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_ts_data *ts = gl_ts; + + return sprintf(buf, "%d\n", ts->ime_threshold_pixel); +} + +static ssize_t ime_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct synaptics_ts_data *ts = gl_ts; + char *ptr_data = (char *)buf; + unsigned long val; + + val = simple_strtoul(ptr_data, NULL, 10); + + if (val >= 0 && val <= max(ts->display_width, ts->display_height)) + ts->ime_threshold_pixel = val; + else + ts->ime_threshold_pixel = 0; + + ts->ime_threshold[0] = ts->ime_threshold_pixel * ts->ts_raw_width / ts->display_width; + ts->ime_threshold[1] = ts->ime_threshold_pixel * ts->ts_raw_height / ts->display_height; + + return count; +} + +static ssize_t ime_work_area_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_ts_data *ts = gl_ts; + + return sprintf(buf, "%d,%d,%d,%d\n", ts->ime_area_pixel[0], + ts->ime_area_pixel[1], ts->ime_area_pixel[2], ts->ime_area_pixel[3]); +} + +static ssize_t ime_work_area_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct synaptics_ts_data *ts = gl_ts; + char *ptr_data = (char *)buf; + char *p; + int pt_count = 0; + unsigned long val[4]; + + while ((p = strsep(&ptr_data, ","))) { + if (!*p) + break; + + if (pt_count >= 4) + break; + + val[pt_count] = simple_strtoul(p, NULL, 10); + + pt_count++; + } + + if (pt_count >= 4 && ts->display_width && ts->display_height) { + ts->ime_area_pixel[0] = val[0]; /* Left */ + ts->ime_area_pixel[1] = val[1]; /* Right */ + ts->ime_area_pixel[2] = val[2]; /* Top */ + ts->ime_area_pixel[3] = val[3]; /* Bottom */ + + if (val[0] < 0 || val[0] > ts->display_width) + ts->ime_area_pos[0] = 0; + else + ts->ime_area_pos[0] = val[0] * ts->max[0] / ts->display_width; + + if (val[1] < 0 || val[1] > ts->display_width) + ts->ime_area_pos[1] = ts->max[0]; + else + ts->ime_area_pos[1] = val[1] * ts->max[0] / ts->display_width; + + if (val[2] < 0 || val[2] > ts->display_height) + ts->ime_area_pos[2] = 0; + else + ts->ime_area_pos[2] = val[2] * ts->max[1] / ts->display_height; + + if (val[3] < 0 || val[3] > ts->display_height) + ts->ime_area_pos[3] = ts->max[1]; + else + ts->ime_area_pos[3] = val[3] * ts->max[1] / ts->display_height; + } + + return count; +} + +static int ime_report_filter(struct synaptics_ts_data *ts, int pos[2][2], const int finger2_pressed, const int z) +{ + int dx = 0; + int dy = 0; + static int report_x; + static int report_y; + + if (finger2_pressed) + return 1; + + if ((pos[0][0] >= ts->ime_area_pos[0] && pos[0][0] <= ts->ime_area_pos[1]) && + (pos[0][1] >= ts->ime_area_pos[2] && pos[0][1] <= ts->ime_area_pos[3])) { + dx = abs(pos[0][0] - report_x); + dy = abs(pos[0][1] - report_y); + + if (dx < ts->ime_threshold[0] && dy < ts->ime_threshold[1] && z != 0) { + return 1; + } + + report_x = pos[0][0]; + report_y = pos[0][1]; + + if (z == 0) { + report_x = report_y = 0; + } + } + + return 0; +} + +/* sys/class/input/inputX/ime_threshold */ +static DEVICE_ATTR(ime_threshold, 0666, ime_threshold_show, + ime_threshold_store); +static DEVICE_ATTR(ime_work_area, 0666, ime_work_area_show, + ime_work_area_store); +#endif + +static ssize_t margin_area_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct synaptics_ts_data *ts = gl_ts; + + return sprintf(buf, "#left,right,top,bottom\n" + "%d,%d,%d,%d\n", ts->margin_inactive_pixel[0], + ts->margin_inactive_pixel[1], + ts->margin_inactive_pixel[2], + ts->margin_inactive_pixel[3]); +} + +static ssize_t margin_area_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct synaptics_ts_data *ts = gl_ts; + char *ptr_data = (char *)buf; + char *p; + uint8_t skip_data = 0; + unsigned long val[5]; + int pt_count = 0; + + while (ptr_data) { + if ((*ptr_data == '#') || skip_data) { + /* skip any string begin at '#' */ + skip_data = 1; + if (*ptr_data == '\n') + skip_data = 0; + } else { + break; + } + ptr_data++; + } + + while ((p = strsep(&ptr_data, ","))) { + if (!*p) + break; + + if (pt_count >= 4) + break; + + val[pt_count] = simple_strtoul(p, NULL, 10); + + pt_count++; + } + + if (pt_count >= 4) { + if (val[0] < 0 || val[0] > ts->display_width) { /* Left */ + ts->margin_inactive_raw[0] = ts->margin_inactive_pixel[0] = 0; + } else { + ts->margin_inactive_pixel[0] = val[0]; + ts->margin_inactive_raw[0] = ts->ts_raw_pos[0] + val[0] * + ts->ts_raw_width / ts->display_width; + } + + if (val[1] < 0 || val[1] > ts->display_width) { /* Right */ + ts->margin_inactive_pixel[1] = 0; + ts->margin_inactive_raw[1] = ts->max[0]; + } else { + ts->margin_inactive_pixel[1] = val[1]; + ts->margin_inactive_raw[1] = ts->ts_raw_pos[0] + val[1] * + ts->ts_raw_width / ts->display_width; + } + + if (val[2] < 0 || val[2] > ts->display_width) { /* top */ + ts->margin_inactive_raw[2] = ts->margin_inactive_pixel[2] = 0; + } else { + ts->margin_inactive_pixel[2] = val[2]; + ts->margin_inactive_raw[2] = ts->ts_raw_pos[1] - val[2] * + ts->ts_raw_width / ts->display_width; + } + + if (val[3] < 0 || val[3] > ts->display_width) { /* Bottom */ + ts->margin_inactive_pixel[3] = 0; + ts->margin_inactive_raw[3] = ts->max[1]; + } else { + ts->margin_inactive_pixel[3] = val[3]; + ts->margin_inactive_raw[3] = ts->ts_raw_pos[1] - val[3] * + ts->ts_raw_width / ts->display_width; + } + } + + return count; +} + +/* sys/class/input/inputX/margin_area */ +static DEVICE_ATTR(margin_area, 0600, margin_area_show, margin_area_store); + +static void margin_filter(struct synaptics_ts_data *ts, int pos[2][2], + const int finger2_pressed, const int z) +{ + if (ts->grip_suppression[0] != 2) { + if (pos[0][0] < ts->margin_inactive_raw[0] || + pos[0][0] > ts->margin_inactive_raw[3]) + ts->grip_suppression[0] = 1; + else if ((pos[0][0] < ts->margin_inactive_raw[1] || + pos[0][0] > ts->margin_inactive_raw[2]) && ts->grip_suppression[0]) + ts->grip_suppression[0] = 1; + else + ts->grip_suppression[0] = 2; + } + if (finger2_pressed && ts->grip_suppression[1] != 2) { + if (pos[1][0] < ts->margin_inactive_raw[0] || + pos[1][0] > ts->margin_inactive_raw[3]) + ts->grip_suppression[1] = 1; + else if ((pos[1][0] < ts->margin_inactive_raw[1] || + pos[1][0] > ts->margin_inactive_raw[2]) && + ts->grip_suppression[1]) + ts->grip_suppression[1] = 1; + else + ts->grip_suppression[1] = 2; + } + + if (z == 0) { + /* Finger left, re-enable margin filter for next touch event */ + ts->grip_suppression[0] = ts->grip_suppression[1] = 0; + } +} + +#ifdef CONFIG_TOUCHSCREEN_DUPLICATED_FILTER +static int duplicated_filter(struct synaptics_ts_data *ts, int pos[2][2], + const int finger2_pressed, const int z) +{ + int drift_x[2]; + int drift_y[2]; + static int ref_x[2], ref_y[2]; + uint8_t discard[2] = {0, 0}; + + drift_x[0] = abs(ref_x[0] - pos[0][0]); + drift_y[0] = abs(ref_y[0] - pos[0][1]); + if (finger2_pressed) { + drift_x[1] = abs(ref_x[1] - pos[1][0]); + drift_y[1] = abs(ref_y[1] - pos[1][1]); + } + /* printk("ref_x :%d, ref_y: %d, x: %d, y: %d\n", ref_x, ref_y, pos[0][0], pos[0][1]); */ + if (drift_x[0] < ts->dup_threshold && drift_y[0] < ts->dup_threshold && z != 0) { + /* printk("ref_x :%d, ref_y: %d, x: %d, y: %d\n", ref_x[0], ref_y[0], pos[0][0], pos[0][1]); */ + discard[0] = 1; + } + if (!finger2_pressed || (drift_x[1] < ts->dup_threshold && drift_y[1] < ts->dup_threshold)) { + discard[1] = 1; + } + if (discard[0] && discard[1]) { + /* if finger 0 and finger 1's movement < threshold , discard it. */ + return 1; + } + ref_x[0] = pos[0][0]; + ref_y[0] = pos[0][1]; + if (finger2_pressed) { + ref_x[1] = pos[1][0]; + ref_y[1] = pos[1][1]; + } + if (z == 0) { + ref_x[0] = ref_y[0] = 0; + ref_x[1] = ref_y[1] = 0; + } + + return 0; +} +#endif /* CONFIG_TOUCHSCREEN_DUPLICATED_FILTER */ + +static int synaptics_touch_sysfs_init(void) +{ + int ret; + android_touch_kobj = kobject_create_and_add("android_touch", NULL); + if (android_touch_kobj == NULL) { + printk(KERN_ERR "%s: subsystem_register failed\n", __func__); + ret = -ENOMEM; + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_vendor.attr); + if (ret) { + printk(KERN_ERR "touch_sysfs_init: sysfs_create_group failed\n"); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_debug_level.attr); + if (ret) { + printk(KERN_ERR "%s: sysfs_create_file failed\n", __func__); + return ret; + } + return 0; +} + +static void synaptics_touch_sysfs_remove(void) +{ + sysfs_remove_file(android_touch_kobj, &dev_attr_debug_level.attr); + kobject_del(android_touch_kobj); +} + static int synaptics_init_panel(struct synaptics_ts_data *ts) { int ret; @@ -151,13 +530,21 @@ static void synaptics_ts_work_func(struc /* int dx = (int8_t)buf[12]; */ /* int dy = (int8_t)buf[13]; */ - int finger2_pressed; + int finger2_pressed = finger > 1 && finger != 7; /* printk("x %4d, y %4d, z %3d, w %2d, F %d, 2nd: x %4d, y %4d, z %3d, w %2d, F %d, dx %4d, dy %4d\n", */ /* x, y, z, w, finger, */ /* x2, y2, z2, w2, finger2, */ /* dx, dy); */ + /* debug log level 1 */ + if (ts->debug_log_level & 0x1) { + printk("%s: raw data:", __func__); + for (i = 0; i < buf_len; i++) + printk(" %2x", buf[i]); + printk("\n"); + } + base = 2; for (f = 0; f < 2; f++) { uint32_t flip_flag = SYNAPTICS_FLIP_X; @@ -192,6 +579,8 @@ static void synaptics_ts_work_func(struc if (ts->flags & SYNAPTICS_SWAP_XY) swap(pos[f][0], pos[f][1]); } + +#ifdef CONFIG_TOUCHSCREEN_COMPATIBLE_REPORT if (z) { input_report_abs(ts->input_dev, ABS_X, pos[0][0]); input_report_abs(ts->input_dev, ABS_Y, pos[0][1]); @@ -199,26 +588,76 @@ static void synaptics_ts_work_func(struc input_report_abs(ts->input_dev, ABS_PRESSURE, z); input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, w); input_report_key(ts->input_dev, BTN_TOUCH, finger); - finger2_pressed = finger > 1 && finger != 7; input_report_key(ts->input_dev, BTN_2, finger2_pressed); if (finger2_pressed) { input_report_abs(ts->input_dev, ABS_HAT0X, pos[1][0]); input_report_abs(ts->input_dev, ABS_HAT0Y, pos[1][1]); } +#endif if (!finger) z = 0; - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, z); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, pos[0][0]); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pos[0][1]); - input_mt_sync(ts->input_dev); + +#ifdef ENABLE_IME_IMPROVEMENT + if (ts->ime_threshold_pixel > 0) { + ret = ime_report_filter(ts, pos, finger2_pressed, z); + if (ret == 1) { + /* printk("%s: ime_report_filter\n", __func__); */ + break; + } + } +#endif + + /** + * Margin filter + */ + if (ts->margin_inactive_pixel[0] || ts->margin_inactive_pixel[1] || + ts->margin_inactive_pixel[2] || ts->margin_inactive_pixel[3]) { + margin_filter(ts, pos, finger2_pressed, z); + } else { + ts->grip_suppression[0] = 2; + ts->grip_suppression[1] = 2; + } + +#ifdef CONFIG_TOUCHSCREEN_DUPLICATED_FILTER + /** + * Small movement report would seem as duplicated report, discard it + */ + ret = duplicated_filter(ts, pos, finger2_pressed, z); + if (ret == 1) { + /* printk("%s: duplicated_filter\n", __func__); */ + break; + } +#endif +#ifdef CONFIG_TOUCHSCREEN_CONCATENATE_REPORT + /** + * We concatenate z, w, x, y info to reduce the number of reports in event hub + */ + if (ts->grip_suppression[0] == 2 || z == 0) { + input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, z << 16 | w); + input_report_abs(ts->input_dev, ABS_MT_POSITION, + (!(finger2_pressed && ts->grip_suppression[1] == 2)) << 31 | pos[0][0] << 16 | pos[0][1]); + } + if (finger2_pressed && ts->grip_suppression[1] == 2) { + input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, z << 16 | w); + input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31 | pos[1][0] << 16 | pos[1][1]); + } +#else + if (ts->grip_suppression[0] == 2 || z == 0) { + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, z); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, pos[0][0]); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pos[0][1]); + input_mt_sync(ts->input_dev); + } if (finger2_pressed) { + if (ts->grip_suppression[1] == 2) { input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, z); input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); input_report_abs(ts->input_dev, ABS_MT_POSITION_X, pos[1][0]); input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pos[1][1]); input_mt_sync(ts->input_dev); + } } else if (ts->reported_finger_count > 1) { input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); @@ -226,6 +665,27 @@ static void synaptics_ts_work_func(struc } ts->reported_finger_count = finger; input_sync(ts->input_dev); +#endif /* CONFIG_TOUCHSCREEN_CONCATENATE_REPORT */ + if (!ts->key_pressed[0] && finger) { + ts->key_pressed[0] = 1; + printk(KERN_INFO "S1@%d, %d\n", pos[0][0], pos[0][1]); + } else if (ts->key_pressed[0] == 1 && !finger) { + ts->key_pressed[0] = 2; + printk(KERN_INFO "E1@%d, %d\n", pos[0][0], pos[0][1]); + } + if (ts->key_pressed[0] == 1 && !ts->key_pressed[1] && finger2_pressed) { + ts->key_pressed[1] = 1; + printk(KERN_INFO "S2@%d, %d\n", pos[1][0], pos[1][1]); + } else if (ts->key_pressed[1] && !finger2_pressed) { + ts->key_pressed[1] = 0; + printk(KERN_INFO "E2@%d, %d\n", pos[1][0], pos[1][1]); + } + /* debug log level 2 */ + if (ts->debug_log_level & 0x2) { + printk("X1 %4d, Y1 %4d, Z %3d, W %2d, F1 %d, X2 %4d, Y2 %4d, F2 %d\n", + pos[0][0], pos[0][1], z, w, finger, + pos[1][0], pos[1][1], finger2_pressed); + } } } } @@ -279,6 +739,7 @@ static int synaptics_ts_probe( int snap_bottom_on; int snap_bottom_off; uint32_t panel_version; + int i; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { printk(KERN_ERR "synaptics_ts_probe: need I2C_FUNC_I2C\n"); @@ -291,7 +752,6 @@ static int synaptics_ts_probe( ret = -ENOMEM; goto err_alloc_data_failed; } - INIT_WORK(&ts->work, synaptics_ts_work_func); ts->client = client; i2c_set_clientdata(client, ts); pdata = client->dev.platform_data; @@ -325,6 +785,7 @@ static int synaptics_ts_probe( } printk(KERN_INFO "synaptics_ts_probe: Product Major Version %x\n", ret); panel_version = ret << 8; + syn_panel_version = panel_version; ret = i2c_smbus_read_byte_data(ts->client, 0xe5); if (ret < 0) { printk(KERN_ERR "i2c_smbus_read_byte_data failed\n"); @@ -362,6 +823,11 @@ static int synaptics_ts_probe( fuzz_y = pdata->fuzz_y; fuzz_p = pdata->fuzz_p; fuzz_w = pdata->fuzz_w; + ts->dup_threshold = pdata->dup_threshold; + ts->display_width = pdata->display_width; + ts->display_height = pdata->display_height; + if (!ts->display_width || !ts->display_height) + ts->display_width = ts->display_height = 1; } else { irqflags = 0; inactive_area_left = 0; @@ -380,6 +846,12 @@ static int synaptics_ts_probe( fuzz_y = 0; fuzz_p = 0; fuzz_w = 0; + ts->display_width = 1; + ts->display_height = 1; + } + + for (i = 0; i < 4 ; i++) { + ts->margin_inactive_pixel[i] = pdata->margin_inactive_pixel[i]; } ret = i2c_smbus_read_byte_data(ts->client, 0xf0); @@ -453,6 +925,11 @@ static int synaptics_ts_probe( goto err_detect_failed; } + synaptics_wq = create_singlethread_workqueue("synaptics_wq"); + if (!synaptics_wq) + goto err_create_wq_failed; + INIT_WORK(&ts->work, synaptics_ts_work_func); + ts->input_dev = input_allocate_device(); if (ts->input_dev == NULL) { ret = -ENOMEM; @@ -491,6 +968,20 @@ static int synaptics_ts_probe( ts->snap_down_off[!(ts->flags & SYNAPTICS_SWAP_XY)] = snap_top_off; ts->snap_up_on[!(ts->flags & SYNAPTICS_SWAP_XY)] = max_y - snap_bottom_on; ts->snap_up_off[!(ts->flags & SYNAPTICS_SWAP_XY)] = max_y - snap_bottom_off; + ts->ts_raw_pos[0] = -inactive_area_left; + ts->ts_raw_pos[1] = max_x + inactive_area_right; + ts->ts_raw_pos[2] = -inactive_area_top; + ts->ts_raw_pos[3] = max_y + inactive_area_bottom; + ts->ts_raw_width = ts->ts_raw_pos[1] - ts->ts_raw_pos[0]; /* ts raw width */ + ts->ts_raw_height = ts->ts_raw_pos[3] - ts->ts_raw_pos[2]; /* ts raw height */ + ts->margin_inactive_raw[0] = ts->ts_raw_pos[0] + ts->margin_inactive_pixel[0] * + ts->ts_raw_width / ts->display_width; + ts->margin_inactive_raw[1] = ts->ts_raw_pos[0] + ts->margin_inactive_pixel[1] * + ts->ts_raw_width / ts->display_width; + ts->margin_inactive_raw[2] = ts->ts_raw_pos[1] - ts->margin_inactive_pixel[2] * + ts->ts_raw_width / ts->display_width; + ts->margin_inactive_raw[3] = ts->ts_raw_pos[1] - ts->margin_inactive_pixel[3] * + ts->ts_raw_width / ts->display_width; printk(KERN_INFO "synaptics_ts_probe: max_x %d, max_y %d\n", max_x, max_y); printk(KERN_INFO "synaptics_ts_probe: inactive_x %d %d, inactive_y %d %d\n", inactive_area_left, inactive_area_right, @@ -498,22 +989,65 @@ static int synaptics_ts_probe( printk(KERN_INFO "synaptics_ts_probe: snap_x %d-%d %d-%d, snap_y %d-%d %d-%d\n", snap_left_on, snap_left_off, snap_right_on, snap_right_off, snap_top_on, snap_top_off, snap_bottom_on, snap_bottom_off); + printk(KERN_INFO "synaptics_ts_probe: margin_pixel_left: %d, margin_pixel_right: %d, " + "margin_pixel_top: %d, margin_pixel_bottom: %d\n", + ts->margin_inactive_pixel[0], ts->margin_inactive_pixel[1], + ts->margin_inactive_pixel[2], ts->margin_inactive_pixel[3]); + printk(KERN_INFO "synaptics_ts_probe: ts_raw_width: %d, ts_raw_height: %d\n", + ts->ts_raw_width, ts->ts_raw_height); +#ifdef CONFIG_TOUCHSCREEN_COMPATIBLE_REPORT input_set_abs_params(ts->input_dev, ABS_X, -inactive_area_left, max_x + inactive_area_right, fuzz_x, 0); input_set_abs_params(ts->input_dev, ABS_Y, -inactive_area_top, max_y + inactive_area_bottom, fuzz_y, 0); input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, fuzz_p, 0); input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, 15, fuzz_w, 0); input_set_abs_params(ts->input_dev, ABS_HAT0X, -inactive_area_left, max_x + inactive_area_right, fuzz_x, 0); input_set_abs_params(ts->input_dev, ABS_HAT0Y, -inactive_area_top, max_y + inactive_area_bottom, fuzz_y, 0); +#endif input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, -inactive_area_left, max_x + inactive_area_right, fuzz_x, 0); input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, -inactive_area_top, max_y + inactive_area_bottom, fuzz_y, 0); input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, fuzz_p, 0); input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 15, fuzz_w, 0); +#ifdef CONFIG_TOUCHSCREEN_CONCATENATE_REPORT + input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((255 << 16) | 255), 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, ((1 << 31) | (max_x << 16) | max_y), 0, 0); +#endif /* ts->input_dev->name = ts->keypad_info->name; */ ret = input_register_device(ts->input_dev); if (ret) { printk(KERN_ERR "synaptics_ts_probe: Unable to register %s input device\n", ts->input_dev->name); goto err_input_register_device_failed; } + + gl_ts = ts; + +#ifdef ENABLE_IME_IMPROVEMENT + ts->ime_threshold_pixel = 0; + + ret = device_create_file(&ts->input_dev->dev, &dev_attr_ime_threshold); + if (ret) { + printk(KERN_ERR "ENABLE_IME_IMPROVEMENT: " + "Error to create ime_threshold\n"); + goto err_input_register_device_failed; + } + ret = device_create_file(&ts->input_dev->dev, &dev_attr_ime_work_area); + if (ret) { + printk(KERN_ERR "ENABLE_IME_IMPROVEMENT: " + "Error to create ime_work_area\n"); + device_remove_file(&ts->input_dev->dev, + &dev_attr_ime_threshold); + goto err_input_register_device_failed; + } + +#endif + + /* For margin filter*/ + ret = device_create_file(&ts->input_dev->dev, &dev_attr_margin_area); + if (ret) { + printk(KERN_ERR "MARGIN_FILTER: " + "Error to create margin_area\n"); + goto err_input_register_device_failed; + } + if (client->irq) { ret = request_irq(client->irq, synaptics_ts_irq_handler, irqflags, client->name, ts); if (ret == 0) { @@ -532,12 +1066,14 @@ static int synaptics_ts_probe( hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); } #ifdef CONFIG_HAS_EARLYSUSPEND - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1; ts->early_suspend.suspend = synaptics_ts_early_suspend; ts->early_suspend.resume = synaptics_ts_late_resume; register_early_suspend(&ts->early_suspend); #endif + synaptics_touch_sysfs_init(); + printk(KERN_INFO "synaptics_ts_probe: Start touchscreen %s in %s mode\n", ts->input_dev->name, ts->use_irq ? "interrupt" : "polling"); return 0; @@ -546,9 +1082,13 @@ err_input_register_device_failed: input_free_device(ts->input_dev); err_input_dev_alloc_failed: + destroy_workqueue(synaptics_wq); + +err_create_wq_failed: err_detect_failed: err_power_failed: kfree(ts); + err_alloc_data_failed: err_check_functionality_failed: return ret; @@ -563,6 +1103,16 @@ static int synaptics_ts_remove(struct i2 else hrtimer_cancel(&ts->timer); input_unregister_device(ts->input_dev); + +#ifdef ENABLE_IME_IMPROVEMENT + device_remove_file(&ts->input_dev->dev, &dev_attr_ime_threshold); + device_remove_file(&ts->input_dev->dev, &dev_attr_ime_work_area); +#endif + /* For margin filter */ + device_remove_file(&ts->input_dev->dev, &dev_attr_margin_area); + + synaptics_touch_sysfs_remove(); + kfree(ts); return 0; } @@ -583,6 +1133,8 @@ static int synaptics_ts_suspend(struct i if (ret < 0) printk(KERN_ERR "synaptics_ts_suspend: i2c_smbus_write_byte_data failed\n"); + ts->key_pressed[0] = 0; + ret = i2c_smbus_write_byte_data(client, 0xf0, 0x86); /* deep sleep */ if (ret < 0) printk(KERN_ERR "synaptics_ts_suspend: i2c_smbus_write_byte_data failed\n"); @@ -654,9 +1206,6 @@ static struct i2c_driver synaptics_ts_dr static int __devinit synaptics_ts_init(void) { - synaptics_wq = create_singlethread_workqueue("synaptics_wq"); - if (!synaptics_wq) - return -ENOMEM; return i2c_add_driver(&synaptics_ts_driver); } --- a/include/linux/curcial_oj.h +++ b/include/linux/curcial_oj.h @@ -36,6 +36,8 @@ struct curcial_oj_platform_data { #endif unsigned irq_gpio; + unsigned rst_gpio; + uint8_t ledval; }; void curcial_oj_send_key(unsigned int code, int value); --- a/include/linux/synaptics_i2c_rmi.h +++ b/include/linux/synaptics_i2c_rmi.h @@ -20,6 +20,7 @@ #define SYNAPTICS_I2C_RMI_NAME "synaptics-rmi-ts" #define SYNAPTICS_T1007_NAME "synaptics-t1007" #define SYNAPTICS_T1021_NAME "synaptics-t1021" +#define SYNAPTICS_3K_NAME "synaptics-3k" enum { SYNAPTICS_FLIP_X = 1UL << 0, @@ -47,6 +48,7 @@ struct synaptics_i2c_rmi_platform_data { struct synaptics_virtual_key *virtual_key; uint8_t virtual_key_num; uint8_t sensitivity; + uint8_t finger_support; uint32_t gap_area; uint32_t key_area; uint32_t flags; @@ -65,6 +67,10 @@ struct synaptics_i2c_rmi_platform_data { uint32_t snap_bottom_off; /* 0x10000 = screen height */ uint32_t fuzz_x; /* 0x10000 = screen width */ uint32_t fuzz_y; /* 0x10000 = screen height */ + uint16_t abs_x_min; + uint16_t abs_x_max; + uint16_t abs_y_min; + uint16_t abs_y_max; int fuzz_p; int fuzz_w; uint32_t display_width; @@ -79,4 +85,11 @@ struct page_description { uint8_t value; }; +struct syn_finger_data { + int x; + int y; + int w; + int z; +}; + #endif /* _LINUX_SYNAPTICS_I2C_RMI_H */