diff options
Diffstat (limited to 'drivers/input/touchscreen/rm31080a_ts.c')
-rw-r--r-- | drivers/input/touchscreen/rm31080a_ts.c | 1370 |
1 files changed, 1370 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/rm31080a_ts.c b/drivers/input/touchscreen/rm31080a_ts.c new file mode 100644 index 00000000000..35e85a25486 --- /dev/null +++ b/drivers/input/touchscreen/rm31080a_ts.c | |||
@@ -0,0 +1,1370 @@ | |||
1 | /* | ||
2 | |||
3 | * Raydium RM31080(T007) touchscreen (SPI bus) - Android version | ||
4 | * | ||
5 | * Copyright (C) 2011-2012 Raydium Inc. | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | * | ||
9 | * Version : 0.04 | ||
10 | */ | ||
11 | |||
12 | //============================================================================= | ||
13 | //INCLUDED FILES | ||
14 | //============================================================================= | ||
15 | #include <linux/input.h> // BUS_SPI | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/sched.h> // wake_up_process() | ||
25 | #include <linux/kthread.h> // kthread_create()、kthread_run() | ||
26 | #include <asm/uaccess.h> // copy_to_user(), | ||
27 | #include <linux/miscdevice.h> | ||
28 | #include <asm/siginfo.h> // siginfo | ||
29 | #include <linux/rcupdate.h> // rcu_read_lock | ||
30 | #include <linux/sched.h> // find_task_by_pid_type | ||
31 | #include <linux/syscalls.h> // sys_clock_gettime() | ||
32 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
33 | #include <linux/earlysuspend.h> | ||
34 | #endif | ||
35 | |||
36 | #include <linux/spi/rm31080a_ts.h> | ||
37 | //============================================================================= | ||
38 | //DEFINITIONS | ||
39 | //============================================================================= | ||
40 | #define ENABLE_WORK_QUEUE | ||
41 | #define ENABLE_REPORT_TO_UART | ||
42 | #define ENABLE_RM31080_DEEP_SLEEP | ||
43 | #define ENABLE_AUTO_SCAN | ||
44 | //#define ENABLE_AUTO_FREQ | ||
45 | //#define ENABLE_SPEED_TEST_FUNCTION | ||
46 | //#define ENABLE_TEST_AVERAGE | ||
47 | //#define ENABLE_CALC_QUEUE_COUNT | ||
48 | |||
49 | #define MAX_SPI_FREQ_HZ 50000000 | ||
50 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) | ||
51 | |||
52 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
53 | #define QUEUE_COUNT 128 | ||
54 | #define RAW_DATA_LENGTH 2048 | ||
55 | |||
56 | #define RM_SCAN_MODE_MANUAL 0x00 | ||
57 | #define RM_SCAN_MODE_PREPARE_AUTO 0x01 | ||
58 | #define RM_SCAN_MODE_AUTO_SCAN 0x02 | ||
59 | |||
60 | #define RM_NEED_NONE 0x00 | ||
61 | #define RM_NEED_TO_SEND_SCAN 0x01 | ||
62 | #define RM_NEED_TO_READ_RAW_DATA 0x02 | ||
63 | #define RM_NEED_TO_SEND_SIGNAL 0x03 | ||
64 | #endif | ||
65 | |||
66 | #ifdef ENABLE_WORK_QUEUE | ||
67 | #include <linux/workqueue.h> | ||
68 | #endif | ||
69 | |||
70 | //============================================================================= | ||
71 | //STRUCTURE DECLARATION | ||
72 | //============================================================================= | ||
73 | struct rm31080a_ts_para { | ||
74 | unsigned long ulHalPID; | ||
75 | bool bInitFinish; | ||
76 | bool bCalcFinish; | ||
77 | bool bEnableScriber; | ||
78 | bool bEnableAutoScan; | ||
79 | bool bIsSuspended; | ||
80 | struct mutex mutex; | ||
81 | #ifdef ENABLE_WORK_QUEUE | ||
82 | struct workqueue_struct *rm_workqueue; | ||
83 | struct work_struct rm_work; | ||
84 | bool bIsWorkQueueExecuting; | ||
85 | #endif | ||
86 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
87 | u8 u8ScanModeState; | ||
88 | #endif | ||
89 | }; | ||
90 | |||
91 | struct rm31080_ts { | ||
92 | const struct rm31080_bus_ops *bops; | ||
93 | struct device *dev; | ||
94 | struct input_dev *input; | ||
95 | unsigned int irq; | ||
96 | bool disabled; | ||
97 | bool suspended; | ||
98 | char phys[32]; | ||
99 | struct mutex access_mutex; | ||
100 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
101 | struct early_suspend early_suspend; | ||
102 | #endif | ||
103 | }; | ||
104 | |||
105 | struct rm31080_bus_ops { | ||
106 | u16 bustype; | ||
107 | int (*read) (struct device * dev, u8 reg); | ||
108 | int (*multi_read) (struct device * dev, u8 first_reg, u8 count, | ||
109 | u16 * buf); | ||
110 | int (*write) (struct device * dev, u8 reg, u16 val); | ||
111 | }; | ||
112 | |||
113 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
114 | struct rm31080_queue_info { | ||
115 | u8(*pQueue)[RAW_DATA_LENGTH]; | ||
116 | u16 u16Front; | ||
117 | u16 u16Rear; | ||
118 | }; | ||
119 | #endif | ||
120 | |||
121 | //============================================================================= | ||
122 | //GLOBAL VARIABLES DECLARATION | ||
123 | //============================================================================= | ||
124 | struct input_dev *g_input_dev; | ||
125 | struct spi_device *g_spi; | ||
126 | struct rm31080a_ts_para g_stTs; | ||
127 | |||
128 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
129 | struct rm31080_queue_info g_stQ; | ||
130 | #endif | ||
131 | |||
132 | //============================================================================= | ||
133 | //FUNCTION DECLARATION | ||
134 | //============================================================================= | ||
135 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
136 | static void rm31080_early_suspend(struct early_suspend *es); | ||
137 | static void rm31080_early_resume(struct early_suspend *es); | ||
138 | #endif | ||
139 | //============================================================================= | ||
140 | // Description: | ||
141 | // Debug function: test speed. | ||
142 | // Input: | ||
143 | // N/A | ||
144 | // Output: | ||
145 | // 1:succeed | ||
146 | // 0:failed | ||
147 | //============================================================================= | ||
148 | #ifdef ENABLE_SPEED_TEST_FUNCTION | ||
149 | void my_calc_time(int iStart) | ||
150 | { | ||
151 | static volatile unsigned int u32Max = UINT_MAX; | ||
152 | |||
153 | static long iTimebuffer[1000]; | ||
154 | static unsigned long long t1, t2; | ||
155 | unsigned long nanosec_rem; | ||
156 | static int iIndex = 0; | ||
157 | |||
158 | if (iStart) { | ||
159 | t1 = cpu_clock(u32Max); | ||
160 | return; | ||
161 | } else | ||
162 | t2 = cpu_clock(u32Max); | ||
163 | |||
164 | t2 = t2 - t1; | ||
165 | |||
166 | nanosec_rem = do_div(t2, 1000000000); | ||
167 | |||
168 | if (t2) { //more than 1 Second | ||
169 | iTimebuffer[iIndex] = 999999; | ||
170 | } else { | ||
171 | iTimebuffer[iIndex] = nanosec_rem / 1000; //micro second | ||
172 | } | ||
173 | |||
174 | iIndex++; | ||
175 | if (iIndex == 1000) { | ||
176 | for (iIndex = 0; iIndex < 1000; iIndex++) { | ||
177 | printk(" %04d,%06d\n", iIndex, | ||
178 | (u32) iTimebuffer[iIndex]); | ||
179 | } | ||
180 | iIndex = 0; | ||
181 | } | ||
182 | |||
183 | } | ||
184 | #endif //ENABLE_SPEED_TEST_FUNCTION | ||
185 | //============================================================================= | ||
186 | // Description: | ||
187 | // RM31080 spi interface. | ||
188 | // Input: | ||
189 | // N/A | ||
190 | // Output: | ||
191 | // 1:succeed | ||
192 | // 0:failed | ||
193 | //============================================================================= | ||
194 | int rm31080_spi_read(u8 u8addr, u8 * rxbuf, size_t len) | ||
195 | { | ||
196 | static DEFINE_MUTEX(lock); | ||
197 | |||
198 | int status; | ||
199 | struct spi_message message; | ||
200 | struct spi_transfer x[2]; | ||
201 | |||
202 | if (!mutex_trylock(&lock)) { | ||
203 | //printk("Raydium TS: rm31080_spi_read trylock fail\n"); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | spi_message_init(&message); | ||
208 | memset(x, 0, sizeof x); | ||
209 | |||
210 | u8addr |= 0x80; | ||
211 | x[0].len = 1; | ||
212 | x[0].tx_buf = &u8addr; | ||
213 | spi_message_add_tail(&x[0], &message); | ||
214 | |||
215 | x[1].len = len; | ||
216 | x[1].rx_buf = rxbuf; | ||
217 | spi_message_add_tail(&x[1], &message); | ||
218 | |||
219 | status = spi_sync(g_spi, &message); | ||
220 | |||
221 | mutex_unlock(&lock); | ||
222 | return status; // 0 = succeed | ||
223 | } | ||
224 | |||
225 | int rm31080_spi_write(u8 * txbuf, size_t len) | ||
226 | { | ||
227 | return spi_write(g_spi, txbuf, len); | ||
228 | } | ||
229 | |||
230 | static int rm31080_spi_byte_read(u8 u8Addr, u8 * pu8Value) | ||
231 | { | ||
232 | int iErrorCode; | ||
233 | iErrorCode = rm31080_spi_read(u8Addr, pu8Value, 1); | ||
234 | if (iErrorCode != 0) { | ||
235 | return 0; //fail | ||
236 | } | ||
237 | return 1; | ||
238 | } | ||
239 | |||
240 | static int rm31080_spi_byte_write(u8 u8Addr, u8 u8Value) | ||
241 | { | ||
242 | int iErrorCode; | ||
243 | u8 buf[2]; | ||
244 | buf[0] = u8Addr; | ||
245 | buf[1] = u8Value; | ||
246 | |||
247 | iErrorCode = rm31080_spi_write(buf, 2); | ||
248 | |||
249 | if (iErrorCode != 0) { | ||
250 | //printk("rm31080_spi_write_byte failed:Reg=%x", u8Addr); | ||
251 | return 0; //fail | ||
252 | } | ||
253 | return 1; | ||
254 | } | ||
255 | |||
256 | //============================================================================= | ||
257 | // Description: | ||
258 | // RM31080 control functions. | ||
259 | // Input: | ||
260 | // N/A | ||
261 | // Output: | ||
262 | // 1:succeed | ||
263 | // 0:failed | ||
264 | //============================================================================= | ||
265 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
266 | |||
267 | #define RM31080_REG_01 0x01 | ||
268 | #define RM31080_REG_02 0x02 | ||
269 | #define RM31080_REG_09 0x09 | ||
270 | #define RM31080_REG_0E 0x0E | ||
271 | #define RM31080_REG_10 0x10 | ||
272 | #define RM31080_REG_11 0x11 | ||
273 | #define RM31080_REG_1F 0x1F | ||
274 | #define RM31080_REG_40 0x40 | ||
275 | #define RM31080_REG_41 0x41 | ||
276 | #define RM31080_REG_80 0x80 | ||
277 | #define RM31080_REG_F2 0xF2 | ||
278 | |||
279 | #define RM31080_RAW_DATA_LENGTH 1530 | ||
280 | static int rm31080_ctrl_clear_int(void) | ||
281 | { | ||
282 | u8 u8Flag; | ||
283 | return rm31080_spi_byte_read(RM31080_REG_F2, &u8Flag); | ||
284 | } | ||
285 | |||
286 | #ifdef ENABLE_AUTO_SCAN | ||
287 | void rm31080_ctrl_enter_auto_mode(void) | ||
288 | { | ||
289 | //Enable auto scan | ||
290 | rm31080_spi_byte_write(RM31080_REG_09, 0x10 | 0x40); | ||
291 | } | ||
292 | |||
293 | void rm31080_ctrl_leave_auto_mode(void) | ||
294 | { | ||
295 | //Disable auto scan | ||
296 | rm31080_spi_byte_write(RM31080_REG_09, 0x00); | ||
297 | } | ||
298 | #endif //ENABLE_AUTO_SCAN | ||
299 | |||
300 | #ifdef ENABLE_RM31080_DEEP_SLEEP | ||
301 | static int rm31080_ctrl_suspend(void) | ||
302 | { | ||
303 | //Flow designed by Roger 20110930 | ||
304 | //rm31080_ts_send_signal(g_stTs.ulHalPID,RM_SIGNAL_SUSPEND); | ||
305 | g_stTs.bInitFinish = 0; | ||
306 | msleep(8); | ||
307 | rm31080_ctrl_clear_int(); | ||
308 | //disable auto scan | ||
309 | rm31080_spi_byte_write(RM31080_REG_09, 0x00); | ||
310 | rm31080_spi_byte_write(RM31080_REG_10, 0x14); | ||
311 | rm31080_spi_byte_write(RM31080_REG_11, 0x17); | ||
312 | msleep(15); | ||
313 | rm31080_spi_byte_write(RM31080_REG_11, 0x06); | ||
314 | return 1; | ||
315 | } | ||
316 | #endif | ||
317 | |||
318 | static int rm31080_ctrl_scan_start(void) | ||
319 | { | ||
320 | return rm31080_spi_byte_write(RM31080_REG_11, 0x17); | ||
321 | } | ||
322 | |||
323 | static u32 rm31080_ctrl_configure(void) | ||
324 | { | ||
325 | u32 u32Flag; | ||
326 | |||
327 | switch (g_stTs.u8ScanModeState) { | ||
328 | case RM_SCAN_MODE_MANUAL: | ||
329 | u32Flag = | ||
330 | RM_NEED_TO_SEND_SCAN | RM_NEED_TO_READ_RAW_DATA | | ||
331 | RM_NEED_TO_SEND_SIGNAL; | ||
332 | break; | ||
333 | #ifdef ENABLE_AUTO_SCAN | ||
334 | case RM_SCAN_MODE_PREPARE_AUTO: | ||
335 | rm31080_ctrl_enter_auto_mode(); | ||
336 | g_stTs.u8ScanModeState = RM_SCAN_MODE_AUTO_SCAN; | ||
337 | u32Flag = RM_NEED_NONE; | ||
338 | break; | ||
339 | case RM_SCAN_MODE_AUTO_SCAN: | ||
340 | rm31080_ctrl_leave_auto_mode(); | ||
341 | rm31080_ctrl_scan_start(); | ||
342 | g_stTs.u8ScanModeState = RM_SCAN_MODE_MANUAL; | ||
343 | u32Flag = | ||
344 | RM_NEED_TO_SEND_SCAN | RM_NEED_TO_READ_RAW_DATA | | ||
345 | RM_NEED_TO_SEND_SIGNAL; | ||
346 | break; | ||
347 | #endif //ENABLE_AUTO_SCAN | ||
348 | default: | ||
349 | u32Flag = RM_NEED_NONE; | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | return u32Flag; | ||
354 | } | ||
355 | |||
356 | static void rm31080_enter_manual_mode(void) | ||
357 | { | ||
358 | flush_workqueue(g_stTs.rm_workqueue); | ||
359 | |||
360 | if (g_stTs.u8ScanModeState == RM_SCAN_MODE_MANUAL) | ||
361 | return; | ||
362 | |||
363 | if (g_stTs.u8ScanModeState == RM_SCAN_MODE_PREPARE_AUTO) { | ||
364 | g_stTs.u8ScanModeState = RM_SCAN_MODE_MANUAL; | ||
365 | return; | ||
366 | } | ||
367 | |||
368 | if (g_stTs.u8ScanModeState == RM_SCAN_MODE_AUTO_SCAN) { | ||
369 | rm31080_ctrl_leave_auto_mode(); | ||
370 | g_stTs.u8ScanModeState = RM_SCAN_MODE_MANUAL; | ||
371 | msleep(10); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | static int rm31080_ctrl_read_raw_data(u8 * p) | ||
376 | { | ||
377 | int iRet; | ||
378 | iRet = rm31080_spi_byte_write(RM31080_REG_01, 0x10); | ||
379 | if (iRet) | ||
380 | iRet = rm31080_spi_byte_write(RM31080_REG_02, 0x00); | ||
381 | |||
382 | if (iRet) { | ||
383 | iRet = rm31080_spi_read(RM31080_REG_80, p, RM31080_RAW_DATA_LENGTH); //return 0 =succeed | ||
384 | iRet = !iRet; | ||
385 | } | ||
386 | |||
387 | if (!iRet) { | ||
388 | //printk("rm31080 read raw data failed\n"); | ||
389 | } | ||
390 | |||
391 | return iRet; | ||
392 | } | ||
393 | #endif //ENABLE_RAW_DATA_QUEUE | ||
394 | //============================================================================= | ||
395 | // Description: | ||
396 | // Queuing functions. | ||
397 | // Input: | ||
398 | // N/A | ||
399 | // Output: | ||
400 | // 0:succeed | ||
401 | // others:error code | ||
402 | //============================================================================= | ||
403 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
404 | |||
405 | static void rm31080_queue_reset(void) | ||
406 | { | ||
407 | g_stQ.u16Rear = 0; | ||
408 | g_stQ.u16Front = 0; | ||
409 | } | ||
410 | |||
411 | static int rm31080_queue_init(void) | ||
412 | { | ||
413 | rm31080_queue_reset(); | ||
414 | g_stQ.pQueue = kmalloc(QUEUE_COUNT * RAW_DATA_LENGTH, GFP_KERNEL); | ||
415 | if (g_stQ.pQueue == NULL) { | ||
416 | //printk("rm31080_queue_init failed\n"); | ||
417 | return -ENOMEM; | ||
418 | } | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static void rm31080_queue_free(void) | ||
423 | { | ||
424 | if (!g_stQ.pQueue) | ||
425 | return; | ||
426 | kfree(g_stQ.pQueue); | ||
427 | g_stQ.pQueue = NULL; | ||
428 | } | ||
429 | |||
430 | //============================================================================= | ||
431 | // Description: | ||
432 | // About full/empty buffer distinction, | ||
433 | // There are a number of solutions like: | ||
434 | // 1.Always keep one slot open. | ||
435 | // 2.Use a fill count to distinguish the two cases. | ||
436 | // 3.Use read and write counts to get the fill count from. | ||
437 | // 4.Use absolute indices. | ||
438 | // we chose "keep one slot open" to make it simple and robust | ||
439 | // and also avoid race condition. | ||
440 | // Input: | ||
441 | // N/A | ||
442 | // Output: | ||
443 | // 1:empty | ||
444 | // 0:not empty | ||
445 | //============================================================================= | ||
446 | static int rm31080_queue_is_empty(void) | ||
447 | { | ||
448 | if (g_stQ.u16Rear == g_stQ.u16Front) | ||
449 | return 1; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | //============================================================================= | ||
454 | // Description: | ||
455 | // check queue full. | ||
456 | // Input: | ||
457 | // N/A | ||
458 | // Output: | ||
459 | // 1:full | ||
460 | // 0:not full | ||
461 | //============================================================================= | ||
462 | static int rm31080_queue_is_full(void) | ||
463 | { | ||
464 | if (g_stQ.u16Rear + 1 == g_stQ.u16Front) | ||
465 | return 1; | ||
466 | |||
467 | if ((g_stQ.u16Rear == (QUEUE_COUNT - 1)) && (g_stQ.u16Front == 0)) | ||
468 | return 1; | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | #ifdef ENABLE_CALC_QUEUE_COUNT | ||
474 | static int rm31080_queue_get_current_count(void) | ||
475 | { | ||
476 | if (g_stQ.u16Rear >= g_stQ.u16Front) | ||
477 | return g_stQ.u16Rear - g_stQ.u16Front; | ||
478 | |||
479 | return (QUEUE_COUNT - g_stQ.u16Front) + g_stQ.u16Rear; | ||
480 | } | ||
481 | #endif | ||
482 | static void *rm31080_enqueue_start(void) | ||
483 | { | ||
484 | if (!g_stQ.pQueue) //error handling for no memory | ||
485 | return NULL; | ||
486 | |||
487 | if (!rm31080_queue_is_full()) | ||
488 | return &g_stQ.pQueue[g_stQ.u16Rear]; | ||
489 | |||
490 | //printk("rm31080 Queue full with Queue Count:%d\n", QUEUE_COUNT); | ||
491 | return NULL; | ||
492 | } | ||
493 | |||
494 | static void rm31080_enqueue_finish(void) | ||
495 | { | ||
496 | if (g_stQ.u16Rear == (QUEUE_COUNT - 1)) | ||
497 | g_stQ.u16Rear = 0; | ||
498 | else | ||
499 | g_stQ.u16Rear++; | ||
500 | } | ||
501 | |||
502 | static void *rm31080_dequeue_start(void) | ||
503 | { | ||
504 | if (!rm31080_queue_is_empty()) | ||
505 | return &g_stQ.pQueue[g_stQ.u16Front]; | ||
506 | |||
507 | return NULL; | ||
508 | } | ||
509 | |||
510 | static void rm31080_dequeue_finish(void) | ||
511 | { | ||
512 | if (g_stQ.u16Front == (QUEUE_COUNT - 1)) | ||
513 | g_stQ.u16Front = 0; | ||
514 | else | ||
515 | g_stQ.u16Front++; | ||
516 | } | ||
517 | |||
518 | static long rm31080_queue_read_raw_data(u8 * p, u32 u32Len) | ||
519 | { | ||
520 | u8 *pQueue; | ||
521 | u32 u32Ret; | ||
522 | pQueue = rm31080_dequeue_start(); | ||
523 | if (!pQueue) | ||
524 | return 0; | ||
525 | |||
526 | u32Ret = copy_to_user(p, pQueue, u32Len); | ||
527 | if (u32Ret != 0) | ||
528 | return 0; | ||
529 | |||
530 | rm31080_dequeue_finish(); | ||
531 | return 1; | ||
532 | |||
533 | } | ||
534 | #endif //ENABLE_RAW_DATA_QUEUE | ||
535 | |||
536 | //============================================================================= | ||
537 | // Description: | ||
538 | // Copy Config(Parameters) to HAL's Buffer | ||
539 | // Input: | ||
540 | // p: HAL's buffer | ||
541 | // u32Len : buffer size | ||
542 | // Output: | ||
543 | // 1: succeed | ||
544 | // 0: failed | ||
545 | //============================================================================= | ||
546 | static long rm31080_get_config(u8 * p, u32 u32Len) | ||
547 | { | ||
548 | u32 u32Ret; | ||
549 | struct rm_spi_ts_platform_data *pdata; | ||
550 | pdata = g_input_dev->dev.parent->platform_data; | ||
551 | u32Ret = copy_to_user(p, pdata->config, u32Len); | ||
552 | if (u32Ret != 0) | ||
553 | return 0; | ||
554 | return 1; | ||
555 | } | ||
556 | |||
557 | #ifdef ENABLE_AUTO_FREQ | ||
558 | void raydium_auto_freq() | ||
559 | { | ||
560 | g_stTs.bInitFinish = 0; | ||
561 | msleep(10); | ||
562 | rm31080_ctrl_clear_int(); | ||
563 | |||
564 | //roger_auto_freq_detection(); | ||
565 | |||
566 | g_stTs.bInitFinish = 1; | ||
567 | rm31080_ctrl_scan_start(); | ||
568 | |||
569 | } | ||
570 | #endif //ENABLE_TEST_AUTO_FREQ | ||
571 | //============================================================================= | ||
572 | #ifdef ENABLE_AUTO_SCAN | ||
573 | void raydium_change_scan_mode(u8 u8TouchCount) | ||
574 | { | ||
575 | static u32 u32NoTouchCount = 0; | ||
576 | if (u8TouchCount) { | ||
577 | u32NoTouchCount = 0; | ||
578 | return; | ||
579 | } | ||
580 | if (u32NoTouchCount < 100) { | ||
581 | u32NoTouchCount++; | ||
582 | } else if (g_stTs.u8ScanModeState == RM_SCAN_MODE_MANUAL) { | ||
583 | #ifdef ENABLE_AUTO_FREQ | ||
584 | raydium_auto_freq(); | ||
585 | #else | ||
586 | if (g_stTs.bEnableAutoScan) | ||
587 | g_stTs.u8ScanModeState = RM_SCAN_MODE_PREPARE_AUTO; | ||
588 | #endif | ||
589 | u32NoTouchCount = 0; | ||
590 | } | ||
591 | } | ||
592 | #endif //ENABLE_AUTO_SCAN | ||
593 | //============================================================================= | ||
594 | //report touch data for scriber | ||
595 | // | ||
596 | //============================================================================= | ||
597 | #ifdef ENABLE_REPORT_TO_UART | ||
598 | void raydium_report_to_uart_printf(unsigned char *ucData, unsigned char ucCount) | ||
599 | { | ||
600 | unsigned char i; | ||
601 | for (i = 0; i < ucCount; i++) { | ||
602 | printk("%02X", ucData[i]); | ||
603 | } | ||
604 | printk("\n"); | ||
605 | } | ||
606 | |||
607 | void raydium_report_to_uart(void *p) | ||
608 | { | ||
609 | unsigned char ucData[1 + 1 + (4 * 12) + 1]; //1=Tag,1=Touch count,4=(xH xL ,yH yL) ,12=max point,1=Check sum | ||
610 | rm_touch_event *spTP; | ||
611 | unsigned short usX, usY; | ||
612 | int i, j; | ||
613 | |||
614 | if (g_stTs.bEnableScriber == 0) | ||
615 | return; | ||
616 | |||
617 | spTP = (rm_touch_event *) p; | ||
618 | |||
619 | ucData[0] = 0x8E; | ||
620 | ucData[1] = spTP->ucTouchCount; | ||
621 | j = 2; | ||
622 | for (i = 0; i < spTP->ucTouchCount; i++) { | ||
623 | usX = spTP->usX[i] + 1; //1~1536 | ||
624 | usY = spTP->usY[i] + 1; //1~960 | ||
625 | ucData[j++] = ((usX >> 8) & 0xFF) | (spTP->ucID[i] << 4); //add id | ||
626 | ucData[j++] = ((usX) & 0xFF); | ||
627 | ucData[j++] = ((usY >> 8) & 0xFF); | ||
628 | ucData[j++] = ((usY) & 0xFF); | ||
629 | } | ||
630 | |||
631 | //check sum | ||
632 | ucData[j] = 0; | ||
633 | for (i = 0; i < j; i++) { | ||
634 | ucData[j] += ucData[i]; | ||
635 | } | ||
636 | ucData[j] = 0x100 - ucData[j]; | ||
637 | j++; | ||
638 | |||
639 | |||
640 | raydium_report_to_uart_printf(ucData, j); | ||
641 | if (spTP->ucTouchCount == 0) //send more , to avoid losing | ||
642 | { | ||
643 | raydium_report_to_uart_printf(ucData, j); | ||
644 | raydium_report_to_uart_printf(ucData, j); | ||
645 | } | ||
646 | } | ||
647 | #endif | ||
648 | //============================================================================= | ||
649 | void raydium_report_pointer(void *p) | ||
650 | { | ||
651 | static unsigned char ucLastTouchCount = 0; | ||
652 | int i; | ||
653 | int iCount; | ||
654 | rm_touch_event *spTP; | ||
655 | spTP = (rm_touch_event *) p; | ||
656 | |||
657 | iCount = max(ucLastTouchCount, spTP->ucTouchCount); | ||
658 | if (iCount) { | ||
659 | for (i = 0; i < iCount; i++) { | ||
660 | if (i == 10) | ||
661 | break; //due to the "touch test" can't support great than 10 points | ||
662 | |||
663 | if (i < spTP->ucTouchCount) { | ||
664 | input_report_abs(g_input_dev, | ||
665 | ABS_MT_TRACKING_ID, | ||
666 | spTP->ucID[i]); | ||
667 | |||
668 | input_report_abs(g_input_dev, | ||
669 | ABS_MT_TOUCH_MAJOR, 100); | ||
670 | if (spTP->usX[i] >= (RM_INPUT_RESOLUTION_X - 1)) | ||
671 | input_report_abs(g_input_dev, ABS_MT_POSITION_X, (RM_INPUT_RESOLUTION_X - 1) - 1); //fixed bug: OS scale fail | ||
672 | else | ||
673 | input_report_abs(g_input_dev, | ||
674 | ABS_MT_POSITION_X, | ||
675 | spTP->usX[i]); | ||
676 | |||
677 | if (spTP->usY[i] >= (RM_INPUT_RESOLUTION_Y - 1)) | ||
678 | input_report_abs(g_input_dev, ABS_MT_POSITION_Y, (RM_INPUT_RESOLUTION_Y - 1) - 1); //fixed bug: OS scale fail | ||
679 | else | ||
680 | input_report_abs(g_input_dev, | ||
681 | ABS_MT_POSITION_Y, | ||
682 | spTP->usY[i]); | ||
683 | } | ||
684 | input_mt_sync(g_input_dev); | ||
685 | } | ||
686 | ucLastTouchCount = spTP->ucTouchCount; | ||
687 | input_report_key(g_input_dev, BTN_TOUCH, | ||
688 | spTP->ucTouchCount > 0); | ||
689 | input_sync(g_input_dev); | ||
690 | #ifdef ENABLE_REPORT_TO_UART | ||
691 | raydium_report_to_uart(p); | ||
692 | #endif | ||
693 | |||
694 | } | ||
695 | |||
696 | #ifdef ENABLE_AUTO_SCAN | ||
697 | raydium_change_scan_mode(spTP->ucTouchCount); | ||
698 | #endif | ||
699 | } | ||
700 | |||
701 | //============================================================================= | ||
702 | |||
703 | //============================================================================= | ||
704 | int rm31080_ts_send_signal(int pid, int iInfo) | ||
705 | { | ||
706 | struct siginfo info; | ||
707 | struct task_struct *t; | ||
708 | int ret; | ||
709 | |||
710 | /* send the signal */ | ||
711 | memset(&info, 0, sizeof(struct siginfo)); | ||
712 | info.si_signo = RM_TS_SIGNAL; | ||
713 | info.si_code = SI_QUEUE; // this is bit of a trickery: SI_QUEUE is normally used by sigqueue from user space, | ||
714 | // and kernel space should use SI_KERNEL. But if SI_KERNEL is used the real_time data | ||
715 | // is not delivered to the user space signal handler function. | ||
716 | info.si_int = iInfo; //real time signals may have 32 bits of data. | ||
717 | |||
718 | rcu_read_lock(); | ||
719 | t = find_task_by_vpid(pid); | ||
720 | if (t == NULL) { | ||
721 | //printk("no such pid\n"); | ||
722 | rcu_read_unlock(); | ||
723 | return -ENODEV; | ||
724 | } | ||
725 | rcu_read_unlock(); | ||
726 | ret = send_sig_info(RM_TS_SIGNAL, &info, t); //send the signal | ||
727 | if (ret < 0) { | ||
728 | //printk("error sending signal\n"); | ||
729 | return ret; | ||
730 | } | ||
731 | |||
732 | return ret; | ||
733 | } | ||
734 | |||
735 | //============================================================================= | ||
736 | static void __rm31080_enable(struct rm31080_ts *ts) | ||
737 | { | ||
738 | enable_irq(ts->irq); | ||
739 | } | ||
740 | |||
741 | static void __rm31080_disable(struct rm31080_ts *ts) | ||
742 | { | ||
743 | disable_irq(ts->irq); | ||
744 | } | ||
745 | |||
746 | static void vtest_toggle(struct rm31080_ts *ts, bool disable) | ||
747 | { | ||
748 | mutex_lock(&ts->input->mutex); | ||
749 | |||
750 | if (!ts->suspended && ts->input->users != 0) { | ||
751 | |||
752 | if (disable) { | ||
753 | if (ts->disabled) | ||
754 | __rm31080_enable(ts); | ||
755 | } else { | ||
756 | if (!ts->disabled) | ||
757 | __rm31080_disable(ts); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | ts->disabled = disable; | ||
762 | |||
763 | mutex_unlock(&ts->input->mutex); | ||
764 | } | ||
765 | |||
766 | static ssize_t vtest_disable_show(struct device *dev, | ||
767 | struct device_attribute *attr, char *buf) | ||
768 | { | ||
769 | struct rm31080_ts *ts = dev_get_drvdata(dev); | ||
770 | |||
771 | return sprintf(buf, "%u\n", ts->disabled); | ||
772 | } | ||
773 | |||
774 | static ssize_t vtest_disable_store(struct device *dev, | ||
775 | struct device_attribute *attr, | ||
776 | const char *buf, size_t count) | ||
777 | { | ||
778 | struct rm31080_ts *ts = dev_get_drvdata(dev); | ||
779 | unsigned long val; | ||
780 | int error; | ||
781 | |||
782 | error = strict_strtoul(buf, 10, &val); | ||
783 | if (error) | ||
784 | return error; | ||
785 | |||
786 | vtest_toggle(ts, val); | ||
787 | |||
788 | return count; | ||
789 | } | ||
790 | |||
791 | static DEVICE_ATTR(disable, 0664, vtest_disable_show, vtest_disable_store); | ||
792 | static struct attribute *vtest_attributes[] = { | ||
793 | &dev_attr_disable.attr, | ||
794 | NULL | ||
795 | }; | ||
796 | |||
797 | static const struct attribute_group vtest_attr_group = { | ||
798 | .attrs = vtest_attributes, | ||
799 | }; | ||
800 | |||
801 | static int rm31080_input_open(struct input_dev *input) | ||
802 | { | ||
803 | struct rm31080_ts *ts = input_get_drvdata(input); | ||
804 | |||
805 | /* protected by input->mutex */ | ||
806 | if (!ts->disabled && !ts->suspended) | ||
807 | __rm31080_enable(ts); | ||
808 | |||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | static void rm31080_input_close(struct input_dev *input) | ||
813 | { | ||
814 | struct rm31080_ts *ts = input_get_drvdata(input); | ||
815 | |||
816 | /* protected by input->mutex */ | ||
817 | if (!ts->disabled && !ts->suspended) | ||
818 | __rm31080_disable(ts); | ||
819 | } | ||
820 | |||
821 | //============================================================================= | ||
822 | |||
823 | #ifdef ENABLE_TEST_AVERAGE //only for test | ||
824 | #define _AVERAGE_COUNT 2 | ||
825 | s8 g_bAverageBuf[_AVERAGE_COUNT][2048]; | ||
826 | int test_soft_average(s8 * pSource) | ||
827 | { | ||
828 | static u8 u8AverageIndex = 0; | ||
829 | static u8 u8StartAverage = 0; | ||
830 | u16 i, j; | ||
831 | s16 s16Sum; | ||
832 | |||
833 | for (i = 0; i < RM31080_RAW_DATA_LENGTH; i++) //RM31080_RAW_DATA_LENGTH =1530 | ||
834 | g_bAverageBuf[u8AverageIndex][i] = pSource[i] - 0x80; | ||
835 | u8AverageIndex++; | ||
836 | |||
837 | if (u8AverageIndex == _AVERAGE_COUNT) { | ||
838 | u8StartAverage = 1; | ||
839 | u8AverageIndex = 0; | ||
840 | } | ||
841 | else | ||
842 | { | ||
843 | u8StartAverage = 0; | ||
844 | } | ||
845 | |||
846 | if (u8StartAverage) { | ||
847 | for (i = 0; i < RM31080_RAW_DATA_LENGTH; i++) { | ||
848 | s16Sum = 0; | ||
849 | for (j = 0; j < _AVERAGE_COUNT; j++) | ||
850 | s16Sum += g_bAverageBuf[j][i]; | ||
851 | pSource[i] = (s16Sum / _AVERAGE_COUNT) + 0x80; | ||
852 | } | ||
853 | return 1; | ||
854 | } | ||
855 | return 0; | ||
856 | } | ||
857 | #endif | ||
858 | |||
859 | #ifdef ENABLE_WORK_QUEUE | ||
860 | //1.2 | ||
861 | static void rm_work_handler(struct work_struct *work) | ||
862 | { | ||
863 | void *pKernelBuffer; | ||
864 | u32 u32Flag; | ||
865 | int iRet; | ||
866 | |||
867 | |||
868 | if (g_stTs.bIsSuspended) { | ||
869 | //printk("rm_work_handler stops after suspend\n"); | ||
870 | return; | ||
871 | } | ||
872 | |||
873 | g_stTs.bIsWorkQueueExecuting = 1; | ||
874 | |||
875 | iRet = rm31080_ctrl_clear_int(); | ||
876 | |||
877 | u32Flag = rm31080_ctrl_configure(); | ||
878 | |||
879 | if (u32Flag | RM_NEED_TO_SEND_SCAN) { | ||
880 | rm31080_ctrl_scan_start(); | ||
881 | } | ||
882 | |||
883 | if (u32Flag | RM_NEED_TO_READ_RAW_DATA) { | ||
884 | pKernelBuffer = rm31080_enqueue_start(); | ||
885 | if (pKernelBuffer) { | ||
886 | iRet = rm31080_ctrl_read_raw_data((u8 *) pKernelBuffer); | ||
887 | #ifdef ENABLE_TEST_AVERAGE | ||
888 | if (iRet) { | ||
889 | iRet = test_soft_average((s8 *) pKernelBuffer); | ||
890 | } | ||
891 | #endif | ||
892 | if (iRet) { | ||
893 | rm31080_enqueue_finish(); | ||
894 | } | ||
895 | } | ||
896 | } | ||
897 | |||
898 | if (u32Flag | RM_NEED_TO_SEND_SIGNAL) { | ||
899 | if (g_stTs.bCalcFinish) { | ||
900 | g_stTs.bCalcFinish = 0; | ||
901 | rm31080_ts_send_signal(g_stTs.ulHalPID, RM_SIGNAL_INTR); | ||
902 | } | ||
903 | } | ||
904 | g_stTs.bIsWorkQueueExecuting = 0; | ||
905 | } | ||
906 | #endif | ||
907 | |||
908 | static irqreturn_t rm31080_irq(int irq, void *handle) | ||
909 | { | ||
910 | |||
911 | //struct rm31080_ts *ts = handle; | ||
912 | if (!g_stTs.bInitFinish) { | ||
913 | return IRQ_HANDLED; | ||
914 | } | ||
915 | |||
916 | #ifdef ENABLE_WORK_QUEUE | ||
917 | queue_work(g_stTs.rm_workqueue, &g_stTs.rm_work); | ||
918 | #endif | ||
919 | |||
920 | return IRQ_HANDLED; | ||
921 | } | ||
922 | |||
923 | //============================================================================= | ||
924 | static void rm31080_init_ts_structure_part(void) | ||
925 | { | ||
926 | g_stTs.bInitFinish = 0; | ||
927 | g_stTs.bCalcFinish = 0; | ||
928 | g_stTs.bEnableScriber = 0; | ||
929 | g_stTs.bIsSuspended = 0; | ||
930 | g_stTs.bEnableAutoScan = 1; | ||
931 | |||
932 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
933 | g_stTs.u8ScanModeState = RM_SCAN_MODE_MANUAL; | ||
934 | #endif | ||
935 | } | ||
936 | |||
937 | static void rm31080_init_ts_structure(void) | ||
938 | { | ||
939 | g_stTs.ulHalPID = 0; | ||
940 | |||
941 | memset(&g_stTs, 0, sizeof(struct rm31080a_ts_para)); | ||
942 | |||
943 | #ifdef ENABLE_WORK_QUEUE | ||
944 | g_stTs.rm_workqueue = create_singlethread_workqueue("rm_work"); | ||
945 | INIT_WORK(&g_stTs.rm_work, rm_work_handler); | ||
946 | g_stTs.bIsWorkQueueExecuting = 0; | ||
947 | #endif | ||
948 | } | ||
949 | |||
950 | //============================================================================= | ||
951 | static void rm31080_start(struct rm31080_ts *ts) | ||
952 | { | ||
953 | #ifdef ENABLE_RM31080_DEEP_SLEEP | ||
954 | struct rm_spi_ts_platform_data *pdata; | ||
955 | #endif | ||
956 | |||
957 | if (!g_stTs.bIsSuspended) | ||
958 | return; | ||
959 | g_stTs.bIsSuspended = 0; | ||
960 | |||
961 | #ifdef ENABLE_RM31080_DEEP_SLEEP | ||
962 | //flow designed by Roger //20110930 | ||
963 | pdata = g_input_dev->dev.parent->platform_data; | ||
964 | gpio_set_value(pdata->gpio_reset, 0); | ||
965 | msleep(120); | ||
966 | gpio_set_value(pdata->gpio_reset, 1); | ||
967 | msleep(10); | ||
968 | rm31080_init_ts_structure_part(); | ||
969 | rm31080_ts_send_signal(g_stTs.ulHalPID, RM_SIGNAL_RESUME); | ||
970 | #elif defined(ENABLE_AUTO_SCAN) | ||
971 | rm31080_ctrl_clear_int(); | ||
972 | rm31080_ctrl_scan_start(); | ||
973 | #endif | ||
974 | |||
975 | } | ||
976 | |||
977 | static void rm31080_stop(struct rm31080_ts *ts) | ||
978 | { | ||
979 | int iCount; | ||
980 | if (g_stTs.bIsSuspended) | ||
981 | return; | ||
982 | |||
983 | iCount = 0; | ||
984 | while (g_stTs.bIsWorkQueueExecuting) { | ||
985 | //printk("Raydium TS: Work_Queue is Executing.\n"); | ||
986 | msleep(1); | ||
987 | iCount++; | ||
988 | if (iCount > 1000) | ||
989 | break; | ||
990 | } | ||
991 | g_stTs.bIsSuspended = 1; | ||
992 | |||
993 | #ifdef ENABLE_RM31080_DEEP_SLEEP | ||
994 | rm31080_ctrl_suspend(); | ||
995 | #endif | ||
996 | } | ||
997 | |||
998 | #ifdef CONFIG_PM | ||
999 | static int rm31080_suspend(struct device *dev) | ||
1000 | { | ||
1001 | struct rm31080_ts *ts = dev_get_drvdata(dev); | ||
1002 | rm31080_stop(ts); | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | static int rm31080_resume(struct device *dev) | ||
1007 | { | ||
1008 | struct rm31080_ts *ts = dev_get_drvdata(dev); | ||
1009 | rm31080_start(ts); | ||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
1014 | static void rm31080_early_suspend(struct early_suspend *es) | ||
1015 | { | ||
1016 | struct rm31080_ts *ts; | ||
1017 | struct device *dev; | ||
1018 | |||
1019 | ts = container_of(es, struct rm31080_ts, early_suspend); | ||
1020 | dev = ts->dev; | ||
1021 | |||
1022 | if (rm31080_suspend(dev) != 0) { | ||
1023 | dev_err(dev, "%s: failed\n", __func__); | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | static void rm31080_early_resume(struct early_suspend *es) | ||
1028 | { | ||
1029 | struct rm31080_ts *ts; | ||
1030 | struct device *dev; | ||
1031 | |||
1032 | ts = container_of(es, struct rm31080_ts, early_suspend); | ||
1033 | dev = ts->dev; | ||
1034 | |||
1035 | if (rm31080_resume(dev) != 0) { | ||
1036 | dev_err(dev, "%s: failed\n", __func__); | ||
1037 | } | ||
1038 | } | ||
1039 | #else | ||
1040 | static const struct dev_pm_ops rm31080_pm_ops = { | ||
1041 | .suspend = rm31080_suspend, | ||
1042 | .resume = rm31080_resume, | ||
1043 | }; | ||
1044 | #endif | ||
1045 | #endif | ||
1046 | |||
1047 | struct rm31080_ts *rm31080_input_init(struct device *dev, unsigned int irq, | ||
1048 | const struct rm31080_bus_ops *bops) | ||
1049 | { | ||
1050 | |||
1051 | struct rm31080_ts *ts; | ||
1052 | struct input_dev *input_dev; | ||
1053 | int err; | ||
1054 | |||
1055 | if (!irq) { | ||
1056 | dev_err(dev, "no IRQ?\n"); | ||
1057 | err = -EINVAL; | ||
1058 | goto err_out; | ||
1059 | } | ||
1060 | |||
1061 | ts = kzalloc(sizeof(*ts), GFP_KERNEL); | ||
1062 | |||
1063 | input_dev = input_allocate_device(); | ||
1064 | |||
1065 | if (!ts || !input_dev) { | ||
1066 | dev_err(dev, "Failed to allocate memory\n"); | ||
1067 | err = -ENOMEM; | ||
1068 | goto err_free_mem; | ||
1069 | } | ||
1070 | |||
1071 | g_input_dev = input_dev; | ||
1072 | |||
1073 | ts->bops = bops; | ||
1074 | ts->dev = dev; | ||
1075 | ts->input = input_dev; | ||
1076 | ts->irq = irq; | ||
1077 | |||
1078 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); | ||
1079 | |||
1080 | input_dev->name = "raydium_ts"; | ||
1081 | input_dev->phys = ts->phys; | ||
1082 | input_dev->dev.parent = dev; | ||
1083 | input_dev->id.bustype = bops->bustype; | ||
1084 | |||
1085 | input_dev->open = rm31080_input_open; | ||
1086 | input_dev->close = rm31080_input_close; | ||
1087 | |||
1088 | input_set_drvdata(input_dev, ts); | ||
1089 | |||
1090 | __set_bit(EV_ABS, input_dev->evbit); | ||
1091 | __set_bit(ABS_X, input_dev->absbit); | ||
1092 | __set_bit(ABS_Y, input_dev->absbit); | ||
1093 | __set_bit(ABS_PRESSURE, input_dev->absbit); | ||
1094 | |||
1095 | __set_bit(EV_KEY, input_dev->evbit); | ||
1096 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
1097 | |||
1098 | |||
1099 | input_set_abs_params(input_dev, ABS_X, | ||
1100 | 0, RM_INPUT_RESOLUTION_X - 1, 0, 0); | ||
1101 | input_set_abs_params(input_dev, ABS_Y, | ||
1102 | 0, RM_INPUT_RESOLUTION_Y - 1, 0, 0); | ||
1103 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0); | ||
1104 | |||
1105 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0); | ||
1106 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
1107 | 0, RM_INPUT_RESOLUTION_X - 1, 0, 0); | ||
1108 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
1109 | 0, RM_INPUT_RESOLUTION_Y - 1, 0, 0); | ||
1110 | input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 32, 0, 0); | ||
1111 | |||
1112 | err = request_threaded_irq(ts->irq, NULL, rm31080_irq, | ||
1113 | IRQF_TRIGGER_RISING, dev_name(dev), ts); | ||
1114 | if (err) { | ||
1115 | dev_err(dev, "irq %d busy?\n", ts->irq); | ||
1116 | goto err_free_mem; | ||
1117 | } | ||
1118 | |||
1119 | mutex_init(&ts->access_mutex); | ||
1120 | #if defined(CONFIG_HAS_EARLYSUSPEND) | ||
1121 | ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; | ||
1122 | ts->early_suspend.suspend = rm31080_early_suspend; | ||
1123 | ts->early_suspend.resume = rm31080_early_resume; | ||
1124 | register_early_suspend(&ts->early_suspend); | ||
1125 | #endif | ||
1126 | |||
1127 | __rm31080_disable(ts); | ||
1128 | |||
1129 | err = sysfs_create_group(&dev->kobj, &vtest_attr_group); | ||
1130 | if (err) | ||
1131 | goto err_free_irq; | ||
1132 | |||
1133 | err = input_register_device(input_dev); | ||
1134 | if (err) | ||
1135 | goto err_remove_attr; | ||
1136 | |||
1137 | return ts; | ||
1138 | |||
1139 | err_remove_attr: | ||
1140 | sysfs_remove_group(&dev->kobj, &vtest_attr_group); | ||
1141 | err_free_irq: | ||
1142 | free_irq(ts->irq, ts); | ||
1143 | err_free_mem: | ||
1144 | input_free_device(input_dev); | ||
1145 | kfree(ts); | ||
1146 | err_out: | ||
1147 | return ERR_PTR(err); | ||
1148 | } | ||
1149 | |||
1150 | static int dev_open(struct inode *inode, struct file *filp) | ||
1151 | { | ||
1152 | return 0; | ||
1153 | } | ||
1154 | |||
1155 | static int dev_release(struct inode *inode, struct file *filp) | ||
1156 | { | ||
1157 | g_stTs.bInitFinish = 0; | ||
1158 | rm31080_enter_manual_mode(); | ||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | static ssize_t | ||
1163 | dev_read(struct file *filp, char __user * buf, size_t count, loff_t * pos) | ||
1164 | { | ||
1165 | unsigned long missing; | ||
1166 | ssize_t status = 0; | ||
1167 | u8 *pMyBuf; | ||
1168 | |||
1169 | pMyBuf = kmalloc(count, GFP_KERNEL); | ||
1170 | if (pMyBuf == NULL) | ||
1171 | return -ENOMEM; | ||
1172 | |||
1173 | pMyBuf[0] = buf[0]; | ||
1174 | status = rm31080_spi_read(pMyBuf[0], pMyBuf, count); | ||
1175 | |||
1176 | if (status != 0) { | ||
1177 | //printk("rm31080_spi_read() fail\n"); | ||
1178 | } | ||
1179 | status = count; | ||
1180 | missing = copy_to_user(buf, pMyBuf, count); | ||
1181 | |||
1182 | if (missing == status) | ||
1183 | status = -EFAULT; | ||
1184 | else | ||
1185 | status = status - missing; | ||
1186 | |||
1187 | kfree(pMyBuf); | ||
1188 | return status; | ||
1189 | } | ||
1190 | |||
1191 | static ssize_t | ||
1192 | dev_write(struct file *filp, const char __user * buf, | ||
1193 | size_t count, loff_t * pos) | ||
1194 | { | ||
1195 | u8 *pMyBuf; | ||
1196 | unsigned long missing; | ||
1197 | ssize_t status = 0; | ||
1198 | |||
1199 | pMyBuf = kmalloc(count, GFP_KERNEL); | ||
1200 | if (pMyBuf == NULL) | ||
1201 | return -ENOMEM; | ||
1202 | |||
1203 | missing = copy_from_user(pMyBuf, buf, count); | ||
1204 | if (missing == 0) { | ||
1205 | status = rm31080_spi_write(pMyBuf, count); | ||
1206 | } else | ||
1207 | status = -EFAULT; | ||
1208 | |||
1209 | kfree(pMyBuf); | ||
1210 | return count; | ||
1211 | } | ||
1212 | |||
1213 | //============================================================================= | ||
1214 | // Description: | ||
1215 | // I/O Control routin. | ||
1216 | // Input: | ||
1217 | // file: | ||
1218 | // cmd : | ||
1219 | // arg : | ||
1220 | // Output: | ||
1221 | // 1: succeed | ||
1222 | // 0: failed | ||
1223 | //============================================================================= | ||
1224 | static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1225 | { | ||
1226 | long ret = 1; | ||
1227 | switch (cmd & 0xFFFF) { | ||
1228 | case RM_IOCTL_REPORT_POINT: | ||
1229 | raydium_report_pointer((void *)arg); | ||
1230 | break; | ||
1231 | case RM_IOCTL_SET_HAL_PID: | ||
1232 | g_stTs.ulHalPID = arg; | ||
1233 | break; | ||
1234 | case RM_IOCTL_INIT_START: | ||
1235 | g_stTs.bInitFinish = 0; | ||
1236 | rm31080_enter_manual_mode(); | ||
1237 | break; | ||
1238 | case RM_IOCTL_INIT_END: | ||
1239 | g_stTs.bInitFinish = 1; | ||
1240 | g_stTs.bCalcFinish = 1; | ||
1241 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
1242 | ret = rm31080_ctrl_scan_start(); | ||
1243 | #endif | ||
1244 | break; | ||
1245 | case RM_IOCTL_FINISH_CALC: | ||
1246 | g_stTs.bCalcFinish = 1; | ||
1247 | break; | ||
1248 | case RM_IOCTL_SCRIBER_CTRL: | ||
1249 | g_stTs.bEnableScriber = (bool) arg; | ||
1250 | break; | ||
1251 | case RM_IOCTL_AUTOSCAN_CTRL: | ||
1252 | g_stTs.bEnableAutoScan = (bool) arg; | ||
1253 | break; | ||
1254 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
1255 | case RM_IOCTL_READ_RAW_DATA: | ||
1256 | ret = | ||
1257 | rm31080_queue_read_raw_data((u8 *) arg, | ||
1258 | (cmd >> 16) & 0xFFFF); | ||
1259 | break; | ||
1260 | #endif | ||
1261 | case RM_IOCTL_SET_PARAMETER: | ||
1262 | ret = rm31080_get_config((u8 *) arg, (cmd >> 16) & 0xFFFF); | ||
1263 | break; | ||
1264 | default: | ||
1265 | break; | ||
1266 | } | ||
1267 | return ret; | ||
1268 | } | ||
1269 | |||
1270 | static struct file_operations dev_fops = { | ||
1271 | .owner = THIS_MODULE, | ||
1272 | .open = dev_open, | ||
1273 | .release = dev_release, | ||
1274 | .read = dev_read, | ||
1275 | .write = dev_write, | ||
1276 | .unlocked_ioctl = dev_ioctl, | ||
1277 | }; | ||
1278 | |||
1279 | static struct miscdevice raydium_ts_miscdev = { | ||
1280 | .minor = MISC_DYNAMIC_MINOR, | ||
1281 | .name = "raydium_ts", | ||
1282 | .fops = &dev_fops, | ||
1283 | }; | ||
1284 | |||
1285 | static const struct rm31080_bus_ops rm31080_spi_bus_ops = { | ||
1286 | .bustype = BUS_SPI, | ||
1287 | }; | ||
1288 | |||
1289 | static int __devexit rm31080_spi_remove(struct spi_device *spi) | ||
1290 | { | ||
1291 | struct rm31080_ts *ts = spi_get_drvdata(spi); | ||
1292 | |||
1293 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
1294 | rm31080_queue_free(); | ||
1295 | #endif | ||
1296 | |||
1297 | #ifdef ENABLE_WORK_QUEUE | ||
1298 | if (g_stTs.rm_workqueue) | ||
1299 | destroy_workqueue(g_stTs.rm_workqueue); | ||
1300 | #endif | ||
1301 | |||
1302 | misc_deregister(&raydium_ts_miscdev); | ||
1303 | |||
1304 | sysfs_remove_group(&ts->dev->kobj, &vtest_attr_group); | ||
1305 | free_irq(ts->irq, ts); | ||
1306 | input_unregister_device(ts->input); | ||
1307 | kfree(ts); | ||
1308 | spi_set_drvdata(spi, NULL); | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | static int __devinit rm31080_spi_probe(struct spi_device *spi) | ||
1313 | { | ||
1314 | struct rm31080_ts *ts; | ||
1315 | |||
1316 | rm31080_init_ts_structure(); | ||
1317 | rm31080_init_ts_structure_part(); | ||
1318 | |||
1319 | if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { | ||
1320 | dev_err(&spi->dev, "SPI CLK %d Hz?\n", spi->max_speed_hz); | ||
1321 | return -EINVAL; | ||
1322 | } | ||
1323 | |||
1324 | ts = rm31080_input_init(&spi->dev, spi->irq, &rm31080_spi_bus_ops); | ||
1325 | if (IS_ERR(ts)) | ||
1326 | return PTR_ERR(ts); | ||
1327 | spi_set_drvdata(spi, ts); | ||
1328 | |||
1329 | g_spi = spi; | ||
1330 | |||
1331 | if (misc_register(&raydium_ts_miscdev) != 0) { | ||
1332 | dev_err(&spi->dev, "Raydium TS: cannot register miscdev\n"); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | #ifdef ENABLE_RAW_DATA_QUEUE | ||
1336 | rm31080_queue_init(); | ||
1337 | #endif | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | static struct spi_driver rm31080_spi_driver = { | ||
1343 | .driver = { | ||
1344 | .name = "rm_ts_spidev", | ||
1345 | .bus = &spi_bus_type, | ||
1346 | .owner = THIS_MODULE, | ||
1347 | #if !defined(CONFIG_HAS_EARLYSUSPEND) | ||
1348 | .pm = &rm31080_pm_ops, | ||
1349 | #endif | ||
1350 | }, | ||
1351 | .probe = rm31080_spi_probe, | ||
1352 | .remove = __devexit_p(rm31080_spi_remove), | ||
1353 | }; | ||
1354 | |||
1355 | static int __init rm31080_spi_init(void) | ||
1356 | { | ||
1357 | return spi_register_driver(&rm31080_spi_driver); | ||
1358 | } | ||
1359 | module_init(rm31080_spi_init); | ||
1360 | |||
1361 | static void __exit rm31080_spi_exit(void) | ||
1362 | { | ||
1363 | spi_unregister_driver(&rm31080_spi_driver); | ||
1364 | } | ||
1365 | module_exit(rm31080_spi_exit); | ||
1366 | |||
1367 | MODULE_AUTHOR("Valentine Hsu <valentine.hsu@rad-ic.com>"); | ||
1368 | MODULE_DESCRIPTION("Raydium touchscreen SPI bus driver"); | ||
1369 | MODULE_LICENSE("GPL"); | ||
1370 | MODULE_ALIAS("spi:raydium-t007"); | ||