PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  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. #include <mach/system.h>
  42. #include <mach/hardware.h>
  43. #include <mach/sys_config.h>
  44. #ifdef CONFIG_HAS_EARLYSUSPEND
  45. #include <linux/pm.h>
  46. #include <linux/earlysuspend.h>
  47. #endif
  48. //#undef CONFIG_HAS_EARLYSUSPEND
  49. static int tp_flag = 0;
  50. //tp status value
  51. #define TP_INITIAL (-1)
  52. #define TP_DOWN (0)
  53. #define TP_UP (1)
  54. #define TP_DATA_VA (2)
  55. //?
  56. #define DUAL_TOUCH (dual_touch_distance)
  57. #define TOUCH_CHANGE (3)
  58. #define TP_DATA_AV_NO (0x3)
  59. //#define PRINT_INT_INFO
  60. //#define PRINT_FILTER_INFO
  61. //#define PRINT_REPORT_STATUS_INFO
  62. //#define PRINT_REPORT_DATA_INFO
  63. //#define PRINT_TASKLET_INFO
  64. #define CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  65. #define PRINT_SUSPEND_INFO
  66. //#define PRINT_FILTER_DOUBLE_POINT_STATUS_INFO
  67. //#define PRINT_ORIENTATION_INFO
  68. //#define FIX_ORIENTATION
  69. #define ORIENTATION_DEFAULT_VAL (-1)
  70. //#define TP_INT_PERIOD_TEST
  71. //#define TP_TEMP_DEBUG
  72. //#define TP_FREQ_DEBUG
  73. //#define PRINT_UP_SEPARATOR
  74. #define TP_FIX_CENTER
  75. #define IRQ_TP (29)
  76. #define TP_BASSADDRESS (0xf1c25000)
  77. #define TP_CTRL0 (0x00)
  78. #define TP_CTRL1 (0x04)
  79. #define TP_CTRL2 (0x08)
  80. #define TP_CTRL3 (0x0c)
  81. #define TP_INT_FIFOC (0x10)
  82. #define TP_INT_FIFOS (0x14)
  83. #define TP_TPR (0x18)
  84. #define TP_CDAT (0x1c)
  85. #define TEMP_DATA (0x20)
  86. #define TP_DATA (0x24)
  87. #define ADC_FIRST_DLY (0x1<<24)
  88. #define ADC_FIRST_DLY_MODE (0x1<<23)
  89. #define ADC_CLK_SELECT (0x0<<22)
  90. #define ADC_CLK_DIVIDER (0x2<<20)
  91. //#define CLK (6)
  92. #define CLK (7)
  93. #define FS_DIV (CLK<<16)
  94. #define ACQ (0x3f)
  95. #define T_ACQ (ACQ)
  96. #define STYLUS_UP_DEBOUNCE (0<<12)
  97. #define STYLUS_UP_DEBOUCE_EN (0<<9)
  98. #define TOUCH_PAN_CALI_EN (1<<6)
  99. #define TP_DUAL_EN (1<<5)
  100. #define TP_MODE_EN (1<<4)
  101. #define TP_ADC_SELECT (0<<3)
  102. #define ADC_CHAN_SELECT (0)
  103. //#define TP_SENSITIVE_ADJUST (0xf<<28)
  104. #define TP_SENSITIVE_ADJUST (tp_sensitive_level<<28) //mark by young for test angda 5" 0xc
  105. #define TP_MODE_SELECT (0x1<<26)
  106. #define PRE_MEA_EN (0x1<<24)
  107. #define PRE_MEA_THRE_CNT (tp_press_threshold<<0) //0x1f40
  108. #define FILTER_EN (1<<2)
  109. #define FILTER_TYPE (0x01<<0)
  110. #define TP_DATA_IRQ_EN (1<<16)
  111. #define TP_DATA_XY_CHANGE (tp_exchange_x_y<<13) //tp_exchange_x_y
  112. #define TP_FIFO_TRIG_LEVEL (3<<8)
  113. #define TP_FIFO_FLUSH (1<<4)
  114. #define TP_UP_IRQ_EN (1<<1)
  115. #define TP_DOWN_IRQ_EN (1<<0)
  116. #define FIFO_DATA_PENDING (1<<16)
  117. #define TP_UP_PENDING (1<<1)
  118. #define TP_DOWN_PENDING (1<<0)
  119. #define SINGLE_TOUCH_MODE (1)
  120. #define CHANGING_TO_DOUBLE_TOUCH_MODE (2)
  121. #define DOUBLE_TOUCH_MODE (3)
  122. #define UP_TOUCH_MODE (4)
  123. #define SINGLE_CNT_LIMIT (40)
  124. #define DOUBLE_CNT_LIMIT (2)
  125. #define UP_TO_SINGLE_CNT_LIMIT (10)
  126. #define TPDATA_MASK (0xfff)
  127. #define FILTER_NOISE_LOWER_LIMIT (2)
  128. #define MAX_DELTA_X (700-100) // avoid excursion
  129. #define MAX_DELTA_Y (1200-200)
  130. #define X_TURN_POINT (330) // x1 < (1647 - MAX_DELTA_X) /3
  131. #define X_COMPENSATE (4*X_TURN_POINT)
  132. #define Y_TURN_POINT (260) // y1 < (1468 -MAX_DELTA_Y )
  133. #define Y_COMPENSATE (2*Y_TURN_POINT)
  134. #ifdef TP_FIX_CENTER
  135. #define X_CENTER_COORDINATE (2048) //for construct two point
  136. #define Y_CENTER_COORDINATE (2048)
  137. #else
  138. #define X_CENTER_COORDINATE (sample_data->x)
  139. #define Y_CENTER_COORDINATE (sample_data->y)
  140. #endif
  141. #define CYCLE_BUFFER_SIZE (64) //must be 2^n
  142. #define DELAY_PERIOD (6) //delay 60 ms, unit is 10ms
  143. #define DELAY_COMPENSTAE_PEROID (3) //the os is busy, can not process the data in time.
  144. #define ZOOM_CHANGE_LIMIT_CNT (3)
  145. #define ZOOM_IN (1)
  146. #define ZOOM_OUT (2)
  147. #define ZOOM_INIT_STATE (3)
  148. #define ZOOM_STATIC (4)
  149. #define SAMPLE_TIME (9.6) //unit is ms. ???
  150. #define SAMPLE_TIME_FACTOR (9.6/SAMPLE_TIME)
  151. #ifndef TRUE
  152. #define TRUE 1
  153. #define FALSE 0
  154. #endif
  155. #ifdef PRINT_INT_INFO
  156. #define print_int_info(fmt, args...) \
  157. do{ \
  158. printk(fmt, ##args); \
  159. }while(0)
  160. #else
  161. #define print_int_info(fmt, args...) //
  162. #endif
  163. #ifdef PRINT_FILTER_INFO
  164. #define print_filter_info(fmt, args...) \
  165. do{ \
  166. printk(fmt, ##args); \
  167. }while(0)
  168. #else
  169. #define print_filter_info(fmt, args...) //
  170. #endif
  171. #ifdef PRINT_REPORT_STATUS_INFO
  172. #define print_report_status_info(fmt, args...) \
  173. do{ \
  174. printk(fmt, ##args); \
  175. }while(0)
  176. #else
  177. #define print_report_status_info(fmt, args...) //
  178. #endif
  179. #ifdef PRINT_REPORT_DATA_INFO
  180. #define print_report_data_info(fmt, args...) \
  181. do{ \
  182. printk(fmt, ##args); \
  183. }while(0)
  184. #else
  185. #define print_report_data_info(fmt, args...) //
  186. #endif
  187. #ifdef PRINT_TASKLET_INFO
  188. #define print_tasklet_info(fmt, args...) \
  189. do{ \
  190. printk(fmt, ##args); \
  191. }while(0)
  192. #else
  193. #define print_tasklet_info(fmt, args...) //
  194. #endif
  195. #ifdef PRINT_FILTER_DOUBLE_POINT_STATUS_INFO
  196. #define print_filter_double_point_status_info(fmt, args...) \
  197. do{ \
  198. printk(fmt, ##args); \
  199. }while(0)
  200. #else
  201. #define print_filter_double_point_status_info(fmt, args...) //
  202. #endif
  203. #ifdef PRINT_ORIENTATION_INFO
  204. #define print_orientation_info(fmt, args...) \
  205. do{ \
  206. printk(fmt, ##args); \
  207. }while(0)
  208. #else
  209. #define print_orientation_info(fmt, args...) //
  210. #endif
  211. struct sun4i_ts_data {
  212. struct resource *res;
  213. struct input_dev *input;
  214. void __iomem *base_addr;
  215. int irq;
  216. char phys[32];
  217. unsigned int count; //for report threshold & touchmod(double to single touch mode) change
  218. unsigned long buffer_head; //for cycle buffer
  219. unsigned long buffer_tail;
  220. int ts_sample_status; //for touchscreen status when sampling
  221. int ts_process_status; //for record touchscreen status when process data
  222. int double_point_cnt; //for noise reduction when in double_touch_mode
  223. int single_touch_cnt; //for noise reduction when change to double_touch_mode
  224. int ts_delay_period; //will determine responding sensitivity
  225. int touchflag;
  226. #ifdef CONFIG_HAS_EARLYSUSPEND
  227. struct early_suspend early_suspend;
  228. #endif
  229. };
  230. struct ts_sample_data{
  231. unsigned int x1;
  232. unsigned int y1;
  233. unsigned int x;
  234. unsigned int y;
  235. unsigned int dx;
  236. unsigned int dy;
  237. unsigned int z1;
  238. unsigned int z2;
  239. int sample_status; //record the sample point status when sampling
  240. unsigned int sample_time;
  241. };
  242. struct sun4i_ts_data * mtTsData =NULL;
  243. static int touch_mode = UP_TOUCH_MODE;
  244. static int change_mode = TRUE;
  245. static int tp_irq_state = TRUE;
  246. #ifdef PRINT_INT_INFO
  247. static cputime64_t cur_wall_time = 0L;
  248. #endif
  249. //static cputime64_t cur_idle_time = 0L;
  250. static struct ts_sample_data cycle_buffer[CYCLE_BUFFER_SIZE] = {{0},};
  251. static struct ts_sample_data *prev_sample;
  252. static struct ts_sample_data *prev_data_sample;
  253. static struct timer_list data_timer;
  254. static 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
  255. static struct ts_sample_data prev_single_sample;
  256. static struct ts_sample_data prev_double_sample_data;
  257. static struct ts_sample_data prev_report_samp;
  258. static int orientation_flag = 0;
  259. static int zoom_flag = 0;
  260. static int accmulate_zoom_out_ds = 0;
  261. static int accmulate_zoom_in_ds = 0;
  262. static int zoom_in_count = 0;
  263. static int zoom_out_count = 0;
  264. static int zoom_change_cnt = 0;
  265. static int hold_cnt = 0;
  266. //config from sysconfig files.
  267. static int glide_delta_ds_max_limit = 0;
  268. static int tp_regidity_level = 0;
  269. static int tp_press_threshold_enable = 0;
  270. static int tp_press_threshold = 0; //usded to adjust sensitivity of touch
  271. static int tp_sensitive_level = 0; //used to adjust sensitivity of pen down detection
  272. static int tp_exchange_x_y = 0;
  273. #define ZOOM_IN_OUT_BUFFER_SIZE_TIMES (2)
  274. #define ZOOM_IN_OUT_BUFFER_SIZE (1<<ZOOM_IN_OUT_BUFFER_SIZE_TIMES)
  275. #define TRANSFER_DATA_BUFFER_SIZE (4)
  276. static struct ts_sample_data zoom_in_data_buffer[ZOOM_IN_OUT_BUFFER_SIZE] = {{0},};
  277. static struct ts_sample_data zoom_out_data_buffer[ZOOM_IN_OUT_BUFFER_SIZE] = {{0},};
  278. static struct ts_sample_data transfer_data_buffer[TRANSFER_DATA_BUFFER_SIZE] = {{0},};
  279. static int zoom_in_buffer_cnt = 0;
  280. static int zoom_out_buffer_cnt = 0;
  281. static spinlock_t tp_do_tasklet_sync;
  282. static int tp_do_tasklet_running = 0;
  283. //for test
  284. //static int tp_irq = 0;
  285. static int dual_touch_distance = 0;
  286. #ifdef PRINT_UP_SEPARATOR
  287. static int separator_flag = 0;
  288. #endif
  289. static int reported_single_point_cnt = 0;
  290. static int reported_data_start_time = 0;
  291. static atomic_t report_up_event_implement_sync = ATOMIC_INIT(1);
  292. static int report_up_event_implement_running = 0;
  293. static int reference_point_flag = 1;
  294. void tp_do_tasklet(unsigned long data);
  295. DECLARE_TASKLET(tp_tasklet,tp_do_tasklet,0);
  296. //????
  297. #ifdef CONFIG_HAS_EARLYSUSPEND
  298. static void sun4i_ts_suspend(struct early_suspend *h)
  299. {
  300. /*int ret;
  301. struct sun4i_ts_data *ts = container_of(h, struct sun4i_ts_data, early_suspend);
  302. */
  303. #ifdef PRINT_SUSPEND_INFO
  304. printk("enter earlysuspend: sun4i_ts_suspend. \n");
  305. #endif
  306. writel(0,TP_BASSADDRESS + TP_CTRL1);
  307. return ;
  308. }
  309. //????
  310. static void sun4i_ts_resume(struct early_suspend *h)
  311. {
  312. /*int ret;
  313. struct sun4i_ts_data *ts = container_of(h, struct sun4i_ts_data, early_suspend);
  314. */
  315. #ifdef PRINT_SUSPEND_INFO
  316. printk("enter laterresume: sun4i_ts_resume. \n");
  317. #endif
  318. writel(STYLUS_UP_DEBOUNCE|STYLUS_UP_DEBOUCE_EN|TP_DUAL_EN|TP_MODE_EN,TP_BASSADDRESS + TP_CTRL1);
  319. return ;
  320. }
  321. #else
  322. //????
  323. #ifdef CONFIG_PM
  324. static int sun4i_ts_suspend(struct platform_device *pdev, pm_message_t state)
  325. {
  326. #ifdef PRINT_SUSPEND_INFO
  327. printk("enter: sun4i_ts_suspend. \n");
  328. #endif
  329. writel(0,TP_BASSADDRESS + TP_CTRL1);
  330. return 0;
  331. }
  332. static int sun4i_ts_resume(struct platform_device *pdev)
  333. {
  334. #ifdef PRINT_SUSPEND_INFO
  335. printk("enter: sun4i_ts_resume. \n");
  336. #endif
  337. writel(STYLUS_UP_DEBOUNCE|STYLUS_UP_DEBOUCE_EN|TP_DUAL_EN|TP_MODE_EN,TP_BASSADDRESS + TP_CTRL1);
  338. return 0;
  339. }
  340. #endif
  341. #endif
  342. static int tp_init(void)
  343. {
  344. //struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)platform_get_drvdata(pdev);
  345. // struct sun4i_ts_data *ts_data = mtTsData;
  346. //TP_CTRL0: 0x0027003f
  347. #ifdef TP_FREQ_DEBUG
  348. writel(0x0028001f, TP_BASSADDRESS + TP_CTRL0);
  349. #else
  350. writel(ADC_CLK_DIVIDER|FS_DIV|T_ACQ, TP_BASSADDRESS + TP_CTRL0);
  351. #endif
  352. //TP_CTRL2: 0xc4000000
  353. if(1 == tp_press_threshold_enable){
  354. writel(TP_SENSITIVE_ADJUST |TP_MODE_SELECT | PRE_MEA_EN | PRE_MEA_THRE_CNT, TP_BASSADDRESS + TP_CTRL2);
  355. }
  356. else{
  357. writel(TP_SENSITIVE_ADJUST|TP_MODE_SELECT,TP_BASSADDRESS + TP_CTRL2);
  358. }
  359. //TP_CTRL3: 0x05
  360. #ifdef TP_FREQ_DEBUG
  361. writel(0x06, TP_BASSADDRESS + TP_CTRL3);
  362. #else
  363. writel(FILTER_EN|FILTER_TYPE,TP_BASSADDRESS + TP_CTRL3);
  364. #endif
  365. #ifdef TP_TEMP_DEBUG
  366. //TP_INT_FIFOC: 0x00010313
  367. 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);
  368. writel(0x10fff, TP_BASSADDRESS + TP_TPR);
  369. #else
  370. //TP_INT_FIFOC: 0x00010313
  371. 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);
  372. #endif
  373. //TP_CTRL1: 0x00000070 -> 0x00000030
  374. writel(TP_DATA_XY_CHANGE|STYLUS_UP_DEBOUNCE|STYLUS_UP_DEBOUCE_EN|TP_DUAL_EN|TP_MODE_EN,TP_BASSADDRESS + TP_CTRL1);
  375. /*
  376. //put_wvalue(TP_CTRL0 ,0x02a6007f); //512us TACQ 4ms FS 60 point
  377. //put_wvalue(TP_CTRL0 ,0x0aa7003f);
  378. put_wvalue(TP_CTRL0 ,0x00a7003f); //100 point
  379. put_wvalue(TP_CTRL1 ,0x00000030);
  380. //put_wvalue(TP_INT_FIFOC,0x12f13);
  381. put_wvalue(TP_INT_FIFOC,0x10313);
  382. //put_wvalue(TP_CTRL2,0x90003e8);
  383. //put_wvalue(TP_CTRL2,0x9002710);
  384. put_wvalue(TP_CTRL2,0xc4002710);
  385. put_wvalue(TP_CTRL3,0x00000005);
  386. */
  387. /*
  388. writel(0x00b70100,TP_BASSADDRESS + TP_CTRL0);
  389. writel(0xfd000000,TP_BASSADDRESS + TP_CTRL2);
  390. writel(0x4,TP_BASSADDRESS + TP_CTRL3);
  391. writel(0x10513,TP_BASSADDRESS +TP_INT_FIFOC);
  392. writel(0x00005230,TP_BASSADDRESS + TP_CTRL1);*/
  393. return (0);
  394. }
  395. static void change_to_single_touch_mode(void)
  396. {
  397. touch_mode = SINGLE_TOUCH_MODE;
  398. reported_single_point_cnt = 0;
  399. return;
  400. }
  401. static void backup_transfered_data(struct ts_sample_data *sample_data)
  402. {
  403. static int index = 0;
  404. index = reported_single_point_cnt%TRANSFER_DATA_BUFFER_SIZE;
  405. transfer_data_buffer[index].dx = sample_data->dx;
  406. transfer_data_buffer[index].dy = sample_data->dy;
  407. transfer_data_buffer[index].x = sample_data->x;
  408. transfer_data_buffer[index].y = sample_data->y;
  409. if(reported_single_point_cnt > (TRANSFER_DATA_BUFFER_SIZE<<10)){
  410. reported_single_point_cnt -= (TRANSFER_DATA_BUFFER_SIZE<<9);
  411. }
  412. reported_single_point_cnt++;
  413. return;
  414. }
  415. static void report_single_point_implement(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  416. {
  417. input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,800);
  418. input_report_abs(ts_data->input, ABS_MT_POSITION_X, sample_data->x);
  419. input_report_abs(ts_data->input, ABS_MT_POSITION_Y, sample_data->y);
  420. /*
  421. print_report_data_info("report single point: x = %d, y = %d\n \
  422. sample_data->dx = %d, sample_data->dy = %d. \n", \
  423. sample_data->x, sample_data->y, sample_data->dx, sample_data->dy);
  424. */
  425. print_report_data_info("report single point: x = %d,sample_data->y = %d. \n", sample_data->x, sample_data->y);
  426. input_mt_sync(ts_data->input);
  427. input_sync(ts_data->input);
  428. return;
  429. }
  430. static void report_single_point(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  431. {
  432. backup_transfered_data(sample_data);
  433. report_single_point_implement(ts_data, sample_data);
  434. return;
  435. }
  436. static void report_slide_data(struct sun4i_ts_data *ts_data)
  437. {
  438. int start = 0;
  439. int end = 0;
  440. #define MIN_DX (DUAL_TOUCH*20)
  441. #define MIN_DY (DUAL_TOUCH*20)
  442. #define MAX_DX (DUAL_TOUCH*40)
  443. #define MAX_DY (DUAL_TOUCH*40)
  444. int dx = 0;
  445. int dy = 0;
  446. int ds_times = 4;
  447. //index = reported_single_point_cnt%TRANSFER_DATA_BUFFER_SIZE;
  448. struct ts_sample_data sample_data;
  449. //printk("reported_single_point_cnt = %d. \n", reported_single_point_cnt);
  450. if(reported_single_point_cnt <= 1){
  451. //only one reference point, can not judge direction
  452. dx = -MIN_DX;
  453. dy = MIN_DY;
  454. //dy = 0;
  455. end = (reported_single_point_cnt-1)%TRANSFER_DATA_BUFFER_SIZE;
  456. sample_data.x = max(0, min(4096, (int)(transfer_data_buffer[end].x + dx)));
  457. sample_data.y = max(0, min(4096, (int)(transfer_data_buffer[end].y + dy)));
  458. //printk("sample_data.x = %d. sample_data.y = %d. \n", sample_data.x, sample_data.y);
  459. report_single_point_implement(ts_data, &sample_data);
  460. sample_data.x = transfer_data_buffer[end].x;
  461. sample_data.y = transfer_data_buffer[end].y;
  462. //printk("sample_data.x = %d. sample_data.y = %d. \n", sample_data.x, sample_data.y);
  463. //report_single_point_implement(ts_data, &sample_data);
  464. }else{
  465. if(reported_single_point_cnt <=TRANSFER_DATA_BUFFER_SIZE){
  466. start = 0;
  467. }else{
  468. start = reported_single_point_cnt - TRANSFER_DATA_BUFFER_SIZE;
  469. }
  470. start = start%TRANSFER_DATA_BUFFER_SIZE;
  471. end = (reported_single_point_cnt-1)%TRANSFER_DATA_BUFFER_SIZE;
  472. dx = transfer_data_buffer[end].x -transfer_data_buffer[start].x;
  473. dy = transfer_data_buffer[end].y -transfer_data_buffer[start].y;
  474. //printk("dx = %d, dy = %d. \n", dx, dy);
  475. if(dx < 0){
  476. dx = -dx;
  477. dx = min(MAX_DX, max(MIN_DX, dx*ds_times/(end - start)));
  478. dx = -dx;
  479. }else{
  480. dx = min(MAX_DX, max(MIN_DX, dx*ds_times/(end - start)));
  481. }
  482. if(dy < 0){
  483. dy = -dy;
  484. dy = min(MAX_DY, max(MIN_DY, dy*ds_times/(end - start)));
  485. dy = -dy;
  486. }else{
  487. dy = min(MAX_DY, max(MIN_DY, dy*ds_times/(end - start)));
  488. }
  489. //printk("dx = %d, dy = %d. \n", dx, dy);
  490. sample_data.x = max(0, min(4096, (int)(transfer_data_buffer[end].x + dx)));
  491. sample_data.y = max(0, min(4096, (int)(transfer_data_buffer[end].y + dy)));
  492. //printk("sample_data.x = %d. sample_data.y = %d. \n", sample_data.x, sample_data.y);
  493. report_single_point_implement(ts_data, &sample_data);
  494. }
  495. }
  496. static void report_up_event_implement(struct sun4i_ts_data *ts_data)
  497. {
  498. static const int UP_EVENT_DELAY_TIME = 3;
  499. static const int SLIDE_MIN_CNT = 3;
  500. if(atomic_sub_and_test(1, &report_up_event_implement_sync)){
  501. //get the resource
  502. if(1 == report_up_event_implement_running){
  503. atomic_inc(&report_up_event_implement_sync);
  504. printk("other thread is running the rountine. \n");
  505. return;
  506. }else{
  507. report_up_event_implement_running = 1;
  508. atomic_inc(&report_up_event_implement_sync);
  509. }
  510. }else{
  511. printk("failed to get the lock. other thread is using the lock. \n");
  512. return;
  513. }
  514. if(0 == data_timer_status){
  515. printk("report_up_event_implement have been called. \n");
  516. goto report_up_event_implement_out;
  517. return;
  518. }
  519. print_report_status_info("enter report_up_event_implement. jiffies == %lu. \n", jiffies);
  520. //printk("prev_sample->sample_time =%d, prev_data_sample->sample_time = %d. \n", prev_sample->sample_time, prev_data_sample->sample_time);
  521. //printk("touch_mode = %d. reported_single_point_cnt = %d. \n", touch_mode, reported_single_point_cnt);
  522. if( (SINGLE_TOUCH_MODE == touch_mode) && \
  523. (reported_single_point_cnt<SLIDE_MIN_CNT) && (reported_single_point_cnt>0) && \
  524. (prev_sample->sample_time >= (prev_data_sample->sample_time + UP_EVENT_DELAY_TIME))){
  525. //obvious, a slide, how to compenstate?
  526. //printk("report_up_event_implement: obvious, a slide. \n");
  527. report_slide_data(ts_data);
  528. }
  529. //note: below operation may be interfere by intterrupt, but it does not matter
  530. input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,0);
  531. input_sync(ts_data->input);
  532. del_timer(&data_timer);
  533. data_timer_status = 0;
  534. ts_data->ts_process_status = TP_UP;
  535. ts_data->double_point_cnt = 0;
  536. //ts_data->buffer_head = 0;
  537. //ts_data->buffer_tail = 0;
  538. ts_data->touchflag = 0;
  539. //ts_data->count = 0;
  540. touch_mode = UP_TOUCH_MODE;
  541. change_mode = TRUE;
  542. reported_single_point_cnt = 0;
  543. reported_data_start_time = 0;
  544. report_up_event_implement_out:
  545. report_up_event_implement_running = 0;
  546. #ifdef PRINT_UP_SEPARATOR
  547. printk("separator: #######%d, %d, %d###########. \n\n\n\n\n\n\n", separator_flag, separator_flag, separator_flag);
  548. separator_flag++;
  549. #endif
  550. return;
  551. }
  552. static int judge_zoom_orientation(struct ts_sample_data *sample_data)
  553. {
  554. int dx,dy;
  555. int ret = 0;
  556. if(1 == reference_point_flag){
  557. dx = sample_data->x - prev_single_sample.x;
  558. dy = sample_data->y - prev_single_sample.y;
  559. if(dx*dy > 0){
  560. ret = -1;
  561. }else if(dx*dy < 0){
  562. ret = 1;
  563. }
  564. }else{
  565. print_orientation_info("judge_zoom_orientation: lack reference point .\n");
  566. }
  567. print_orientation_info("sun4i-ts: orientation_flag == %d . \n", ret);
  568. return ret;
  569. }
  570. static void filter_double_point_init(struct ts_sample_data *sample_data, int backup_samp_flag)
  571. {
  572. //backup prev_double_sample_data
  573. zoom_flag = ZOOM_INIT_STATE;
  574. accmulate_zoom_out_ds = 0;
  575. zoom_out_count = 0;
  576. accmulate_zoom_in_ds = 0;
  577. zoom_in_count = 0;
  578. //printk("sample_data->x = %d, sample_data-> y = %d. \n", sample_data->x, sample_data->y);
  579. if(1 == backup_samp_flag){
  580. memcpy((void*)(&prev_double_sample_data), (void*)sample_data, sizeof(*sample_data));
  581. }
  582. hold_cnt = 0;
  583. //when report two point, the first two point will be reserved for reference purpose.
  584. return;
  585. }
  586. static void change_to_double_mode(struct sun4i_ts_data *ts_data)
  587. {
  588. if((CHANGING_TO_DOUBLE_TOUCH_MODE != touch_mode) && \
  589. (DOUBLE_TOUCH_MODE != touch_mode)&& \
  590. (UP_TOUCH_MODE != touch_mode)){
  591. printk("change_to_double_mode: err, not the expected state. touch_mode = %d. \n", touch_mode);
  592. }
  593. touch_mode = DOUBLE_TOUCH_MODE;
  594. change_mode = FALSE;
  595. ts_data->single_touch_cnt = 0; //according this counter, change to single touch mode
  596. return;
  597. }
  598. static void change_to_zoom_in(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  599. {
  600. zoom_flag = ZOOM_IN;
  601. zoom_change_cnt = 0;
  602. accmulate_zoom_out_ds = 0;
  603. zoom_out_count = 0;
  604. //orientation_flag = judge_zoom_orientation(sample_data);
  605. change_to_double_mode(ts_data);
  606. return;
  607. }
  608. static void change_to_zoom_out(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  609. {
  610. zoom_flag = ZOOM_OUT;
  611. zoom_change_cnt = 0;
  612. accmulate_zoom_in_ds = 0;
  613. zoom_in_count = 0;
  614. //orientation_flag = judge_zoom_orientation(sample_data);
  615. change_to_double_mode(ts_data);
  616. return;
  617. }
  618. static void filter_zoom_in_data_init(void)
  619. {
  620. zoom_in_buffer_cnt = 0;
  621. // zoom_out_buffer_cnt = 0;
  622. return;
  623. }
  624. static void filter_zoom_out_data_init(void)
  625. {
  626. // zoom_in_buffer_cnt = 0;
  627. zoom_out_buffer_cnt = 0;
  628. return;
  629. }
  630. static void filter_zoom_in_data(struct ts_sample_data * report_data, struct ts_sample_data *sample_data)
  631. {
  632. static int i = 0;
  633. static int index = 0;
  634. static int count = 0;
  635. //backup data to filter noise, only when ds < 40, need this operation.
  636. //printk("before filter zoom in: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy);
  637. index = zoom_in_buffer_cnt%ZOOM_IN_OUT_BUFFER_SIZE;
  638. zoom_in_data_buffer[index].dx = sample_data->dx;
  639. zoom_in_data_buffer[index].dy = sample_data->dy;
  640. zoom_in_data_buffer[index].x = sample_data->x;
  641. zoom_in_data_buffer[index].y = sample_data->y;
  642. //printk("zoom_in_buffer_cnt quyu ZOOM_IN_OUT_BUFFER_SIZE = %d. \n", index);
  643. if(zoom_in_buffer_cnt > (ZOOM_IN_OUT_BUFFER_SIZE<<10)){
  644. zoom_in_buffer_cnt -= (ZOOM_IN_OUT_BUFFER_SIZE<<9);
  645. }
  646. if(zoom_in_buffer_cnt >= ZOOM_IN_OUT_BUFFER_SIZE){
  647. index = ZOOM_IN_OUT_BUFFER_SIZE - 1;
  648. }
  649. //index mean the real count.
  650. sample_data->dx = 0;
  651. sample_data->dy = 0;
  652. sample_data->x = 0;
  653. sample_data->y = 0;
  654. count = 0;
  655. for(i = 0; i <= index; i++){
  656. sample_data->dx += zoom_in_data_buffer[i].dx;
  657. sample_data->dy += zoom_in_data_buffer[i].dy;
  658. sample_data->x += zoom_in_data_buffer[i].x;
  659. sample_data->y += zoom_in_data_buffer[i].y;
  660. count++;
  661. //printk("i = %d. \n", i);
  662. }
  663. sample_data->dx /= count;
  664. sample_data->dy /= count;
  665. sample_data->x /= count;
  666. sample_data->y /= count;
  667. report_data->x = sample_data->x;
  668. report_data->y = sample_data->y;
  669. report_data->dx = sample_data->dx;
  670. report_data->dy = sample_data->dy;
  671. //printk("after filter zoom in: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy);
  672. zoom_in_buffer_cnt++;
  673. //printk("using mean value for nosie reduction: zoom_in_buffer_cnt = %d. \n", zoom_in_buffer_cnt);
  674. return;
  675. }
  676. static void filter_zoom_out_data(struct ts_sample_data * report_data, struct ts_sample_data *sample_data)
  677. {
  678. static int i = 0;
  679. static int index = 0;
  680. static int count = 0;
  681. //backup data to filter noise, only when ds < 40, need this operation.
  682. //printk("before filter zoom out: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy);
  683. index = zoom_out_buffer_cnt%ZOOM_IN_OUT_BUFFER_SIZE;
  684. zoom_out_data_buffer[index].dx = sample_data->dx;
  685. zoom_out_data_buffer[index].dy = sample_data->dy;
  686. zoom_out_data_buffer[index].x = sample_data->x;
  687. zoom_out_data_buffer[index].y = sample_data->y;
  688. //printk("zoom_out_buffer_cnt quyu ZOOM_IN_OUT_BUFFER_SIZE = %d. \n", index);
  689. if(zoom_out_buffer_cnt > (ZOOM_IN_OUT_BUFFER_SIZE<<10)){
  690. zoom_out_buffer_cnt -= (ZOOM_IN_OUT_BUFFER_SIZE<<9);
  691. }
  692. if(zoom_out_buffer_cnt >= ZOOM_IN_OUT_BUFFER_SIZE){
  693. index = ZOOM_IN_OUT_BUFFER_SIZE - 1;
  694. }
  695. //index mean the real count.
  696. sample_data->dx = 0;
  697. sample_data->dy = 0;
  698. sample_data->x = 0;
  699. sample_data->y = 0;
  700. count = 0;
  701. for(i = 0; i <= index; i++){
  702. sample_data->dx += zoom_out_data_buffer[i].dx;
  703. sample_data->dy += zoom_out_data_buffer[i].dy;
  704. sample_data->x += zoom_out_data_buffer[i].x;
  705. sample_data->y += zoom_out_data_buffer[i].y;
  706. count++;
  707. //printk("i = %d. \n", i);
  708. }
  709. sample_data->dx /= count;
  710. sample_data->dy /= count;
  711. sample_data->x /= count;
  712. sample_data->y /= count;
  713. report_data->x = sample_data->x;
  714. report_data->y = sample_data->y;
  715. report_data->dx = sample_data->dx;
  716. report_data->dy = sample_data->dy;
  717. //printk("after filter zoom out: sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy);
  718. zoom_out_buffer_cnt++;
  719. //printk("using mean value for nosie reduction: zoom_out_buffer_cnt = %d. \n", zoom_out_buffer_cnt);
  720. return;
  721. }
  722. static int filter_double_point(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  723. {
  724. int ret = 0;
  725. static int prev_sample_ds = 0;
  726. static int cur_sample_ds = 0;
  727. static int delta_ds = 0;
  728. #define DELTA_DS_LIMIT (1)
  729. #define HOLD_DS_LIMIT (3)
  730. #define ZOOM_IN_CNT_LIMIT (3)
  731. #define FIRST_ZOOM_IN_COMPENSTATE (3) //actually zoom out, usually with zoom in ops first.
  732. #define ZOOM_OUT_CNT_LIMIT (tp_regidity_level) //related with screen's regidity
  733. #define GLIDE_DELTA_DS_MAX_TIMES (4)
  734. #define GLIDE_DELTA_DS_MAX_LIMIT (glide_delta_ds_max_limit)
  735. if(ZOOM_INIT_STATE == zoom_flag && (0 == zoom_out_count && 0 == zoom_in_count)){
  736. 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));
  737. /*printk("sun4i-ts: prev_double_sample_data->x = %d, prev_double_sample_data->y = %d, \
  738. prev_double_sample_data.dx = %d, prev_double_sample_data.dy = %d. \n", \
  739. prev_double_sample_data.x, prev_double_sample_data.y, prev_double_sample_data.dx, prev_double_sample_data.dy);
  740. */
  741. }
  742. cur_sample_ds = int_sqrt((sample_data->dx)*(sample_data->dx) + (sample_data->dy)*(sample_data->dy));
  743. delta_ds = cur_sample_ds - prev_sample_ds;
  744. //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);
  745. /*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", \
  746. zoom_in_count, accmulate_zoom_in_ds, zoom_out_count, accmulate_zoom_out_ds);
  747. */
  748. //update prev_double_sample_data
  749. memcpy((void*)&prev_double_sample_data, (void*)sample_data, sizeof(*sample_data));
  750. prev_sample_ds = cur_sample_ds;
  751. //printk("prev_sample_ds = %d, cur_sample_ds = %d. \n", prev_sample_ds, cur_sample_ds);
  752. if(delta_ds > HOLD_DS_LIMIT){//zoom in
  753. if(ZOOM_OUT == zoom_flag){//zoom in when zoom out
  754. //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));
  755. if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_out_ds/zoom_out_count))){
  756. //noise
  757. //printk("delta_ds = %d, prev_sample_ds = %d, cur_sample_ds = %d. \n", delta_ds, prev_sample_ds, cur_sample_ds);
  758. cur_sample_ds = prev_sample_ds; //discard the noise, and can not be reference.
  759. //printk("delta_ds = %d, (4*accmulate_zoom_out_ds/zoom_out_count) = %d. \n", delta_ds, (4*accmulate_zoom_out_ds/zoom_out_count));
  760. print_filter_double_point_status_info("sun4i-ts: noise, zoom in when zoom out. \n");
  761. //printk("discard noise. \n");
  762. ret = TRUE;
  763. }else{
  764. //normal zoom in
  765. zoom_change_cnt++;
  766. accmulate_zoom_in_ds += delta_ds;
  767. zoom_in_count++;
  768. if(zoom_change_cnt > ZOOM_IN_CNT_LIMIT){
  769. print_filter_double_point_status_info("change to ZOOM_IN from ZOOM_OUT. \n");
  770. change_to_zoom_in(ts_data, sample_data);
  771. filter_zoom_in_data_init();
  772. filter_zoom_in_data(&prev_report_samp, sample_data);
  773. }else{
  774. //zoom_change_cnt = 0;
  775. print_filter_double_point_status_info("sun4i-ts: normal zoom in, but this will cause twitter. \n");
  776. ret = TRUE;
  777. }
  778. }
  779. //accmulate_zoom_out_ds -= delta_ds;
  780. //zoom_out_count++;
  781. }else if(ZOOM_IN == zoom_flag){
  782. if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_in_ds/zoom_in_count))){
  783. cur_sample_ds = prev_sample_ds; //discard the noise, and can not be reference.
  784. //printk("discard noise. \n");
  785. ret = TRUE;
  786. }else{
  787. accmulate_zoom_in_ds += delta_ds;
  788. zoom_in_count++;
  789. filter_zoom_in_data(&prev_report_samp, sample_data);
  790. }
  791. zoom_change_cnt = 0;
  792. accmulate_zoom_out_ds = 0;
  793. zoom_out_count = 0;
  794. #if 0
  795. printk("ZOOM_IN: delta_ds= %d. \n", delta_ds);
  796. #endif
  797. }else if(ZOOM_INIT_STATE == zoom_flag ||ZOOM_STATIC == zoom_flag){
  798. zoom_in_count++;
  799. if(zoom_in_count > (ZOOM_CHANGE_LIMIT_CNT + FIRST_ZOOM_IN_COMPENSTATE)){
  800. accmulate_zoom_in_ds = delta_ds;
  801. zoom_in_count = 1;
  802. if(ZOOM_INIT_STATE == zoom_flag){
  803. orientation_flag = judge_zoom_orientation(sample_data);
  804. report_up_event_implement(ts_data);
  805. }
  806. filter_zoom_in_data_init();
  807. filter_zoom_in_data(&prev_report_samp, sample_data);
  808. print_filter_double_point_status_info("change to ZOOM_IN from ZOOM_INIT_STATE. \n");
  809. change_to_zoom_in(ts_data, sample_data);
  810. #if 1
  811. print_filter_double_point_status_info("ZOOM_INIT_STATE: delta_ds= %d. \n", delta_ds);
  812. #endif
  813. }else{
  814. ret = TRUE;
  815. }
  816. }
  817. }else if(delta_ds<(-HOLD_DS_LIMIT)){//zoom out
  818. delta_ds = -delta_ds;
  819. if(ZOOM_IN == zoom_flag){//zoom out when zoom in
  820. 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));
  821. if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_in_ds/zoom_in_count))){ //noise
  822. //printk("delta_ds = %d, prev_sample_ds = %d, cur_sample_ds = %d. \n", delta_ds, prev_sample_ds, cur_sample_ds);
  823. cur_sample_ds = prev_sample_ds; //discard the noise, and can not be reference.
  824. print_filter_double_point_status_info("sun4i-ts: noise, zoom out when zoom in. \n");
  825. //printk("discard noise. \n");
  826. //zoom_change_cnt = 0;
  827. ret = TRUE;
  828. }else{//normal zoom out
  829. zoom_change_cnt++;
  830. accmulate_zoom_out_ds += delta_ds;
  831. zoom_out_count++;
  832. if(zoom_change_cnt > ZOOM_OUT_CNT_LIMIT){
  833. print_filter_double_point_status_info("change to ZOOM_OUT from ZOOM_IN. \n");
  834. change_to_zoom_out(ts_data, sample_data);
  835. filter_zoom_out_data_init();
  836. filter_zoom_out_data(&prev_report_samp, sample_data);
  837. }else{
  838. //zoom_change_cnt = 0;
  839. print_filter_double_point_status_info("sun4i-ts: normal zoom out, but this will cause twitter. \n");
  840. ret = TRUE;
  841. }
  842. }
  843. //accmulate_zoom_in_ds -= delta_ds;
  844. //zoom_in_count++;
  845. }else if(ZOOM_OUT == zoom_flag){ //zoom out when zoom out
  846. if(delta_ds > min(GLIDE_DELTA_DS_MAX_LIMIT, (GLIDE_DELTA_DS_MAX_TIMES*accmulate_zoom_out_ds/zoom_out_count))){
  847. cur_sample_ds = prev_sample_ds;
  848. //printk("discard noise. \n");
  849. ret = TRUE;
  850. }else{
  851. accmulate_zoom_out_ds += delta_ds;
  852. zoom_out_count++;
  853. filter_zoom_out_data(&prev_report_samp, sample_data);
  854. }
  855. zoom_change_cnt = 0;
  856. accmulate_zoom_in_ds = 0;
  857. zoom_in_count = 0;
  858. //printk("ZOOM_OUT: delta_ds= %d. \n", delta_ds);
  859. }else if(ZOOM_INIT_STATE == zoom_flag ||ZOOM_STATIC == zoom_flag){
  860. zoom_out_count ++;
  861. if(zoom_out_count > ZOOM_CHANGE_LIMIT_CNT){
  862. accmulate_zoom_out_ds = delta_ds;
  863. zoom_out_count = 1;
  864. if(ZOOM_INIT_STATE == zoom_flag){
  865. orientation_flag = judge_zoom_orientation(sample_data);
  866. report_up_event_implement(ts_data);
  867. }
  868. filter_zoom_out_data_init();
  869. filter_zoom_out_data(&prev_report_samp, sample_data);
  870. print_filter_double_point_status_info("change to ZOOM_OUT from ZOOM_INIT_STATE. \n");
  871. change_to_zoom_out(ts_data, sample_data);
  872. #if 1
  873. print_filter_double_point_status_info("ZOOM_INIT_STATE: delta_ds= %d. \n", delta_ds);
  874. #endif
  875. }else{
  876. //have not known orientation, discard the point
  877. ret = TRUE;
  878. }
  879. }
  880. }else{ //delta_ds <= HOLD_DS_LIMIT, static mode
  881. //printk("delta_ds == %d. \n", delta_ds);
  882. //zoom_change_cnt
  883. //printk("delta_ds == %d. \n", delta_ds);
  884. hold_cnt++;
  885. cur_sample_ds = prev_sample_ds;
  886. if(hold_cnt > 100000){
  887. hold_cnt = 100;
  888. }
  889. if(unlikely(ZOOM_INIT_STATE == zoom_flag )){
  890. print_filter_double_point_status_info("ZOOM_INIT_STATE: delta_ds == %d. \n", delta_ds);
  891. if(hold_cnt <= ZOOM_CHANGE_LIMIT_CNT){ //discard the first 3 point
  892. ret = TRUE;
  893. }else{
  894. //when change to static mode, and not know orientation yet, need judge orientation.
  895. orientation_flag = judge_zoom_orientation(sample_data);
  896. report_up_event_implement(ts_data);
  897. zoom_flag = ZOOM_STATIC;
  898. change_to_double_mode(ts_data);
  899. memcpy((void*)&prev_report_samp, (void*)sample_data, sizeof(*sample_data));
  900. }
  901. }else{
  902. memcpy((void*)sample_data, (void*)&prev_report_samp, sizeof(*sample_data));
  903. }
  904. //filter_double_point_init(sample_data, 0);
  905. }
  906. return ret;
  907. }
  908. static void report_double_point(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  909. {
  910. int x1,x2,y1,y2;
  911. y1 = 0;
  912. y2 = 0;
  913. //int tmp;
  914. //tmp = X_TURN_POINT<<2;
  915. //printk("enter report_double_point . \n");
  916. if(TRUE == filter_double_point(ts_data, sample_data)){ //noise
  917. return;
  918. }
  919. //when report double point, need to clear single_touch_cnt
  920. ts_data->single_touch_cnt = 0;
  921. if(sample_data->dx < X_TURN_POINT){
  922. x1 = X_CENTER_COORDINATE - (sample_data->dx<<2);
  923. x2 = X_CENTER_COORDINATE + (sample_data->dx<<2);
  924. }else{
  925. x1 = X_CENTER_COORDINATE - X_COMPENSATE - ((sample_data->dx) - X_TURN_POINT);
  926. x2 = X_CENTER_COORDINATE + X_COMPENSATE + ((sample_data->dx) - X_TURN_POINT);
  927. }
  928. #ifdef FIX_ORIENTATION
  929. orientation_flag = ORIENTATION_DEFAULT_VAL;
  930. #endif
  931. //printk("X_TURN_POINT is %d. \n", tmp);
  932. if(0 == orientation_flag){
  933. print_orientation_info("orientation_flag: orientation is not supported or have not known, set the default orientation. \n");
  934. orientation_flag = ORIENTATION_DEFAULT_VAL;
  935. }
  936. if(-1 == orientation_flag){
  937. if(sample_data->dy < Y_TURN_POINT){
  938. y1 = Y_CENTER_COORDINATE - (sample_data->dy<<1);
  939. y2 = Y_CENTER_COORDINATE + (sample_data->dy<<1);
  940. }else{
  941. y1 = Y_CENTER_COORDINATE - Y_COMPENSATE - (sample_data->dy - Y_TURN_POINT);
  942. y2 = Y_CENTER_COORDINATE + Y_COMPENSATE + (sample_data->dy - Y_TURN_POINT);
  943. }
  944. }else if(1 == orientation_flag){
  945. if(sample_data->dy < Y_TURN_POINT){
  946. y2 = Y_CENTER_COORDINATE - (sample_data->dy<<1);
  947. y1 = Y_CENTER_COORDINATE + (sample_data->dy<<1);
  948. }else{
  949. y2 = Y_CENTER_COORDINATE - Y_COMPENSATE - (sample_data->dy - Y_TURN_POINT);
  950. y1 = Y_CENTER_COORDINATE + Y_COMPENSATE + (sample_data->dy - Y_TURN_POINT);
  951. }
  952. }
  953. input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,800);
  954. input_report_abs(ts_data->input, ABS_MT_POSITION_X, x1);
  955. input_report_abs(ts_data->input, ABS_MT_POSITION_Y, y1);
  956. input_mt_sync(ts_data->input);
  957. input_report_abs(ts_data->input, ABS_MT_TOUCH_MAJOR,800);
  958. input_report_abs(ts_data->input, ABS_MT_POSITION_X, x2);
  959. input_report_abs(ts_data->input, ABS_MT_POSITION_Y, y2);
  960. input_mt_sync(ts_data->input);
  961. input_sync(ts_data->input);
  962. print_report_data_info("report two point: x1 = %d, y1 = %d; x2 = %d, y2 = %d. \n",x1, y1, x2, y2);
  963. print_report_data_info("sample_data->dx = %d, sample_data->dy = %d. \n", sample_data->dx, sample_data->dy);
  964. return;
  965. }
  966. static void report_data(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  967. {
  968. //printk("calling report data. \n");
  969. if(TRUE == change_mode){ //only up event happened, change_mode is allowed.
  970. printk("err: report_data: never execute. \n ");
  971. ts_data->single_touch_cnt++;
  972. if(ts_data->single_touch_cnt > UP_TO_SINGLE_CNT_LIMIT){
  973. //change to single touch mode
  974. change_to_single_touch_mode();
  975. report_single_point(ts_data, sample_data);
  976. print_report_data_info("change touch mode to SINGLE_TOUCH_MODE from UP state. \n");
  977. }
  978. }else if(FALSE == change_mode){
  979. //keep in double touch mode
  980. //remain in double touch mode
  981. ts_data->single_touch_cnt++;
  982. if(ts_data->single_touch_cnt > SINGLE_CNT_LIMIT){ //to avoid unconsiously touch
  983. //change to single touch mode
  984. change_to_single_touch_mode();
  985. report_single_point(ts_data, sample_data);
  986. print_report_data_info("change touch mode to SINGLE_TOUCH_MODE from double_touch_mode. \n");
  987. }
  988. }
  989. return;
  990. }
  991. static void report_up_event(unsigned long data)
  992. {
  993. struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)data;
  994. /*when the time is out, and the buffer data can not affect the timer to re-timing immediately,
  995. *this will happen,
  996. *from this we can conclude, the delay_time is not proper, need to be longer
  997. */
  998. if(ts_data->buffer_head != ts_data->buffer_tail){
  999. //printk("warn: when report_up_event, the buffer is not empty. clear the buffer.\n");
  1000. //printk("ts_data->buffer_head = %lu, ts_data->buffer_tail = %lu \n", ts_data->buffer_head, ts_data->buffer_tail);
  1001. //ts_data->buffer_tail = ts_data->buffer_head;
  1002. //do not discard the data, just let the tasklet to take care of it.
  1003. mod_timer(&data_timer, jiffies + ts_data->ts_delay_period);
  1004. tp_do_tasklet(ts_data->buffer_head); //direct calling tasklet, do not use int bottom half, may result in some bad behavior.!!!
  1005. return;
  1006. }
  1007. report_up_event_implement(ts_data);
  1008. return;
  1009. }
  1010. static void process_data(struct sun4i_ts_data *ts_data, struct ts_sample_data *sample_data)
  1011. {
  1012. //printk("enter process_data. \n");
  1013. ts_data->touchflag = 1;
  1014. if(((sample_data->dx) > DUAL_TOUCH)&&((sample_data->dy) > DUAL_TOUCH)){
  1015. ts_data->touchflag = 2;
  1016. ts_data->double_point_cnt++;
  1017. if(UP_TOUCH_MODE == touch_mode ){
  1018. print_orientation_info("sun4i-ts: need to get the single point. \n");
  1019. //the direction should be the default value;
  1020. /*prev_single_sample.x = sample_data->x;
  1021. prev_single_sample.y = sample_data->y;
  1022. */
  1023. reference_point_flag = 0;
  1024. touch_mode = SINGLE_TOUCH_MODE;
  1025. }
  1026. //printk("ts_data->double_point_cnt is %d. \n", ts_data->double_point_cnt);
  1027. if(ts_data->double_point_cnt > DOUBLE_CNT_LIMIT){
  1028. if(sample_data->dx < MAX_DELTA_X && sample_data->dy < MAX_DELTA_Y){
  1029. //ts_data->count = 0;
  1030. if(SINGLE_TOUCH_MODE == touch_mode){
  1031. touch_mode = CHANGING_TO_DOUBLE_TOUCH_MODE;
  1032. orientation_flag = 0;
  1033. filter_double_point_init(sample_data, 1);
  1034. print_orientation_info("sun4i-ts: CHANGING_TO_DOUBLE_TOUCH_MODE orientation_flag == %d . \n", orientation_flag);
  1035. return;
  1036. }
  1037. report_double_point(ts_data, sample_data);
  1038. }
  1039. }
  1040. }else if(1 == ts_data->touchflag){
  1041. if(DOUBLE_TOUCH_MODE == touch_mode ){
  1042. //normally, to really change to single_touch_mode, spend about 100ms
  1043. //printk("receive 1 point when in DOUBLE_TOUCH_MODE, ts_data->single_touch_cnt = %d. \n", ts_data->single_touch_cnt);
  1044. if(6 == ts_data->single_touch_cnt ){ //discard old data, remain in double_touch_mode,and change to ZOOM_INIT_STATE
  1045. filter_zoom_in_data_init();
  1046. filter_zoom_out_data_init();
  1047. prev_single_sample.x = sample_data->x;
  1048. prev_single_sample.y = sample_data->y;
  1049. reference_point_flag = 1;
  1050. orientation_flag = 0;
  1051. filter_double_point_init(sample_data, 0);
  1052. }else if(ts_data->single_touch_cnt > 6){ //update prev_single_sample
  1053. prev_single_sample.x = sample_data->x;
  1054. prev_single_sample.y = sample_data->y;
  1055. reference_point_flag = 1;
  1056. }
  1057. report_data(ts_data, sample_data);
  1058. }else if(SINGLE_TOUCH_MODE == touch_mode ||UP_TOUCH_MODE == touch_mode || CHANGING_TO_DOUBLE_TOUCH_MODE == touch_mode){//remain in single touch mode
  1059. if(SINGLE_TOUCH_MODE == touch_mode ||UP_TOUCH_MODE == touch_mode){
  1060. prev_single_sample.x = sample_data->x;
  1061. prev_single_sample.y = sample_data->y;
  1062. reference_point_flag = 1;
  1063. }
  1064. if(SINGLE_TOUCH_MODE != touch_mode){
  1065. change_to_single_touch_mode();
  1066. }
  1067. report_single_point(ts_data, sample_data);
  1068. }
  1069. }
  1070. return;
  1071. }
  1072. void tp_do_tasklet(unsigned long data)
  1073. {
  1074. //struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)platform_get_drvdata(pdev);
  1075. struct sun4i_ts_data *ts_data = mtTsData;
  1076. struct ts_sample_data *sample_data;
  1077. int head = 0;
  1078. int tail = 0;
  1079. //printk("try to get the lock and setting the running state. \n");
  1080. if(1 == spin_trylock(&tp_do_tasklet_sync)){
  1081. if(1 == tp_do_tasklet_running){
  1082. spin_unlock(&tp_do_tasklet_sync);
  1083. //printk("other thread is running the rountine. \n");
  1084. return;
  1085. }else{
  1086. tp_do_tasklet_running = 1;
  1087. spin_unlock(&tp_do_tasklet_sync);
  1088. }
  1089. }else{
  1090. //printk("failed to get the lock. other thread is using the lock. \n");
  1091. return;
  1092. }
  1093. // printk("get the lock, the running state is setted. to use the data. \n");
  1094. head = (int)data;
  1095. tail = (int)ts_data->buffer_tail; //!!! tail may have changed, while the data is remain?
  1096. if((tail + CYCLE_BUFFER_SIZE*2) < head){ //tail have been modify to avoid overflow
  1097. goto out;
  1098. }
  1099. print_tasklet_info("enter tasklet. head = %d, tail = %d. jiffies == %lu. \n", head, tail, jiffies);
  1100. while((tail) < (head)){ //when tail == head, mean the buffer is empty
  1101. sample_data = &cycle_buffer[tail&(CYCLE_BUFFER_SIZE-1)];
  1102. tail++;
  1103. print_filter_info("sample_data->sample_status == %d, ts_data->ts_process_status == %d \n", \
  1104. sample_data->sample_status, ts_data->ts_process_status);
  1105. #ifdef TP_INT_PERIOD_TEST
  1106. continue;
  1107. #endif
  1108. if(TP_UP == sample_data->sample_status || TP_DOWN == sample_data->sample_status)
  1109. {
  1110. //when received up & down event, reinitialize ts_data->double_point_cnt to debounce for DOUBLE_TOUCH_MODE
  1111. ts_data->double_point_cnt = 0;
  1112. if((TP_DATA_VA == ts_data->ts_process_status || TP_DOWN == ts_data->ts_process_status) && data_timer_status){
  1113. //delay 20ms , ignore up event & down event
  1114. print_filter_info("(prev_sample->sample_time + ts_data->ts_delay_period) == %u, \
  1115. (sample_data->sample_time) == %u. \n", \
  1116. (prev_sample->sample_time + ts_data->ts_delay_period), \
  1117. (sample_data->sample_time));
  1118. 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);
  1119. if(time_after_eq((unsigned long)(prev_sample->sample_time + ts_data->ts_delay_period - DELAY_COMPENSTAE_PEROID), (unsigned long)(sample_data->sample_time))){
  1120. //notice: sample_time may overflow
  1121. print_filter_info("ignore up event & down event. \n");
  1122. mod_timer(&data_timer, jiffies + ts_data->ts_delay_period);
  1123. prev_sample->sample_time = sample_data->sample_time;
  1124. continue;
  1125. }
  1126. }
  1127. }
  1128. switch(sample_data->sample_status)
  1129. {
  1130. case TP_DOWN:
  1131. {
  1132. if(1 == data_timer_status){
  1133. report_up_event_implement(ts_data);
  1134. }
  1135. ts_data->touchflag = 0;
  1136. //ts_data->count = 0;
  1137. ts_data->ts_process_status = TP_DOWN;
  1138. ts_data->double_point_cnt = 0;
  1139. prev_sample->sample_time = sample_data->sample_time;
  1140. reported_data_start_time = sample_data->sample_time;
  1141. print_report_status_info("actuall TP_DOWN . \n");
  1142. break;
  1143. }
  1144. case TP_DATA_VA:
  1145. {
  1146. //memcpy(prev_sample, sample_date, sizeof(ts_sample_data));
  1147. print_filter_info("data: sample_data->sample_time = %lu. \n", sample_data->sample_time);
  1148. prev_data_sample->sample_time = sample_data->sample_time;
  1149. prev_sample->sample_time = sample_data->sample_time;
  1150. process_data(ts_data, sample_data);
  1151. if(0 == data_timer_status){
  1152. mod_timer(&data_timer, jiffies + ts_data->ts_delay_period);
  1153. data_timer_status = 1;
  1154. prev_data_sample->x = sample_data->x;
  1155. prev_data_sample->y = sample_data->y;
  1156. print_report_status_info("timer is start up. \n");
  1157. }else{
  1158. mod_timer(&data_timer, jiffies + ts_data->ts_delay_period);
  1159. print_report_status_info("more ts_data->ts_delay_period ms delay. jiffies + ts_data->ts_delay_period = %lu. \n", jiffies + ts_data->ts_delay_period);
  1160. }
  1161. ts_data->ts_process_status = TP_DATA_VA;
  1162. break;
  1163. }
  1164. case TP_UP :
  1165. {
  1166. //actually, this case will never be run
  1167. if(1 == ts_data->touchflag || 2 == ts_data->touchflag)
  1168. {
  1169. print_report_status_info("actually TP_UP. \n");
  1170. //ts_data->touchflag = 0;
  1171. //ts_data->count = 0;
  1172. //touch_mode = SINGLE_TOUCH_MODE;
  1173. //change_mode = TRUE;
  1174. //ts_data->ts_process_status = TP_UP;
  1175. report_up_event((unsigned long)ts_data);
  1176. }
  1177. break;
  1178. }
  1179. default:
  1180. break;
  1181. }
  1182. }
  1183. //update buffer_tail
  1184. ts_data->buffer_tail = (unsigned long)tail;
  1185. //avoid overflow
  1186. if(ts_data->buffer_tail > (CYCLE_BUFFER_SIZE << 4)){
  1187. writel(0, ts_data->base_addr + TP_INT_FIFOC); //disable irq
  1188. ts_data->buffer_tail -= (CYCLE_BUFFER_SIZE<<3);
  1189. ts_data->buffer_head -= (CYCLE_BUFFER_SIZE<<3); //head may have been change by interrupt
  1190. if(TRUE == tp_irq_state){
  1191. //enable irq
  1192. writel(TP_DATA_IRQ_EN|TP_FIFO_TRIG_LEVEL|TP_FIFO_FLUSH|TP_UP_IRQ_EN|TP_DOWN_IRQ_EN, ts_data->base_addr + TP_INT_FIFOC);
  1193. }
  1194. }
  1195. if(FALSE == tp_irq_state){
  1196. //enable irq
  1197. writel(TP_DATA_IRQ_EN|TP_FIFO_TRIG_LEVEL|TP_FIFO_FLUSH|TP_UP_IRQ_EN|TP_DOWN_IRQ_EN, ts_data->base_addr + TP_INT_FIFOC);
  1198. tp_irq_state = TRUE;
  1199. }
  1200. out:
  1201. tp_do_tasklet_running = 0;
  1202. //printk("after using the cycle buffer. \n");
  1203. }
  1204. static irqreturn_t sun4i_isr_tp(int irq, void *dev_id)
  1205. {
  1206. struct platform_device *pdev = dev_id;
  1207. struct sun4i_ts_data *ts_data = (struct sun4i_ts_data *)platform_get_drvdata(pdev);
  1208. unsigned int reg_val;
  1209. unsigned int reg_fifoc;
  1210. int head_index = (int)(ts_data->buffer_head&(CYCLE_BUFFER_SIZE-1));
  1211. int tail = (int)ts_data->buffer_tail;
  1212. #ifdef TP_INT_PERIOD_TEST
  1213. static int count = 0;
  1214. #endif
  1215. #ifdef TP_TEMP_DEBUG
  1216. static unsigned int temp_cnt = 0;
  1217. static unsigned int temp_data = 0;
  1218. #define TOTAL_TIMES 4
  1219. #endif
  1220. reg_val = readl(TP_BASSADDRESS + TP_INT_FIFOS);
  1221. if(!(reg_val&(TP_DOWN_PENDING | FIFO_DATA_PENDING | TP_UP_PENDING))){
  1222. //printk("non tp irq . \n");
  1223. #ifdef TP_TEMP_DEBUG
  1224. if(reg_val&0x40000)
  1225. {
  1226. writel(reg_val&0x40000,TP_BASSADDRESS + TP_INT_FIFOS);
  1227. reg_val = readl(TP_BASSADDRESS + TEMP_DATA);
  1228. if(temp_cnt < (TOTAL_TIMES - 1))
  1229. {
  1230. temp_data += reg_val;
  1231. temp_cnt++;
  1232. }else{
  1233. temp_data += reg_val;
  1234. temp_data /= TOTAL_TIMES;
  1235. printk("temp = ");
  1236. printk("%d\n",temp_data);
  1237. temp_data = 0;
  1238. temp_cnt = 0;
  1239. }
  1240. return IRQ_HANDLED;
  1241. }
  1242. #endif
  1243. return IRQ_NONE;
  1244. }
  1245. if(((tail+CYCLE_BUFFER_SIZE)) <= (ts_data->buffer_head)){ //when head-tail == CYCLE_BUFFER_SIZE, mean the buffer is full.
  1246. printk("warn: cycle buffer is full. \n");
  1247. //ts_data->buffer_tail++; //ignore one point, increment tail is danger, when tasklet is using the tail.
  1248. writel(0, ts_data->base_addr + TP_INT_FIFOC); //disable irq
  1249. tp_irq_state = FALSE;
  1250. writel(reg_val,TP_BASSADDRESS + TP_INT_FIFOS); //clear irq pending
  1251. tp_tasklet.data = ts_data->buffer_head;
  1252. printk("schedule tasklet. ts_data->buffer_head = %lu, \
  1253. ts_data->buffer_tail = %lu.\n", ts_data->buffer_head, ts_data->buffer_tail);
  1254. tasklet_schedule(&tp_tasklet);
  1255. return IRQ_HANDLED;
  1256. }
  1257. if(reg_val&TP_DOWN_PENDING)
  1258. {
  1259. writel(reg_val&TP_DOWN_PENDING,TP_BASSADDRESS + TP_INT_FIFOS);
  1260. print_int_info("press the screen: jiffies to ms == %u , jiffies == %lu, time: = %llu \n", \
  1261. jiffies_to_msecs((long)get_jiffies_64()), jiffies, get_cpu_idle_time_us(0, &cur_wall_time));
  1262. ts_data->ts_sample_status = TP_DOWN;
  1263. ts_data->count = 0;
  1264. cycle_buffer[head_index].sample_status = TP_DOWN;
  1265. cycle_buffer[head_index].sample_time= jiffies;
  1266. //update buffer_head
  1267. ts_data->buffer_head++;
  1268. #ifdef TP_INT_PERIOD_TEST
  1269. count = 0;
  1270. #endif
  1271. }else if(reg_val&FIFO_DATA_PENDING) //do not report data on up status
  1272. {
  1273. // if((TP_DOWN == ts_data->ts_sample_status || TP_DATA_VA == ts_data->ts_sample_status)){
  1274. ts_data->count++;
  1275. if(ts_data->count > FILTER_NOISE_LOWER_LIMIT){
  1276. cycle_buffer[head_index].x = readl(TP_BASSADDRESS + TP_DATA);
  1277. cycle_buffer[head_index].y = readl(TP_BASSADDRESS + TP_DATA);
  1278. cycle_buffer[head_index].dx = readl(TP_BASSADDRESS + TP_DATA);
  1279. cycle_buffer[head_index].dy = readl(TP_BASSADDRESS + TP_DATA);
  1280. cycle_buffer[head_index].sample_time= jiffies;
  1281. //ts_data->z1 = readl(TP_BASSADDRESS + TP_DATA);
  1282. //ts_data->z2 = readl(TP_BASSADDRESS + TP_DATA);
  1283. cycle_buffer[head_index].sample_status = TP_DATA_VA;
  1284. ts_data->ts_sample_status = TP_DATA_VA;
  1285. //flush fifo
  1286. reg_fifoc = readl(ts_data->base_addr+TP_INT_FIFOC);
  1287. reg_fifoc |= TP_FIFO_FLUSH;
  1288. writel(reg_fifoc, ts_data->base_addr+TP_INT_FIFOC);
  1289. print_int_info("data coming, jiffies to ms == %u , jiffies == %lu, time: = %llu \n", \
  1290. jiffies_to_msecs((long)get_jiffies_64()), jiffies, get_cpu_idle_time_us(0, &cur_wall_time));
  1291. //update buffer_head
  1292. ts_data->buffer_head++;
  1293. #ifdef TP_INT_PERIOD_TEST
  1294. count++;
  1295. printk("jiffies = %d. count = %d. \n", jiffies, count);
  1296. #endif
  1297. }else{
  1298. //flush fifo, the data you do not want to reserved, need to be flush out fifo
  1299. reg_fifoc = readl(ts_data->base_addr+TP_INT_FIFOC);
  1300. reg_fifoc |= TP_FIFO_FLUSH;
  1301. writel(reg_fifoc, ts_data->base_addr+TP_INT_FIFOC);
  1302. }
  1303. udelay(1);
  1304. writel(reg_val&FIFO_DATA_PENDING,TP_BASSADDRESS + TP_INT_FIFOS);
  1305. /* }else{ //INITIAL or UP
  1306. printk("err: data int when tp up. jiffies to ms == %u , jiffies == %llu, time: = %llu \n", \
  1307. jiffies_to_msecs((long)get_jiffies_64()), jiffies, get_cpu_idle_time_us(0, &cur_wall_time));
  1308. //writel(TP_DATA_IRQ_EN|TP_FIFO_TRIG_LEVEL|TP_FIFO_FLUSH|TP_UP_IRQ_EN|TP_DOWN_IRQ_EN, ts_data->base_addr + TP_INT_FIFOC);
  1309. writel(TP_DATA_IRQ_EN|TP_FIFO_TRIG_LEVEL|TP_FIFO_FLUSH|TP_UP_IRQ_EN|TP_DOWN_IRQ_EN, ts_data->base_addr+TP_INT_FIFOC);
  1310. writel(reg_val&FIFO_DATA_PENDING,TP_BASSADDRESS + TP_INT_FIFOS);
  1311. return IRQ_HANDLED;
  1312. }*/
  1313. }else if(reg_val&TP_UP_PENDING) {
  1314. writel(reg_val&TP_UP_PENDING,TP_BASSADDRESS + TP_INT_FIFOS);
  1315. print_int_info("up the screen. jiffies to ms == %u , jiffies == %lu, time: = %llu \n", \
  1316. jiffies_to_msecs((long)get_jiffies_64()), jiffies, get_cpu_idle_time_us(0, &cur_wall_time));
  1317. cycle_buffer[head_index].sample_status = TP_UP;
  1318. ts_data->count = 0;
  1319. cycle_buffer[head_index].sample_time= jiffies;
  1320. //update buffer_head
  1321. ts_data->buffer_head++;
  1322. }
  1323. tp_tasklet.data = ts_data->buffer_head;
  1324. //print_tasklet_info("schedule tasklet. ts_data->buffer_head = %lu, ts_data->buffer_tail = %lu\n", ts_data->buffer_head, ts_data->buffer_tail);
  1325. tasklet_schedule(&tp_tasklet);
  1326. return IRQ_HANDLED;
  1327. }
  1328. static int sun4i_ts_open(struct input_dev *dev)
  1329. {
  1330. /* enable clock */
  1331. return 0;
  1332. }
  1333. static void sun4i_ts_close(struct input_dev *dev)
  1334. {
  1335. /* disable clock */
  1336. }
  1337. static struct sun4i_ts_data *sun4i_ts_data_alloc(struct platform_device *pdev)
  1338. {
  1339. struct sun4i_ts_data *ts_data = kzalloc(sizeof(*ts_data), GFP_KERNEL);
  1340. if (!ts_data)
  1341. return NULL;
  1342. ts_data->input = input_allocate_device();
  1343. if (!ts_data->input) {
  1344. kfree(ts_data);
  1345. return NULL;
  1346. }
  1347. ts_data->input->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
  1348. set_bit(BTN_TOUCH, ts_data->input->keybit);
  1349. input_set_abs_params(ts_data->input, ABS_MT_TOUCH_MAJOR, 0, 1000, 0, 0);
  1350. input_set_abs_params(ts_data->input, ABS_MT_POSITION_X, 0, 4095, 0, 0);
  1351. input_set_abs_params(ts_data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
  1352. ts_data->input->name = pdev->name;
  1353. ts_data->input->phys = "sun4i_ts/input0";
  1354. ts_data->input->id.bustype = BUS_HOST ;
  1355. ts_data->input->id.vendor = 0x0001;
  1356. ts_data->input->id.product = 0x0001;
  1357. ts_data->input->id.version = 0x0100;
  1358. ts_data->input->open = sun4i_ts_open;
  1359. ts_data->input->close = sun4i_ts_close;
  1360. ts_data->input->dev.parent = &pdev->dev;
  1361. ts_data->ts_sample_status = TP_INITIAL;
  1362. ts_data->ts_process_status = TP_INITIAL;
  1363. ts_data->double_point_cnt = 0;
  1364. ts_data->single_touch_cnt = 0;
  1365. ts_data->ts_delay_period = DELAY_PERIOD + DELAY_COMPENSTAE_PEROID;
  1366. ts_data->buffer_head = 0;
  1367. ts_data->buffer_tail = 0;
  1368. return ts_data;
  1369. }
  1370. static void sun4i_ts_data_free(struct sun4i_ts_data *ts_data)
  1371. {
  1372. if (!ts_data)
  1373. return;
  1374. if (ts_data->input)
  1375. input_free_device(ts_data->input);
  1376. kfree(ts_data);
  1377. }
  1378. static int __devinit sun4i_ts_probe(struct platform_device *pdev)
  1379. {
  1380. int err =0;
  1381. int irq = platform_get_irq(pdev, 0);
  1382. struct sun4i_ts_data *ts_data;
  1383. tp_flag = 0;
  1384. #ifdef CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  1385. printk( "sun4i-ts.c: sun4i_ts_probe: start...\n");
  1386. #endif
  1387. ts_data = sun4i_ts_data_alloc(pdev);
  1388. if (!ts_data) {
  1389. dev_err(&pdev->dev, "Cannot allocate driver structures\n");
  1390. err = -ENOMEM;
  1391. goto err_out;
  1392. }
  1393. mtTsData = ts_data;
  1394. //tp_do_tasklet_running = ATOMIC_INIT(1);
  1395. spin_lock_init(&tp_do_tasklet_sync);
  1396. //report_up_event_implement_sync = ATOMIC_INIT(1);
  1397. #ifdef CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  1398. printk("begin get platform resourec\n");
  1399. #endif
  1400. ts_data->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  1401. if (!ts_data->res) {
  1402. err = -ENOMEM;
  1403. dev_err(&pdev->dev, "Can't get the MEMORY\n");
  1404. goto err_out1;
  1405. }
  1406. ts_data->base_addr = (void __iomem *)TP_BASSADDRESS;
  1407. ts_data->irq = irq;
  1408. //tp_irq = irq;
  1409. err = request_irq(irq, sun4i_isr_tp,
  1410. IRQF_DISABLED, pdev->name, pdev);
  1411. if (err) {
  1412. dev_err(&pdev->dev, "Cannot request keypad IRQ\n");
  1413. goto err_out2;
  1414. }
  1415. platform_set_drvdata(pdev, ts_data);
  1416. //printk("Input request \n");
  1417. /* All went ok, so register to the input system */
  1418. err = input_register_device(ts_data->input);
  1419. if (err)
  1420. goto err_out3;
  1421. #ifdef CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  1422. printk("tp init\n");
  1423. #endif
  1424. tp_init();
  1425. #ifdef CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  1426. printk( "sun4i-ts.c: sun4i_ts_probe: end\n");
  1427. #endif
  1428. #ifdef CONFIG_HAS_EARLYSUSPEND
  1429. printk("==register_early_suspend =\n");
  1430. ts_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
  1431. ts_data->early_suspend.suspend = sun4i_ts_suspend;
  1432. ts_data->early_suspend.resume = sun4i_ts_resume;
  1433. register_early_suspend(&ts_data->early_suspend);
  1434. #endif
  1435. init_timer(&data_timer);
  1436. data_timer.expires = jiffies + ts_data->ts_delay_period;
  1437. data_timer.data = (unsigned long)ts_data;
  1438. data_timer.function = report_up_event;
  1439. prev_sample = kzalloc(sizeof(*prev_sample), GFP_KERNEL);
  1440. prev_data_sample = kzalloc(sizeof(*prev_data_sample), GFP_KERNEL);
  1441. return 0;
  1442. err_out3:
  1443. if (ts_data->irq)
  1444. free_irq(ts_data->irq, pdev);
  1445. err_out2:
  1446. err_out1:
  1447. sun4i_ts_data_free(ts_data);
  1448. err_out:
  1449. #ifdef CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  1450. printk( "sun4i-ts.c: sun4i_ts_probe: failed!\n");
  1451. #endif
  1452. return err;
  1453. }
  1454. static int __devexit sun4i_ts_remove(struct platform_device *pdev)
  1455. {
  1456. struct sun4i_ts_data *ts_data = platform_get_drvdata(pdev);
  1457. #ifdef CONFIG_HAS_EARLYSUSPEND
  1458. unregister_early_suspend(&ts_data->early_suspend);
  1459. #endif
  1460. input_unregister_device(ts_data->input);
  1461. free_irq(ts_data->irq, pdev);
  1462. sun4i_ts_data_free(ts_data);
  1463. platform_set_drvdata(pdev, NULL);
  1464. //cancle tasklet?
  1465. return 0;
  1466. }
  1467. static struct platform_driver sun4i_ts_driver = {
  1468. .probe = sun4i_ts_probe,
  1469. .remove = __devexit_p(sun4i_ts_remove),
  1470. #ifdef CONFIG_HAS_EARLYSUSPEND
  1471. #else
  1472. #ifdef CONFIG_PM
  1473. .suspend = sun4i_ts_suspend,
  1474. .resume = sun4i_ts_resume,
  1475. #endif
  1476. #endif
  1477. .driver = {
  1478. .name = "sun4i-ts",
  1479. },
  1480. };
  1481. static void sun4i_ts_nop_release(struct device *dev)
  1482. {
  1483. /* Nothing */
  1484. }
  1485. static struct resource sun4i_ts_resource[] = {
  1486. {
  1487. .flags = IORESOURCE_IRQ,
  1488. .start = IRQ_TP ,
  1489. .end = IRQ_TP ,
  1490. },
  1491. {
  1492. .flags = IORESOURCE_MEM,
  1493. .start = TP_BASSADDRESS,
  1494. .end = TP_BASSADDRESS + 0x100-1,
  1495. },
  1496. };
  1497. struct platform_device sun4i_ts_device = {
  1498. .name = "sun4i-ts",
  1499. .id = -1,
  1500. .dev = {
  1501. .release = sun4i_ts_nop_release,
  1502. },
  1503. .resource = sun4i_ts_resource,
  1504. .num_resources = ARRAY_SIZE(sun4i_ts_resource),
  1505. };
  1506. static int __init sun4i_ts_init(void)
  1507. {
  1508. int device_used = 0;
  1509. int ret = -1;
  1510. //get the config para
  1511. int tp_screen_size = 0;
  1512. #ifdef CONFIG_TOUCHSCREEN_SUN4I_DEBUG
  1513. printk("sun4i-ts.c: sun4i_ts_init: start ...\n");
  1514. #endif
  1515. //config rtp
  1516. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_used", &device_used, sizeof(device_used)/sizeof(int))){
  1517. pr_err("sun4i_ts_init: script_parser_fetch err. \n");
  1518. goto script_parser_fetch_err;
  1519. }
  1520. printk("rtp_used == %d. \n", device_used);
  1521. if(1 == device_used){
  1522. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_screen_size", &tp_screen_size, 1)){
  1523. pr_err("sun4i_ts_init: script_parser_fetch err. \n");
  1524. goto script_parser_fetch_err;
  1525. }
  1526. printk("sun4i-ts: tp_screen_size is %d inch.\n", tp_screen_size);
  1527. if(7 == tp_screen_size){
  1528. dual_touch_distance = 20;
  1529. glide_delta_ds_max_limit = 90;
  1530. tp_regidity_level = 7;
  1531. }else if(5 == tp_screen_size){
  1532. dual_touch_distance = 35;
  1533. glide_delta_ds_max_limit = 150;
  1534. tp_regidity_level = 5;
  1535. }else{
  1536. pr_err("sun4i-ts: tp_screen_size is not supported. \n");
  1537. goto script_parser_fetch_err;
  1538. }
  1539. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_regidity_level", &tp_regidity_level, 1)){
  1540. pr_err("sun4i_ts_init: script_parser_fetch err rtp_regidity_level. \n");
  1541. goto script_parser_fetch_err;
  1542. }
  1543. printk("sun4i-ts: tp_regidity_level is %d.\n", tp_regidity_level);
  1544. if(tp_regidity_level < 2 || tp_regidity_level > 10){
  1545. printk("sun4i-ts: only tp_regidity_level between 2 and 10 is supported. \n");
  1546. goto script_parser_fetch_err;
  1547. }
  1548. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_press_threshold_enable", &tp_press_threshold_enable, 1)){
  1549. pr_err("sun4i_ts_init: script_parser_fetch err rtp_press_threshold_enable. \n");
  1550. goto script_parser_fetch_err;
  1551. }
  1552. printk("sun4i-ts: tp_press_threshold_enable is %d.\n", tp_press_threshold_enable);
  1553. if(0 != tp_press_threshold_enable && 1 != tp_press_threshold_enable){
  1554. printk("sun4i-ts: only tp_press_threshold_enable 0 or 1 is supported. \n");
  1555. goto script_parser_fetch_err;
  1556. }
  1557. if(1 == tp_press_threshold_enable){
  1558. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_press_threshold", &tp_press_threshold, 1)){
  1559. pr_err("sun4i_ts_init: script_parser_fetch err rtp_press_threshold. \n");
  1560. goto script_parser_fetch_err;
  1561. }
  1562. printk("sun4i-ts: rtp_press_threshold is %d.\n", tp_press_threshold);
  1563. if(tp_press_threshold < 0 || tp_press_threshold > 0xFFFFFF){
  1564. printk("sun4i-ts: only tp_regidity_level between 0 and 0xFFFFFF is supported. \n");
  1565. goto script_parser_fetch_err;
  1566. }
  1567. }
  1568. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_sensitive_level", &tp_sensitive_level, 1)){
  1569. pr_err("sun4i_ts_init: script_parser_fetch err rtp_sensitive_level. \n");
  1570. goto script_parser_fetch_err;
  1571. }
  1572. printk("sun4i-ts: rtp_sensitive_level is %d.\n", tp_sensitive_level);
  1573. if(tp_sensitive_level < 0 || tp_sensitive_level > 0xf){
  1574. printk("sun4i-ts: only tp_regidity_level between 0 and 0xf is supported. \n");
  1575. goto script_parser_fetch_err;
  1576. }
  1577. if(SCRIPT_PARSER_OK != script_parser_fetch("rtp_para", "rtp_exchange_x_y_flag", &tp_exchange_x_y, 1)){
  1578. pr_err("sun4i_ts_init: script_parser_fetch err rtp_exchange_x_y_flag. \n");
  1579. goto script_parser_fetch_err;
  1580. }
  1581. printk("sun4i-ts: rtp_exchange_x_y_flag is %d.\n", tp_exchange_x_y);
  1582. if(0 != tp_exchange_x_y && 1 != tp_exchange_x_y){
  1583. printk("sun4i-ts: only tp_exchange_x_y==1 or tp_exchange_x_y==0 is supported. \n");
  1584. goto script_parser_fetch_err;
  1585. }
  1586. }else{
  1587. goto script_parser_fetch_err;
  1588. }
  1589. platform_device_register(&sun4i_ts_device);
  1590. ret = platform_driver_register(&sun4i_ts_driver);
  1591. script_parser_fetch_err:
  1592. return ret;
  1593. }
  1594. static void __exit sun4i_ts_exit(void)
  1595. {
  1596. platform_driver_unregister(&sun4i_ts_driver);
  1597. platform_device_unregister(&sun4i_ts_device);
  1598. }
  1599. module_init(sun4i_ts_init);
  1600. module_exit(sun4i_ts_exit);
  1601. MODULE_AUTHOR("zhengdixu <@>");
  1602. MODULE_DESCRIPTION("sun4i touchscreen driver");
  1603. MODULE_LICENSE("GPL");