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"); | ||
