PageRenderTime 221ms CodeModel.GetById 54ms app.highlight 153ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/input/touchscreen/sun4i-ts.c

https://bitbucket.org/ndreys/linux-sunxi
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