/drivers/input/touchscreen/sun4i-ts.c
C | 1877 lines | 1371 code | 272 blank | 234 comment | 197 complexity | d39650a37f7cf8225540a4eb96c568c7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
1/* This program is free software; you can redistribute it and/or modify 2* it under the terms of the GNU General Public License as published by 3* the Free Software Foundation; either version 2 of the License, or 4* (at your option) any later version. 5* 6* This program is distributed in the hope that it will be useful, 7* but WITHOUT ANY WARRANTY; without even the implied warranty of 8* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9* GNU General Public License for more details. 10* 11* You should have received a copy of the GNU General Public License 12* along with this program; if not, write to the Free Software 13* 14* Copyright (c) 2009 15* 16* ChangeLog 17* 18* 19*/ 20#include <linux/interrupt.h> 21#include <linux/errno.h> 22#include <linux/kernel.h> 23#include <linux/module.h> 24#include <linux/slab.h> 25#include <linux/input.h> 26#include <linux/device.h> 27#include <linux/platform_device.h> 28#include <linux/init.h> 29#include <linux/delay.h> 30#include <linux/ioport.h> 31#include <asm/irq.h> 32#include <asm/io.h> 33#include <linux/fs.h> 34#include <asm/uaccess.h> 35#include <linux/mm.h> 36#include <linux/slab.h> 37#include <linux/timer.h> 38#include <linux/jiffies.h> 39#include <linux/tick.h> 40#include <asm-generic/cputime.h> 41 42#include <mach/system.h> 43#include <mach/hardware.h> 44#include <mach/sys_config.h> 45 46#ifdef CONFIG_HAS_EARLYSUSPEND 47 #include <linux/pm.h> 48 #include <linux/earlysuspend.h> 49#endif 50 51//#undef CONFIG_HAS_EARLYSUSPEND 52 53static int tp_flag = 0; 54 55//tp status value 56#define TP_INITIAL (-1) 57#define TP_DOWN (0) 58#define TP_UP (1) 59#define TP_DATA_VA (2) 60//? 61#define DUAL_TOUCH (dual_touch_distance) 62#define TOUCH_CHANGE (3) 63#define TP_DATA_AV_NO (0x3) 64 65//#define PRINT_INT_INFO 66//#define PRINT_FILTER_INFO 67//#define PRINT_REPORT_STATUS_INFO 68//#define PRINT_REPORT_DATA_INFO 69//#define PRINT_TASKLET_INFO 70#define CONFIG_TOUCHSCREEN_SUN4I_DEBUG 71#define PRINT_SUSPEND_INFO 72//#define PRINT_FILTER_DOUBLE_POINT_STATUS_INFO 73//#define PRINT_ORIENTATION_INFO 74//#define FIX_ORIENTATION 75#define ORIENTATION_DEFAULT_VAL (-1) 76//#define TP_INT_PERIOD_TEST 77//#define TP_TEMP_DEBUG 78//#define TP_FREQ_DEBUG 79//#define PRINT_UP_SEPARATOR 80#define TP_FIX_CENTER 81 82#define IRQ_TP (29) 83#define TP_BASSADDRESS (0xf1c25000) 84#define TP_CTRL0 (0x00) 85#define TP_CTRL1 (0x04) 86#define TP_CTRL2 (0x08) 87#define TP_CTRL3 (0x0c) 88#define TP_INT_FIFOC (0x10) 89#define TP_INT_FIFOS (0x14) 90#define TP_TPR (0x18) 91#define TP_CDAT (0x1c) 92#define TEMP_DATA (0x20) 93#define TP_DATA (0x24) 94 95 96#define ADC_FIRST_DLY (0x1<<24) 97#define ADC_FIRST_DLY_MODE (0x1<<23) 98#define ADC_CLK_SELECT (0x0<<22) 99#define ADC_CLK_DIVIDER (0x2<<20) 100//#define CLK (6) 101#define CLK (7) 102#define FS_DIV (CLK<<16) 103#define ACQ (0x3f) 104#define T_ACQ (ACQ) 105 106#define STYLUS_UP_DEBOUNCE (0<<12) 107#define STYLUS_UP_DEBOUCE_EN (0<<9) 108#define TOUCH_PAN_CALI_EN (1<<6) 109#define TP_DUAL_EN (1<<5) 110#define TP_MODE_EN (1<<4) 111#define TP_ADC_SELECT (0<<3) 112#define ADC_CHAN_SELECT (0) 113 114//#define TP_SENSITIVE_ADJUST (0xf<<28) 115#define TP_SENSITIVE_ADJUST (tp_sensitive_level<<28) //mark by young for test angda 5" 0xc 116#define TP_MODE_SELECT (0x1<<26) 117#define PRE_MEA_EN (0x1<<24) 118#define PRE_MEA_THRE_CNT (tp_press_threshold<<0) //0x1f40 119 120 121#define FILTER_EN (1<<2) 122#define FILTER_TYPE (0x01<<0) 123 124#define TP_DATA_IRQ_EN (1<<16) 125#define TP_DATA_XY_CHANGE (tp_exchange_x_y<<13) //tp_exchange_x_y 126#define TP_FIFO_TRIG_LEVEL (3<<8) 127#define TP_FIFO_FLUSH (1<<4) 128#define TP_UP_IRQ_EN (1<<1) 129#define TP_DOWN_IRQ_EN (1<<0) 130 131#define FIFO_DATA_PENDING (1<<16) 132#define TP_UP_PENDING (1<<1) 133#define TP_DOWN_PENDING (1<<0) 134 135#define SINGLE_TOUCH_MODE (1) 136#define CHANGING_TO_DOUBLE_TOUCH_MODE (2) 137#define DOUBLE_TOUCH_MODE (3) 138#define UP_TOUCH_MODE (4) 139 140#define SINGLE_CNT_LIMIT (40) 141#define DOUBLE_CNT_LIMIT (2) 142#define UP_TO_SINGLE_CNT_LIMIT (10) 143 144#define TPDATA_MASK (0xfff) 145#define FILTER_NOISE_LOWER_LIMIT (2) 146#define MAX_DELTA_X (700-100) // avoid excursion 147#define MAX_DELTA_Y (1200-200) 148#define X_TURN_POINT (330) // x1 < (1647 - MAX_DELTA_X) /3 149#define X_COMPENSATE (4*X_TURN_POINT) 150#define Y_TURN_POINT (260) // y1 < (1468 -MAX_DELTA_Y ) 151#define Y_COMPENSATE (2*Y_TURN_POINT) 152 153#ifdef TP_FIX_CENTER 154#define X_CENTER_COORDINATE (2048) //for construct two point 155#define Y_CENTER_COORDINATE (2048) 156#else 157#define X_CENTER_COORDINATE (sample_data->x) 158#define Y_CENTER_COORDINATE (sample_data->y) 159#endif 160 161#define CYCLE_BUFFER_SIZE (64) //must be 2^n 162#define DELAY_PERIOD (6) //delay 60 ms, unit is 10ms 163#define DELAY_COMPENSTAE_PEROID (3) //the os is busy, can not process the data in time. 164 165#define ZOOM_CHANGE_LIMIT_CNT (3) 166#define ZOOM_IN (1) 167#define ZOOM_OUT (2) 168#define ZOOM_INIT_STATE (3) 169#define ZOOM_STATIC (4) 170 171#define SAMPLE_TIME (9.6) //unit is ms. ??? 172#define SAMPLE_TIME_FACTOR (9.6/SAMPLE_TIME) 173 174#ifndef TRUE 175#define TRUE 1 176#define FALSE 0 177#endif 178 179#ifdef PRINT_INT_INFO 180#define print_int_info(fmt, args...) \ 181 do{ \ 182 printk(fmt, ##args); \ 183 }while(0) 184#else 185#define print_int_info(fmt, args...) // 186#endif 187 188#ifdef PRINT_FILTER_INFO 189#define print_filter_info(fmt, args...) \ 190 do{ \ 191 printk(fmt, ##args); \ 192 }while(0) 193#else 194#define print_filter_info(fmt, args...) // 195#endif 196 197#ifdef PRINT_REPORT_STATUS_INFO 198#define print_report_status_info(fmt, args...) \ 199 do{ \ 200 printk(fmt, ##args); \ 201 }while(0) 202#else 203#define print_report_status_info(fmt, args...) // 204#endif 205 206#ifdef PRINT_REPORT_DATA_INFO 207#define print_report_data_info(fmt, args...) \ 208 do{ \ 209 printk(fmt, ##args); \ 210 }while(0) 211#else 212#define print_report_data_info(fmt, args...) // 213#endif 214 215#ifdef PRINT_TASKLET_INFO 216#define print_tasklet_info(fmt, args...) \ 217 do{ \ 218 printk(fmt, ##args); \ 219 }while(0) 220#else 221#define print_tasklet_info(fmt, args...) // 222#endif 223 224#ifdef PRINT_FILTER_DOUBLE_POINT_STATUS_INFO 225#define print_filter_double_point_status_info(fmt, args...) \ 226 do{ \ 227 printk(fmt, ##args); \ 228 }while(0) 229#else 230#define print_filter_double_point_status_info(fmt, args...) // 231#endif 232 233#ifdef PRINT_ORIENTATION_INFO 234#define print_orientation_info(fmt, args...) \ 235 do{ \ 236 printk(fmt, ##args); \ 237 }while(0) 238#else 239#define print_orientation_info(fmt, args...) // 240#endif 241 242struct sun4i_ts_data { 243 struct resource *res; 244 struct input_dev *input; 245 void __iomem *base_addr; 246 int irq; 247 char phys[32]; 248 unsigned int count; //for report threshold & touchmod(double to single touch mode) change 249 unsigned long buffer_head; //for cycle buffer 250 unsigned long buffer_tail; 251 int ts_sample_status; //for touchscreen status when sampling 252 int ts_process_status; //for record touchscreen status when process data 253 int double_point_cnt; //for noise reduction when in double_touch_mode 254 int single_touch_cnt; //for noise reduction when change to double_touch_mode 255 int ts_delay_period; //will determine responding sensitivity 256 int touchflag; 257#ifdef CONFIG_HAS_EARLYSUSPEND 258 struct early_suspend early_suspend; 259#endif 260}; 261 262struct ts_sample_data{ 263 unsigned int x1; 264 unsigned int y1; 265 unsigned int x; 266 unsigned int y; 267 unsigned int dx; 268 unsigned int dy; 269 unsigned int z1; 270 unsigned int z2; 271 int sample_status; //record the sample point status when sampling 272 unsigned int sample_time; 273}; 274 275struct sun4i_ts_data * mtTsData =NULL; 276static int touch_mode = UP_TOUCH_MODE; 277static int change_mode = TRUE; 278static int tp_irq_state = TRUE; 279 280#ifdef PRINT_INT_INFO 281static cputime64_t cur_wall_time = 0L; 282#endif 283 284//static cputime64_t cur_idle_time = 0L; 285 286static struct ts_sample_data cycle_buffer[CYCLE_BUFFER_SIZE] = {{0},}; 287static struct ts_sample_data *prev_sample; 288static struct ts_sample_data *prev_data_sample; 289static struct timer_list data_timer; 290static int data_timer_status = 0; //when 1, mean tp driver have recervied data, and begin to report data, and start timer to reduce up&down signal 291static struct ts_sample_data prev_single_sample; 292static struct ts_sample_data prev_double_sample_data; 293static struct ts_sample_data prev_report_samp; 294static int orientation_flag = 0; 295static int zoom_flag = 0; 296static int accmulate_zoom_out_ds = 0; 297static int accmulate_zoom_in_ds = 0; 298static int zoom_in_count = 0; 299static int zoom_out_count = 0; 300static int zoom_change_cnt = 0; 301static int hold_cnt = 0; 302//config from sysconfig files. 303static int glide_delta_ds_max_limit = 0; 304static int tp_regidity_level = 0; 305static int tp_press_threshold_enable = 0; 306static int tp_press_threshold = 0; //usded to adjust sensitivity of touch 307static int tp_sensitive_level = 0; //used to adjust sensitivity of pen down detection 308static int tp_exchange_x_y = 0; 309 310#define ZOOM_IN_OUT_BUFFER_SIZE_TIMES (2) 311#define ZOOM_IN_OUT_BUFFER_SIZE (1<<ZOOM_IN_OUT_BUFFER_SIZE_TIMES) 312#define TRANSFER_DATA_BUFFER_SIZE (4) 313 314static struct ts_sample_data zoom_in_data_buffer[ZOOM_IN_OUT_BUFFER_SIZE] = {{0},}; 315static struct ts_sample_data zoom_out_data_buffer[ZOOM_IN_OUT_BUFFER_SIZE] = {{0},}; 316static struct ts_sample_data transfer_data_buffer[TRANSFER_DATA_BUFFER_SIZE] = {{0},}; 317 318static int zoom_in_buffer_cnt = 0; 319static int zoom_out_buffer_cnt = 0; 320 321static spinlock_t tp_do_tasklet_sync; 322static int tp_do_tasklet_running = 0; 323//for test 324//static int tp_irq = 0; 325static int dual_touch_distance = 0; 326 327#ifdef PRINT_UP_SEPARATOR 328 static int separator_flag = 0; 329#endif 330 331static int reported_single_point_cnt = 0; 332static int reported_data_start_time = 0; 333 334static atomic_t report_up_event_implement_sync = ATOMIC_INIT(1); 335static int report_up_event_implement_running = 0; 336 337static int reference_point_flag = 1; 338 339void tp_do_tasklet(unsigned long data); 340DECLARE_TASKLET(tp_tasklet,tp_do_tasklet,0); 341 342//???? 343#ifdef CONFIG_HAS_EARLYSUSPEND 344static void sun4i_ts_suspend(struct early_suspend *h) 345{ 346 /*int ret; 347 struct sun4i_ts_data *ts = container_of(h, struct sun4i_ts_data, early_suspend); 348 */ 349 #ifdef PRINT_SUSPEND_INFO 350 printk("enter earlysuspend: sun4i_ts_suspend. \n"); 351 #endif 352 writel(0,TP_BASSADDRESS + TP_CTRL1); 353 return ; 354} 355 356//???? 357static void sun4i_ts_resume(struct early_suspend *h) 358{ 359 /*int ret; 360 struct sun4i_ts_data *ts = container_of(h, struct sun4i_ts_data, early_suspend); 361 */ 362 #ifdef PRINT_SUSPEND_INFO 363 printk("enter laterresume: sun4i_ts_resume. \n"); 364 #endif 365 writel(STYLUS_UP_DEBOUNCE|STYLUS_UP_DEBOUCE_EN|TP_DUAL_EN|TP_MODE_EN,TP_BASSADDRESS + TP_CTRL1); 366 return ; 367} 368#else 369//???? 370#ifdef CONFIG_PM 371static int sun4i_ts_suspend(struct platform_device *pdev, pm_message_t state) 372{ 373 #ifdef PRINT_SUSPEND_INFO 374 printk("enter: sun4i_ts_suspend. \n"); 375 #endif 376 377 writel(0,TP_BASSADDRESS + TP_CTRL1); 378 return 0; 379} 380 381static int sun4i_ts_resume(struct platform_device *pdev) 382{ 383 #ifdef PRINT_SUSPEND_INFO 384 printk("enter: sun4i_ts_resume. \n"); 385 #endif 386 387 writel(STYLUS_UP_DEBOUNCE|STYLUS_UP_DEBOUCE_EN|TP_DUAL_EN|TP_MODE_EN,TP_BASSADDRESS + TP_CTRL1); 388 return 0; 389} 390#endif 391 392#endif 393 394 395static int tp_init(void) 396{ 397 //struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)platform_get_drvdata(pdev); 398// struct sun4i_ts_data *ts_data = mtTsData; 399 //TP_CTRL0: 0x0027003f 400 #ifdef TP_FREQ_DEBUG 401 writel(0x0028001f, TP_BASSADDRESS + TP_CTRL0); 402 #else 403 writel(ADC_CLK_DIVIDER|FS_DIV|T_ACQ, TP_BASSADDRESS + TP_CTRL0); 404 #endif 405 //TP_CTRL2: 0xc4000000 406 if(1 == tp_press_threshold_enable){ 407 writel(TP_SENSITIVE_ADJUST |TP_MODE_SELECT | PRE_MEA_EN | PRE_MEA_THRE_CNT, TP_BASSADDRESS + TP_CTRL2); 408 } 409 else{ 410 writel(TP_SENSITIVE_ADJUST|TP_MODE_SELECT,TP_BASSADDRESS + TP_CTRL2); 411 } 412 413 414 //TP_CTRL3: 0x05 415 #ifdef TP_FREQ_DEBUG 416 writel(0x06, TP_BASSADDRESS + TP_CTRL3); 417 #else 418 writel(FILTER_EN|FILTER_TYPE,TP_BASSADDRESS + TP_CTRL3); 419 #endif 420 421 #ifdef TP_TEMP_DEBUG 422 //TP_INT_FIFOC: 0x00010313 423 writel(TP_DATA_IRQ_EN|TP_FIFO_TRIG_LEVEL|TP_FIFO_FLUSH|TP_UP_IRQ_EN|TP_DOWN_IRQ_EN|0x40000, TP_BASSADDRESS + TP_INT_FIFOC); 424 writel(0x10fff, TP_BASSADDRESS + TP_TPR); 425 #else 426 //TP_INT_FIFOC: 0x00010313 427 writel(TP_DATA_IRQ_EN|TP_FIFO_TRIG_LEVEL|TP_FIFO_FLUSH|TP_UP_IRQ_EN|TP_DOWN_IRQ_EN, TP_BASSADDRESS + TP_INT_FIFOC); 428 #endif 429 //TP_CTRL1: 0x00000070 -> 0x00000030 430 writel(TP_DATA_XY_CHANGE|STYLUS_UP_DEBOUNCE|STYLUS_UP_DEBOUCE_EN|TP_DUAL_EN|TP_MODE_EN,TP_BASSADDRESS + TP_CTRL1); 431 432 433 /* 434 //put_wvalue(TP_CTRL0 ,0x02a6007f); //512us TACQ 4ms FS 60 point 435 //put_wvalue(TP_CTRL0 ,0x0aa7003f); 436 put_wvalue(TP_CTRL0 ,0x00a7003f); //100 point 437 put_wvalue(TP_CTRL1 ,0x00000030); 438 //put_wvalue(TP_INT_FIFOC,0x12f13); 439 put_wvalue(TP_INT_FIFOC,0x10313); 440 //put_wvalue(TP_CTRL2,0x90003e8); 441 //put_wvalue(TP_CTRL2,0x9002710); 442 put_wvalue(TP_CTRL2,0xc4002710); 443 put_wvalue(TP_CTRL3,0x00000005); 444 */ 445 446 /* 447 writel(0x00b70100,TP_BASSADDRESS + TP_CTRL0); 448 writel(0xfd000000,TP_BASSADDRESS + TP_CTRL2); 449 writel(0x4,TP_BASSADDRESS + TP_CTRL3); 450 writel(0x10513,TP_BASSADDRESS +TP_INT_FIFOC); 451 writel(0x00005230,TP_BASSADDRESS + TP_CTRL1);*/ 452 return (0); 453} 454static void change_to_single_touch_mode(void) 455{ 456 touch_mode = SINGLE_TOUCH_MODE; 457 reported_single_point_cnt = 0; 458 return; 459} 460 461static void backup_transfered_data(struct ts_sample_data *sample_data) 462{ 463 static int index = 0; 464 465 index = reported_single_point_cnt%TRANSFER_DATA_BUFFER_SIZE; 466 transfer_data_buffer[index].dx = sample_data->dx; 467 transfer_data_buffer[index].dy = sample_data->dy; 468 transfer_data_buffer[index].x = sample_data->x; 469 transfer_data_buffer[index].y = sample_data->y; 470 471 if(reported_single_point_cnt > (TRANSFER_DATA_BUFFER_SIZE<<10)){ 472 reported_single_point_cnt -= (TRANSFER_DATA_BUFFER_SIZE<<9); 473 } 474 reported_single_point_cnt++; 475 476 return; 477} 478 479static void report_single_point_implement(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 480{ 481 input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,800); 482 input_report_abs(ts_data->input, ABS_MT_POSITION_X, sample_data->x); 483 input_report_abs(ts_data->input, ABS_MT_POSITION_Y, sample_data->y); 484/* 485 print_report_data_info("report single point: x = %d, y = %d\n \ 486 sample_data->dx = %d, sample_data->dy = %d. \n", \ 487 sample_data->x, sample_data->y, sample_data->dx, sample_data->dy); 488 */ 489 print_report_data_info("report single point: x = %d,sample_data->y = %d. \n", sample_data->x, sample_data->y); 490 491 input_mt_sync(ts_data->input); 492 input_sync(ts_data->input); 493 494 return; 495} 496 497static void report_single_point(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 498{ 499 backup_transfered_data(sample_data); 500 report_single_point_implement(ts_data, sample_data); 501 return; 502} 503 504static void report_slide_data(struct sun4i_ts_data *ts_data) 505{ 506 int start = 0; 507 int end = 0; 508#define MIN_DX (DUAL_TOUCH*20) 509#define MIN_DY (DUAL_TOUCH*20) 510#define MAX_DX (DUAL_TOUCH*40) 511#define MAX_DY (DUAL_TOUCH*40) 512 int dx = 0; 513 int dy = 0; 514 int ds_times = 4; 515 //index = reported_single_point_cnt%TRANSFER_DATA_BUFFER_SIZE; 516 struct ts_sample_data sample_data; 517 518 //printk("reported_single_point_cnt = %d. \n", reported_single_point_cnt); 519 if(reported_single_point_cnt <= 1){ 520 //only one reference point, can not judge direction 521 dx = -MIN_DX; 522 dy = MIN_DY; 523 //dy = 0; 524 end = (reported_single_point_cnt-1)%TRANSFER_DATA_BUFFER_SIZE; 525 sample_data.x = max(0, min(4096, (int)(transfer_data_buffer[end].x + dx))); 526 sample_data.y = max(0, min(4096, (int)(transfer_data_buffer[end].y + dy))); 527 //printk("sample_data.x = %d. sample_data.y = %d. \n", sample_data.x, sample_data.y); 528 report_single_point_implement(ts_data, &sample_data); 529 530 sample_data.x = transfer_data_buffer[end].x; 531 sample_data.y = transfer_data_buffer[end].y; 532 //printk("sample_data.x = %d. sample_data.y = %d. \n", sample_data.x, sample_data.y); 533 //report_single_point_implement(ts_data, &sample_data); 534 535 }else{ 536 if(reported_single_point_cnt <=TRANSFER_DATA_BUFFER_SIZE){ 537 start = 0; 538 }else{ 539 start = reported_single_point_cnt - TRANSFER_DATA_BUFFER_SIZE; 540 } 541 start = start%TRANSFER_DATA_BUFFER_SIZE; 542 end = (reported_single_point_cnt-1)%TRANSFER_DATA_BUFFER_SIZE; 543 544 dx = transfer_data_buffer[end].x -transfer_data_buffer[start].x; 545 dy = transfer_data_buffer[end].y -transfer_data_buffer[start].y; 546 //printk("dx = %d, dy = %d. \n", dx, dy); 547 if(dx < 0){ 548 dx = -dx; 549 dx = min(MAX_DX, max(MIN_DX, dx*ds_times/(end - start))); 550 dx = -dx; 551 }else{ 552 dx = min(MAX_DX, max(MIN_DX, dx*ds_times/(end - start))); 553 } 554 555 if(dy < 0){ 556 dy = -dy; 557 dy = min(MAX_DY, max(MIN_DY, dy*ds_times/(end - start))); 558 dy = -dy; 559 }else{ 560 dy = min(MAX_DY, max(MIN_DY, dy*ds_times/(end - start))); 561 } 562 563 //printk("dx = %d, dy = %d. \n", dx, dy); 564 sample_data.x = max(0, min(4096, (int)(transfer_data_buffer[end].x + dx))); 565 sample_data.y = max(0, min(4096, (int)(transfer_data_buffer[end].y + dy))); 566 567 //printk("sample_data.x = %d. sample_data.y = %d. \n", sample_data.x, sample_data.y); 568 report_single_point_implement(ts_data, &sample_data); 569 } 570 } 571 572static void report_up_event_implement(struct sun4i_ts_data *ts_data) 573{ 574 static const int UP_EVENT_DELAY_TIME = 3; 575 static const int SLIDE_MIN_CNT = 3; 576 if(atomic_sub_and_test(1, &report_up_event_implement_sync)){ 577 //get the resource 578 if(1 == report_up_event_implement_running){ 579 atomic_inc(&report_up_event_implement_sync); 580 printk("other thread is running the rountine. \n"); 581 return; 582 }else{ 583 report_up_event_implement_running = 1; 584 atomic_inc(&report_up_event_implement_sync); 585 } 586 }else{ 587 printk("failed to get the lock. other thread is using the lock. \n"); 588 return; 589 } 590 591 if(0 == data_timer_status){ 592 printk("report_up_event_implement have been called. \n"); 593 goto report_up_event_implement_out; 594 return; 595 } 596 597 print_report_status_info("enter report_up_event_implement. jiffies == %lu. \n", jiffies); 598 599 //printk("prev_sample->sample_time =%d, prev_data_sample->sample_time = %d. \n", prev_sample->sample_time, prev_data_sample->sample_time); 600 //printk("touch_mode = %d. reported_single_point_cnt = %d. \n", touch_mode, reported_single_point_cnt); 601 if( (SINGLE_TOUCH_MODE == touch_mode) && \ 602 (reported_single_point_cnt<SLIDE_MIN_CNT) && (reported_single_point_cnt>0) && \ 603 (prev_sample->sample_time >= (prev_data_sample->sample_time + UP_EVENT_DELAY_TIME))){ 604 //obvious, a slide, how to compenstate? 605 //printk("report_up_event_implement: obvious, a slide. \n"); 606 report_slide_data(ts_data); 607 } 608 609 //note: below operation may be interfere by intterrupt, but it does not matter 610 input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,0); 611 input_sync(ts_data->input); 612 del_timer(&data_timer); 613 data_timer_status = 0; 614 ts_data->ts_process_status = TP_UP; 615 ts_data->double_point_cnt = 0; 616 //ts_data->buffer_head = 0; 617 //ts_data->buffer_tail = 0; 618 ts_data->touchflag = 0; 619 //ts_data->count = 0; 620 touch_mode = UP_TOUCH_MODE; 621 change_mode = TRUE; 622 reported_single_point_cnt = 0; 623 reported_data_start_time = 0; 624 625report_up_event_implement_out: 626 report_up_event_implement_running = 0; 627 628#ifdef PRINT_UP_SEPARATOR 629 printk("separator: #######%d, %d, %d###########. \n\n\n\n\n\n\n", separator_flag, separator_flag, separator_flag); 630 separator_flag++; 631#endif 632 633 return; 634} 635 636static int judge_zoom_orientation(struct ts_sample_data *sample_data) 637{ 638 int dx,dy; 639 int ret = 0; 640 if(1 == reference_point_flag){ 641 dx = sample_data->x - prev_single_sample.x; 642 dy = sample_data->y - prev_single_sample.y; 643 if(dx*dy > 0){ 644 ret = -1; 645 }else if(dx*dy < 0){ 646 ret = 1; 647 } 648 }else{ 649 print_orientation_info("judge_zoom_orientation: lack reference point .\n"); 650 } 651 652 print_orientation_info("sun4i-ts: orientation_flag == %d . \n", ret); 653 return ret; 654} 655static void filter_double_point_init(struct ts_sample_data *sample_data, int backup_samp_flag) 656{ 657 //backup prev_double_sample_data 658 zoom_flag = ZOOM_INIT_STATE; 659 accmulate_zoom_out_ds = 0; 660 zoom_out_count = 0; 661 accmulate_zoom_in_ds = 0; 662 zoom_in_count = 0; 663 //printk("sample_data->x = %d, sample_data-> y = %d. \n", sample_data->x, sample_data->y); 664 if(1 == backup_samp_flag){ 665 memcpy((void*)(&prev_double_sample_data), (void*)sample_data, sizeof(*sample_data)); 666 } 667 668 hold_cnt = 0; 669 //when report two point, the first two point will be reserved for reference purpose. 670 return; 671} 672 673static void change_to_double_mode(struct sun4i_ts_data *ts_data) 674{ 675 if((CHANGING_TO_DOUBLE_TOUCH_MODE != touch_mode) && \ 676 (DOUBLE_TOUCH_MODE != touch_mode)&& \ 677 (UP_TOUCH_MODE != touch_mode)){ 678 printk("change_to_double_mode: err, not the expected state. touch_mode = %d. \n", touch_mode); 679 } 680 touch_mode = DOUBLE_TOUCH_MODE; 681 change_mode = FALSE; 682 ts_data->single_touch_cnt = 0; //according this counter, change to single touch mode 683 return; 684} 685 686static void change_to_zoom_in(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 687{ 688 zoom_flag = ZOOM_IN; 689 zoom_change_cnt = 0; 690 accmulate_zoom_out_ds = 0; 691 zoom_out_count = 0; 692 //orientation_flag = judge_zoom_orientation(sample_data); 693 change_to_double_mode(ts_data); 694 return; 695} 696 697static void change_to_zoom_out(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 698{ 699 zoom_flag = ZOOM_OUT; 700 zoom_change_cnt = 0; 701 accmulate_zoom_in_ds = 0; 702 zoom_in_count = 0; 703 //orientation_flag = judge_zoom_orientation(sample_data); 704 change_to_double_mode(ts_data); 705 return; 706} 707 708static void filter_zoom_in_data_init(void) 709{ 710 zoom_in_buffer_cnt = 0; 711 // zoom_out_buffer_cnt = 0; 712 return; 713} 714 715static void filter_zoom_out_data_init(void) 716{ 717// zoom_in_buffer_cnt = 0; 718 zoom_out_buffer_cnt = 0; 719 return; 720} 721static void filter_zoom_in_data(struct ts_sample_data * report_data, struct ts_sample_data *sample_data) 722{ 723 static int i = 0; 724 static int index = 0; 725 static int count = 0; 726 //backup data to filter noise, only when ds < 40, need this operation. 727 728 //printk("before filter zoom in: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy); 729 index = zoom_in_buffer_cnt%ZOOM_IN_OUT_BUFFER_SIZE; 730 zoom_in_data_buffer[index].dx = sample_data->dx; 731 zoom_in_data_buffer[index].dy = sample_data->dy; 732 zoom_in_data_buffer[index].x = sample_data->x; 733 zoom_in_data_buffer[index].y = sample_data->y; 734 735 //printk("zoom_in_buffer_cnt quyu ZOOM_IN_OUT_BUFFER_SIZE = %d. \n", index); 736 if(zoom_in_buffer_cnt > (ZOOM_IN_OUT_BUFFER_SIZE<<10)){ 737 zoom_in_buffer_cnt -= (ZOOM_IN_OUT_BUFFER_SIZE<<9); 738 } 739 740 if(zoom_in_buffer_cnt >= ZOOM_IN_OUT_BUFFER_SIZE){ 741 index = ZOOM_IN_OUT_BUFFER_SIZE - 1; 742 } 743 //index mean the real count. 744 sample_data->dx = 0; 745 sample_data->dy = 0; 746 sample_data->x = 0; 747 sample_data->y = 0; 748 count = 0; 749 for(i = 0; i <= index; i++){ 750 sample_data->dx += zoom_in_data_buffer[i].dx; 751 sample_data->dy += zoom_in_data_buffer[i].dy; 752 sample_data->x += zoom_in_data_buffer[i].x; 753 sample_data->y += zoom_in_data_buffer[i].y; 754 count++; 755 //printk("i = %d. \n", i); 756 } 757 758 sample_data->dx /= count; 759 sample_data->dy /= count; 760 sample_data->x /= count; 761 sample_data->y /= count; 762 763 report_data->x = sample_data->x; 764 report_data->y = sample_data->y; 765 report_data->dx = sample_data->dx; 766 report_data->dy = sample_data->dy; 767 768 //printk("after filter zoom in: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy); 769 zoom_in_buffer_cnt++; 770 //printk("using mean value for nosie reduction: zoom_in_buffer_cnt = %d. \n", zoom_in_buffer_cnt); 771 772 return; 773} 774 775static void filter_zoom_out_data(struct ts_sample_data * report_data, struct ts_sample_data *sample_data) 776{ 777 static int i = 0; 778 static int index = 0; 779 static int count = 0; 780 //backup data to filter noise, only when ds < 40, need this operation. 781 782 //printk("before filter zoom out: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy); 783 index = zoom_out_buffer_cnt%ZOOM_IN_OUT_BUFFER_SIZE; 784 zoom_out_data_buffer[index].dx = sample_data->dx; 785 zoom_out_data_buffer[index].dy = sample_data->dy; 786 zoom_out_data_buffer[index].x = sample_data->x; 787 zoom_out_data_buffer[index].y = sample_data->y; 788 789 //printk("zoom_out_buffer_cnt quyu ZOOM_IN_OUT_BUFFER_SIZE = %d. \n", index); 790 if(zoom_out_buffer_cnt > (ZOOM_IN_OUT_BUFFER_SIZE<<10)){ 791 zoom_out_buffer_cnt -= (ZOOM_IN_OUT_BUFFER_SIZE<<9); 792 } 793 794 if(zoom_out_buffer_cnt >= ZOOM_IN_OUT_BUFFER_SIZE){ 795 index = ZOOM_IN_OUT_BUFFER_SIZE - 1; 796 } 797 //index mean the real count. 798 sample_data->dx = 0; 799 sample_data->dy = 0; 800 sample_data->x = 0; 801 sample_data->y = 0; 802 count = 0; 803 804 for(i = 0; i <= index; i++){ 805 sample_data->dx += zoom_out_data_buffer[i].dx; 806 sample_data->dy += zoom_out_data_buffer[i].dy; 807 sample_data->x += zoom_out_data_buffer[i].x; 808 sample_data->y += zoom_out_data_buffer[i].y; 809 count++; 810 //printk("i = %d. \n", i); 811 } 812 813 sample_data->dx /= count; 814 sample_data->dy /= count; 815 sample_data->x /= count; 816 sample_data->y /= count; 817 818 report_data->x = sample_data->x; 819 report_data->y = sample_data->y; 820 report_data->dx = sample_data->dx; 821 report_data->dy = sample_data->dy; 822 823 //printk("after filter zoom out: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy); 824 zoom_out_buffer_cnt++; 825 //printk("using mean value for nosie reduction: zoom_out_buffer_cnt = %d. \n", zoom_out_buffer_cnt); 826 827 return; 828} 829 830static int filter_double_point(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 831{ 832 int ret = 0; 833 static int prev_sample_ds = 0; 834 static int cur_sample_ds = 0; 835 static int delta_ds = 0; 836 837 #define DELTA_DS_LIMIT (1) 838 #define HOLD_DS_LIMIT (3) 839 #define ZOOM_IN_CNT_LIMIT (3) 840 #define FIRST_ZOOM_IN_COMPENSTATE (3) //actually zoom out, usually with zoom in ops first. 841 #define ZOOM_OUT_CNT_LIMIT (tp_regidity_level) //related with screen's regidity 842 #define GLIDE_DELTA_DS_MAX_TIMES (4) 843 #define GLIDE_DELTA_DS_MAX_LIMIT (glide_delta_ds_max_limit) 844 845 if(ZOOM_INIT_STATE == zoom_flag && (0 == zoom_out_count && 0 == zoom_in_count)){ 846 prev_sample_ds = int_sqrt((prev_double_sample_data.dx)*(prev_double_sample_data.dx) + (prev_double_sample_data.dy)*(prev_double_sample_data.dy)); 847 /*printk("sun4i-ts: prev_double_sample_data->x = %d, prev_double_sample_data->y = %d, \ 848 prev_double_sample_data.dx = %d, prev_double_sample_data.dy = %d. \n", \ 849 prev_double_sample_data.x, prev_double_sample_data.y, prev_double_sample_data.dx, prev_double_sample_data.dy); 850 */ 851 } 852 853 cur_sample_ds = int_sqrt((sample_data->dx)*(sample_data->dx) + (sample_data->dy)*(sample_data->dy)); 854 delta_ds = cur_sample_ds - prev_sample_ds; 855 //print_filter_double_point_status_info("delta_ds = %d, prev_sample_ds = %d, cur_sample_ds = %d. \n", delta_ds, prev_sample_ds, cur_sample_ds); 856 /*print_filter_double_point_status_info("zoom_in_count = %d, accmulate_zoom_in_ds = %d, zoom_out_count = %d, accmulate_zoom_out_ds=%d. \n", \ 857 zoom_in_count, accmulate_zoom_in_ds, zoom_out_count, accmulate_zoom_out_ds); 858 */ 859 860 //update prev_double_sample_data 861 memcpy((void*)&prev_double_sample_data, (void*)sample_data, sizeof(*sample_data)); 862 prev_sample_ds = cur_sample_ds; 863 //printk("prev_sample_ds = %d, cur_sample_ds = %d. \n", prev_sample_ds, cur_sample_ds); 864 865 if(delta_ds > HOLD_DS_LIMIT){//zoom in 866 867 if(ZOOM_OUT == zoom_flag){//zoom in when zoom out 868 //printk("delta_ds = %d, (4*accmulate_zoom_out_ds/zoom_out_count) = %d. \n", delta_ds, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_out_ds/zoom_out_count)); 869 if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_out_ds/zoom_out_count))){ 870 //noise 871 //printk("delta_ds = %d, prev_sample_ds = %d, cur_sample_ds = %d. \n", delta_ds, prev_sample_ds, cur_sample_ds); 872 cur_sample_ds = prev_sample_ds; //discard the noise, and can not be reference. 873 //printk("delta_ds = %d, (4*accmulate_zoom_out_ds/zoom_out_count) = %d. \n", delta_ds, (4*accmulate_zoom_out_ds/zoom_out_count)); 874 print_filter_double_point_status_info("sun4i-ts: noise, zoom in when zoom out. \n"); 875 //printk("discard noise. \n"); 876 ret = TRUE; 877 }else{ 878 //normal zoom in 879 zoom_change_cnt++; 880 accmulate_zoom_in_ds += delta_ds; 881 zoom_in_count++; 882 if(zoom_change_cnt > ZOOM_IN_CNT_LIMIT){ 883 print_filter_double_point_status_info("change to ZOOM_IN from ZOOM_OUT. \n"); 884 change_to_zoom_in(ts_data, sample_data); 885 filter_zoom_in_data_init(); 886 filter_zoom_in_data(&prev_report_samp, sample_data); 887 }else{ 888 //zoom_change_cnt = 0; 889 print_filter_double_point_status_info("sun4i-ts: normal zoom in, but this will cause twitter. \n"); 890 ret = TRUE; 891 } 892 } 893 //accmulate_zoom_out_ds -= delta_ds; 894 //zoom_out_count++; 895 }else if(ZOOM_IN == zoom_flag){ 896 if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_in_ds/zoom_in_count))){ 897 cur_sample_ds = prev_sample_ds; //discard the noise, and can not be reference. 898 //printk("discard noise. \n"); 899 ret = TRUE; 900 }else{ 901 accmulate_zoom_in_ds += delta_ds; 902 zoom_in_count++; 903 filter_zoom_in_data(&prev_report_samp, sample_data); 904 } 905 zoom_change_cnt = 0; 906 accmulate_zoom_out_ds = 0; 907 zoom_out_count = 0; 908 #if 0 909 printk("ZOOM_IN: delta_ds= %d. \n", delta_ds); 910 #endif 911 }else if(ZOOM_INIT_STATE == zoom_flag ||ZOOM_STATIC == zoom_flag){ 912 zoom_in_count++; 913 if(zoom_in_count > (ZOOM_CHANGE_LIMIT_CNT + FIRST_ZOOM_IN_COMPENSTATE)){ 914 accmulate_zoom_in_ds = delta_ds; 915 zoom_in_count = 1; 916 if(ZOOM_INIT_STATE == zoom_flag){ 917 orientation_flag = judge_zoom_orientation(sample_data); 918 report_up_event_implement(ts_data); 919 } 920 filter_zoom_in_data_init(); 921 filter_zoom_in_data(&prev_report_samp, sample_data); 922 print_filter_double_point_status_info("change to ZOOM_IN from ZOOM_INIT_STATE. \n"); 923 change_to_zoom_in(ts_data, sample_data); 924 #if 1 925 print_filter_double_point_status_info("ZOOM_INIT_STATE: delta_ds= %d. \n", delta_ds); 926 #endif 927 }else{ 928 ret = TRUE; 929 } 930 931 } 932 }else if(delta_ds<(-HOLD_DS_LIMIT)){//zoom out 933 delta_ds = -delta_ds; 934 935 if(ZOOM_IN == zoom_flag){//zoom out when zoom in 936 print_filter_double_point_status_info("delta_ds = %d, (4*accmulate_zoom_in_ds/zoom_in_count) = %d. \n", -delta_ds, (4*accmulate_zoom_in_ds/zoom_in_count)); 937 if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_in_ds/zoom_in_count))){ //noise 938 //printk("delta_ds = %d, prev_sample_ds = %d, cur_sample_ds = %d. \n", delta_ds, prev_sample_ds, cur_sample_ds); 939 cur_sample_ds = prev_sample_ds; //discard the noise, and can not be reference. 940 print_filter_double_point_status_info("sun4i-ts: noise, zoom out when zoom in. \n"); 941 //printk("discard noise. \n"); 942 //zoom_change_cnt = 0; 943 ret = TRUE; 944 }else{//normal zoom out 945 zoom_change_cnt++; 946 accmulate_zoom_out_ds += delta_ds; 947 zoom_out_count++; 948 if(zoom_change_cnt > ZOOM_OUT_CNT_LIMIT){ 949 print_filter_double_point_status_info("change to ZOOM_OUT from ZOOM_IN. \n"); 950 change_to_zoom_out(ts_data, sample_data); 951 filter_zoom_out_data_init(); 952 filter_zoom_out_data(&prev_report_samp, sample_data); 953 }else{ 954 //zoom_change_cnt = 0; 955 print_filter_double_point_status_info("sun4i-ts: normal zoom out, but this will cause twitter. \n"); 956 ret = TRUE; 957 } 958 } 959 //accmulate_zoom_in_ds -= delta_ds; 960 //zoom_in_count++; 961 }else if(ZOOM_OUT == zoom_flag){ //zoom out when zoom out 962 if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_out_ds/zoom_out_count))){ 963 cur_sample_ds = prev_sample_ds; 964 //printk("discard noise. \n"); 965 ret = TRUE; 966 }else{ 967 accmulate_zoom_out_ds += delta_ds; 968 zoom_out_count++; 969 filter_zoom_out_data(&prev_report_samp, sample_data); 970 } 971 zoom_change_cnt = 0; 972 accmulate_zoom_in_ds = 0; 973 zoom_in_count = 0; 974 //printk("ZOOM_OUT: delta_ds= %d. \n", delta_ds); 975 }else if(ZOOM_INIT_STATE == zoom_flag ||ZOOM_STATIC == zoom_flag){ 976 zoom_out_count ++; 977 if(zoom_out_count > ZOOM_CHANGE_LIMIT_CNT){ 978 accmulate_zoom_out_ds = delta_ds; 979 zoom_out_count = 1; 980 if(ZOOM_INIT_STATE == zoom_flag){ 981 orientation_flag = judge_zoom_orientation(sample_data); 982 report_up_event_implement(ts_data); 983 } 984 filter_zoom_out_data_init(); 985 filter_zoom_out_data(&prev_report_samp, sample_data); 986 print_filter_double_point_status_info("change to ZOOM_OUT from ZOOM_INIT_STATE. \n"); 987 change_to_zoom_out(ts_data, sample_data); 988 #if 1 989 print_filter_double_point_status_info("ZOOM_INIT_STATE: delta_ds= %d. \n", delta_ds); 990 #endif 991 }else{ 992 //have not known orientation, discard the point 993 ret = TRUE; 994 } 995 996 } 997 998 }else{ //delta_ds <= HOLD_DS_LIMIT, static mode 999 //printk("delta_ds == %d. \n", delta_ds); 1000 //zoom_change_cnt 1001 //printk("delta_ds == %d. \n", delta_ds); 1002 hold_cnt++; 1003 cur_sample_ds = prev_sample_ds; 1004 if(hold_cnt > 100000){ 1005 hold_cnt = 100; 1006 } 1007 1008 if(unlikely(ZOOM_INIT_STATE == zoom_flag )){ 1009 print_filter_double_point_status_info("ZOOM_INIT_STATE: delta_ds == %d. \n", delta_ds); 1010 if(hold_cnt <= ZOOM_CHANGE_LIMIT_CNT){ //discard the first 3 point 1011 ret = TRUE; 1012 }else{ 1013 //when change to static mode, and not know orientation yet, need judge orientation. 1014 orientation_flag = judge_zoom_orientation(sample_data); 1015 report_up_event_implement(ts_data); 1016 zoom_flag = ZOOM_STATIC; 1017 change_to_double_mode(ts_data); 1018 memcpy((void*)&prev_report_samp, (void*)sample_data, sizeof(*sample_data)); 1019 } 1020 }else{ 1021 memcpy((void*)sample_data, (void*)&prev_report_samp, sizeof(*sample_data)); 1022 } 1023 1024 //filter_double_point_init(sample_data, 0); 1025 1026 } 1027 1028 1029 return ret; 1030 1031} 1032static void report_double_point(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 1033{ 1034 int x1,x2,y1,y2; 1035 1036 y1 = 0; 1037 y2 = 0; 1038 1039 //int tmp; 1040 //tmp = X_TURN_POINT<<2; 1041 //printk("enter report_double_point . \n"); 1042 if(TRUE == filter_double_point(ts_data, sample_data)){ //noise 1043 return; 1044 } 1045 1046 //when report double point, need to clear single_touch_cnt 1047 ts_data->single_touch_cnt = 0; 1048 1049 if(sample_data->dx < X_TURN_POINT){ 1050 x1 = X_CENTER_COORDINATE - (sample_data->dx<<2); 1051 x2 = X_CENTER_COORDINATE + (sample_data->dx<<2); 1052 }else{ 1053 x1 = X_CENTER_COORDINATE - X_COMPENSATE - ((sample_data->dx) - X_TURN_POINT); 1054 x2 = X_CENTER_COORDINATE + X_COMPENSATE + ((sample_data->dx) - X_TURN_POINT); 1055 } 1056#ifdef FIX_ORIENTATION 1057 orientation_flag = ORIENTATION_DEFAULT_VAL; 1058#endif 1059 1060 //printk("X_TURN_POINT is %d. \n", tmp); 1061 if(0 == orientation_flag){ 1062 print_orientation_info("orientation_flag: orientation is not supported or have not known, set the default orientation. \n"); 1063 orientation_flag = ORIENTATION_DEFAULT_VAL; 1064 } 1065 1066 if(-1 == orientation_flag){ 1067 if(sample_data->dy < Y_TURN_POINT){ 1068 y1 = Y_CENTER_COORDINATE - (sample_data->dy<<1); 1069 y2 = Y_CENTER_COORDINATE + (sample_data->dy<<1); 1070 1071 }else{ 1072 y1 = Y_CENTER_COORDINATE - Y_COMPENSATE - (sample_data->dy - Y_TURN_POINT); 1073 y2 = Y_CENTER_COORDINATE + Y_COMPENSATE + (sample_data->dy - Y_TURN_POINT); 1074 } 1075 1076 }else if(1 == orientation_flag){ 1077 if(sample_data->dy < Y_TURN_POINT){ 1078 y2 = Y_CENTER_COORDINATE - (sample_data->dy<<1); 1079 y1 = Y_CENTER_COORDINATE + (sample_data->dy<<1); 1080 1081 }else{ 1082 y2 = Y_CENTER_COORDINATE - Y_COMPENSATE - (sample_data->dy - Y_TURN_POINT); 1083 y1 = Y_CENTER_COORDINATE + Y_COMPENSATE + (sample_data->dy - Y_TURN_POINT); 1084 } 1085 } 1086 1087 input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,800); 1088 input_report_abs(ts_data->input, ABS_MT_POSITION_X, x1); 1089 input_report_abs(ts_data->input, ABS_MT_POSITION_Y, y1); 1090 input_mt_sync(ts_data->input); 1091 1092 input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,800); 1093 input_report_abs(ts_data->input, ABS_MT_POSITION_X, x2); 1094 input_report_abs(ts_data->input, ABS_MT_POSITION_Y, y2); 1095 input_mt_sync(ts_data->input); 1096 input_sync(ts_data->input); 1097 1098 print_report_data_info("report two point: x1 = %d, y1 = %d; x2 = %d, y2 = %d. \n",x1, y1, x2, y2); 1099 print_report_data_info("sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy); 1100 1101 1102 return; 1103} 1104 1105static void report_data(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 1106{ 1107 //printk("calling report data. \n"); 1108 if(TRUE == change_mode){ //only up event happened, change_mode is allowed. 1109 printk("err: report_data: never execute. \n "); 1110 ts_data->single_touch_cnt++; 1111 if(ts_data->single_touch_cnt > UP_TO_SINGLE_CNT_LIMIT){ 1112 //change to single touch mode 1113 change_to_single_touch_mode(); 1114 report_single_point(ts_data, sample_data); 1115 print_report_data_info("change touch mode to SINGLE_TOUCH_MODE from UP state. \n"); 1116 1117 } 1118 }else if(FALSE == change_mode){ 1119 //keep in double touch mode 1120 //remain in double touch mode 1121 ts_data->single_touch_cnt++; 1122 if(ts_data->single_touch_cnt > SINGLE_CNT_LIMIT){ //to avoid unconsiously touch 1123 //change to single touch mode 1124 change_to_single_touch_mode(); 1125 report_single_point(ts_data, sample_data); 1126 1127 print_report_data_info("change touch mode to SINGLE_TOUCH_MODE from double_touch_mode. \n"); 1128 1129 } 1130 } 1131 1132 return; 1133} 1134 1135static void report_up_event(unsigned long data) 1136{ 1137 struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)data; 1138 1139 /*when the time is out, and the buffer data can not affect the timer to re-timing immediately, 1140 *this will happen, 1141 *from this we can conclude, the delay_time is not proper, need to be longer 1142 */ 1143 if(ts_data->buffer_head != ts_data->buffer_tail){ 1144 //printk("warn: when report_up_event, the buffer is not empty. clear the buffer.\n"); 1145 //printk("ts_data->buffer_head = %lu, ts_data->buffer_tail = %lu \n", ts_data->buffer_head, ts_data->buffer_tail); 1146 //ts_data->buffer_tail = ts_data->buffer_head; 1147 //do not discard the data, just let the tasklet to take care of it. 1148 mod_timer(&data_timer, jiffies + ts_data->ts_delay_period); 1149 tp_do_tasklet(ts_data->buffer_head); //direct calling tasklet, do not use int bottom half, may result in some bad behavior.!!! 1150 return; 1151 } 1152 1153 report_up_event_implement(ts_data); 1154 return; 1155} 1156 1157static void process_data(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data) 1158{ 1159 //printk("enter process_data. \n"); 1160 ts_data->touchflag = 1; 1161 if(((sample_data->dx) > DUAL_TOUCH)&&((sample_data->dy) > DUAL_TOUCH)){ 1162 ts_data->touchflag = 2; 1163 ts_data->double_point_cnt++; 1164 if(UP_TOUCH_MODE == touch_mode ){ 1165 print_orientation_info("sun4i-ts: need to get the single point. \n"); 1166 //the direction should be the default value; 1167 /*prev_single_sample.x = sample_data->x; 1168 prev_single_sample.y = sample_data->y; 1169 */ 1170 reference_point_flag = 0; 1171 touch_mode = SINGLE_TOUCH_MODE; 1172 } 1173 //printk("ts_data->double_point_cnt is %d. \n", ts_data->double_point_cnt); 1174 if(ts_data->double_point_cnt > DOUBLE_CNT_LIMIT){ 1175 if(sample_data->dx < MAX_DELTA_X && sample_data->dy < MAX_DELTA_Y){ 1176 //ts_data->count = 0; 1177 if(SINGLE_TOUCH_MODE == touch_mode){ 1178 touch_mode = CHANGING_TO_DOUBLE_TOUCH_MODE; 1179 orientation_flag = 0; 1180 filter_double_point_init(sample_data, 1); 1181 print_orientation_info("sun4i-ts: CHANGING_TO_DOUBLE_TOUCH_MODE orientation_flag == %d . \n", orientation_flag); 1182 return; 1183 } 1184 report_double_point(ts_data, sample_data); 1185 } 1186 } 1187 1188 }else if(1 == ts_data->touchflag){ 1189 if(DOUBLE_TOUCH_MODE == touch_mode ){ 1190 //normally, to really change to single_touch_mode, spend about 100ms 1191 //printk("receive 1 point when in DOUBLE_TOUCH_MODE, ts_data->single_touch_cnt = %d. \n", ts_data->single_touch_cnt); 1192 if(6 == ts_data->single_touch_cnt ){ //discard old data, remain in double_touch_mode,and change to ZOOM_INIT_STATE 1193 filter_zoom_in_data_init(); 1194 filter_zoom_out_data_init(); 1195 prev_single_sample.x = sample_data->x; 1196 prev_single_sample.y = sample_data->y; 1197 reference_point_flag = 1; 1198 orientation_flag = 0; 1199 filter_double_point_init(sample_data, 0); 1200 }else if(ts_data->single_touch_cnt > 6){ //update prev_single_sample 1201 prev_single_sample.x = sample_data->x; 1202 prev_single_sample.y = sample_data->y; 1203 reference_point_flag = 1; 1204 } 1205 report_data(ts_data, sample_data); 1206 }else if(SINGLE_TOUCH_MODE == touch_mode ||UP_TOUCH_MODE == touch_mode || CHANGING_TO_DOUBLE_TOUCH_MODE == touch_mode){//remain in single touch mode 1207 if(SINGLE_TOUCH_MODE == touch_mode ||UP_TOUCH_MODE == touch_mode){ 1208 prev_single_sample.x = sample_data->x; 1209 prev_single_sample.y = sample_data->y; 1210 reference_point_flag = 1; 1211 } 1212 if(SINGLE_TOUCH_MODE != touch_mode){ 1213 change_to_single_touch_mode(); 1214 } 1215 1216 report_single_point(ts_data, sample_data); 1217 } 1218 } 1219 1220 return; 1221 1222} 1223 1224 1225 1226void tp_do_tasklet(unsigned long data) 1227{ 1228 //struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)platform_get_drvdata(pdev); 1229 1230 struct sun4i_ts_data *ts_data = mtTsData; 1231 struct ts_sample_data *sample_data; 1232 int head = 0; 1233 int tail = 0; 1234 1235 //printk("try to get the lock and setting the running state. \n"); 1236 if(1 == spin_trylock(&tp_do_tasklet_sync)){ 1237 if(1 == tp_do_tasklet_running){ 1238 spin_unlock(&tp_do_tasklet_sync); 1239 //printk("other thread is running the rountine. \n"); 1240 return; 1241 }else{ 1242 tp_do_tasklet_running = 1; 1243 spin_unlock(&tp_do_tasklet_sync); 1244 } 1245 }else{ 1246 //printk("failed to get the lock. other thread is using the lock. \n"); 1247 return; 1248 } 1249 // printk("get the lock, the running state is setted. to use the data. \n"); 1250 head = (int)data; 1251 tail = (int)ts_data->buffer_tail; //!!! tail may have changed, while the data is remain? 1252 1253 if((tail + CYCLE_BUFFER_SIZE*2) < head){ //tail have been modify to avoid overflow 1254 goto out; 1255 } 1256 1257 print_tasklet_info("enter tasklet. head = %d, tail = %d. jiffies == %lu. \n", head, tail, jiffies); 1258 1259 while((tail) < (head)){ //when tail == head, mean the buffer is empty 1260 sample_data = &cycle_buffer[tail&(CYCLE_BUFFER_SIZE-1)]; 1261 tail++; 1262 print_filter_info("sample_data->sample_status == %d, ts_data->ts_process_status == %d \n", \ 1263 sample_data->sample_status, ts_data->ts_process_status); 1264 1265 #ifdef TP_INT_PERIOD_TEST 1266 continue; 1267 #endif 1268 if(TP_UP == sample_data->sample_status || TP_DOWN == sample_data->sample_status) 1269 { 1270 //when received up & down event, reinitialize ts_data->double_point_cnt to debounce for DOUBLE_TOUCH_MODE 1271 ts_data->double_point_cnt = 0; 1272 1273 if((TP_DATA_VA == ts_data->ts_process_status || TP_DOWN == ts_data->ts_process_status) && data_timer_status){ 1274 //delay 20ms , ignore up event & down event 1275 print_filter_info("(prev_sample->sample_time + ts_data->ts_delay_period) == %u, \ 1276 (sample_data->sample_time) == %u. \n", \ 1277 (prev_sample->sample_time + ts_data->ts_delay_period), \ 1278 (sample_data->sample_time)); 1279 print_filter_info("up or down: sample_data->sample_time = %lu.sample_data->sample_status = %d \n", sample_data->sample_time, sample_data->sample_status); 1280 if(time_after_eq((unsigned long)(prev_sample->sample_time + ts_data->ts_delay_period - DELAY_COMPENSTAE_PEROID), (unsigned long)(sample_data->sample_time))){ 1281 //notice: sample_time may overflow 1282 print_filter_info("ignore up event & down event. \n"); 1283 mod_timer(&data_timer, jiffies + ts_data->ts_delay_period); 1284 prev_sample->sample_time = sample_data->sample_time; 1285 continue; 1286 } 1287 1288 } 1289 } 1290 1291 switch(sample_data->sample_status) 1292 { 1293 case TP_DOWN: 1294 { 1295 if(1 == data_timer_status){ 1296 report_up_event_implement(ts_data); 1297 } 1298 ts_data->touchflag = 0; 1299 //ts_data->count = 0; 1300 ts_data->ts_process_status = TP_DOWN; 1301 ts_data->double_point_cnt = 0; 1302 prev_sample->sample_time = sample_data->sample_time; 1303 reported_data_start_time = sample_data->sample_time; 1304 print_report_status_info("actuall TP_DOWN . \n"); 1305 break; 1306 } 1307 case TP_DATA_VA: 1308 { 1309 //memcpy(prev_sample, sample_date, sizeof(ts_sample_data)); 1310 print_filter_info("data: sample_data->sample_time = %lu. \n", sample_data->sample_time); 1311 prev_data_sample->sample_time = s…
Large files files are truncated, but you can click here to view the full file