Guest User

Untitled

a guest
May 17th, 2016
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.60 KB | None | 0 0
  1. /*
  2. * MELFAS mcs8000 touchscreen driver
  3. *
  4. * Copyright (C) 2011 LGE, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. */
  21.  
  22. #include <linux/timer.h>
  23. #include <linux/module.h>
  24. #include <linux/delay.h>
  25. #include <linux/workqueue.h>
  26.  
  27. #include <linux/i2c.h>
  28. #include <linux/gpio.h>
  29. #include <linux/input.h>
  30. #include <linux/interrupt.h>
  31. #include <linux/io.h>
  32. #include <asm/uaccess.h>
  33. #include <linux/miscdevice.h>
  34.  
  35. /* To enable FW Upgrade */
  36. #include "mcs8000_download.h"
  37.  
  38. #include <linux/i2c-gpio.h>
  39. #include CONFIG_LGE_BOARD_HEADER_FILE
  40.  
  41.  
  42. #ifdef CONFIG_HAS_EARLYSUSPEND
  43. #include <linux/earlysuspend.h>
  44. static struct early_suspend ts_early_suspend;
  45. static void mcs8000_early_suspend(struct early_suspend *h);
  46. static void mcs8000_late_resume(struct early_suspend *h);
  47. #endif
  48.  
  49.  
  50. //static int mcs8000_ts_off(void);
  51. int mcs8000_ts_on(void);
  52. static void mcs8000_Data_Clear(void);
  53. static void ResetTS(void);
  54. static void Release_All_Fingers(void);
  55.  
  56. #define TS_POLLING_TIME 0 /* msec */
  57.  
  58.  
  59. #define DEBUG_TS 0 /* enable or disable debug message */
  60.  
  61. #if DEBUG_TS
  62. #define DMSG(fmt, args...) printk(KERN_DEBUG fmt, ##args)
  63. #else
  64. #define DMSG(fmt, args...) do {} while (0)
  65. #endif
  66.  
  67. #define ON 1
  68. #define OFF 0
  69. #define PRESSED 1
  70. #define RELEASED 0
  71.  
  72. /* melfas data */
  73. #define TS_MAX_Z_TOUCH 255
  74. #define TS_MAX_W_TOUCH 30
  75. #define MTSI_VERSION 0x07 /* 0x05 */
  76. #define TS_MAX_X_COORD 320
  77. #define TS_MAX_Y_COORD 480
  78. #define FW_VERSION 0x00
  79.  
  80. #define TS_READ_START_ADDR 0x0F
  81. #define TS_READ_START_ADDR2 0x10
  82.  
  83. #if 1 // woden@lge.com [2013-02-26] => New TS Firmware was applied.
  84. #define TS_LATEST_FW_VERSION_EU_SUN 0x16
  85. #define TS_LATEST_FW_VERSION_EU_INO 0x20
  86. #else
  87. #define TS_LATEST_FW_VERSION_EU_SUN 0x15
  88. #define TS_LATEST_FW_VERSION_EU_INO 0x18
  89. #endif
  90.  
  91. #define TS_READ_REGS_LEN 66
  92. #define MELFAS_MAX_TOUCH 11
  93.  
  94. #define I2C_RETRY_CNT 10
  95. #define PRESS_KEY 1
  96. #define RELEASE_KEY 0
  97. #define DEBUG_PRINT 1
  98.  
  99.  
  100.  
  101. #define SET_DOWNLOAD_BY_GPIO 1
  102. #define GPIO_TOUCH_ID 121
  103.  
  104. #if defined(CONFIG_MACH_MSM7X25A_V1)
  105. #define KEY_SIM_SWITCH 223
  106. #endif
  107.  
  108. #define LOGTAG "[melfas_ts]: "
  109.  
  110. int power_flag=0;
  111. static int irq_flag;
  112.  
  113. enum {
  114. None = 0,
  115. TOUCH_SCREEN,
  116. TOUCH_KEY
  117. };
  118.  
  119. struct muti_touch_info {
  120. int strength;
  121. int width;
  122. int posX;
  123. int posY;
  124. };
  125.  
  126.  
  127. struct mcs8000_ts_device {
  128. struct i2c_client *client;
  129. struct input_dev *input_dev;
  130. struct delayed_work work;
  131. //struct work_struct work;
  132. int num_irq;
  133. int intr_gpio;
  134. int scl_gpio;
  135. int sda_gpio;
  136. bool pendown;
  137. int (*power)(unsigned char onoff);
  138. struct workqueue_struct *ts_wq;
  139.  
  140. /*20110607 seven.kim@lge.com for touch frimware download [START] */
  141. //struct wake_lock wakelock;
  142. int irq_sync;
  143. int fw_version;
  144. int hw_version;
  145. int status;
  146. int tsp_type;
  147. /*20110607 seven.kim@lge.com for touch frimware download [END] */
  148. };
  149.  
  150. static struct input_dev *mcs8000_ts_input = NULL;
  151.  
  152. struct mcs8000_ts_device mcs8000_ts_dev;
  153.  
  154. int Is_Release_Error[MELFAS_MAX_TOUCH]={0}; /* for touch stable */
  155.  
  156. static unsigned char ucSensedInfo = 0;
  157.  
  158. #define READ_NUM 8 /* now, just using two finger data */
  159.  
  160. static unsigned char g_touchLogEnable = 1;
  161.  
  162. unsigned char ex_fw_ver;
  163. unsigned char ex_hw_ver;
  164. unsigned char ex_touch_id;
  165.  
  166. void mcs8000_firmware_info(unsigned char* fw_ver, unsigned char* hw_ver, unsigned char *comp_ver);
  167.  
  168. //static int misc_opened = 0;
  169. //static unsigned int mcs8000_debug_mask = MCS8000_DM_TRACE_NO;
  170.  
  171. //static struct mcs8000_ts_device *mcs8000_ext_ts = (void *)NULL;
  172.  
  173.  
  174. void Send_Touch(unsigned int x, unsigned int y)
  175. {
  176. input_report_abs(mcs8000_ts_dev.input_dev, ABS_MT_TOUCH_MAJOR, 1);
  177. input_report_abs(mcs8000_ts_dev.input_dev, ABS_MT_POSITION_X, x);
  178. input_report_abs(mcs8000_ts_dev.input_dev, ABS_MT_POSITION_Y, y);
  179. input_mt_sync(mcs8000_ts_dev.input_dev);
  180. input_sync(mcs8000_ts_dev.input_dev);
  181. input_report_abs(mcs8000_ts_dev.input_dev, ABS_MT_TOUCH_MAJOR, 0);
  182. input_report_abs(mcs8000_ts_dev.input_dev, ABS_MT_POSITION_X, x);
  183. input_report_abs(mcs8000_ts_dev.input_dev, ABS_MT_POSITION_Y, y);
  184. input_mt_sync(mcs8000_ts_dev.input_dev);
  185. input_sync(mcs8000_ts_dev.input_dev);
  186. }
  187. EXPORT_SYMBOL(Send_Touch);
  188.  
  189. /* #define to_delayed_work(_work) container_of(_work, struct delayed_work, work ) */
  190.  
  191.  
  192. static struct muti_touch_info g_Mtouch_info[MELFAS_MAX_TOUCH];
  193. /*
  194. static int melfas_init_panel(struct mcs8000_ts_device *ts)
  195. {
  196. int ret ;
  197. int buf = 0;
  198. ret = i2c_master_send(ts->client, &buf, 1);
  199.  
  200. ret = i2c_master_send(ts->client, &buf, 1);
  201.  
  202. if (ret <0)
  203. {
  204. printk(KERN_ERR "melfas_ts_probe: i2c_master_send() failed\n [%d]", ret);
  205. return 0;
  206. }
  207.  
  208.  
  209. return true;
  210. }
  211. */
  212.  
  213. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-12-07]
  214. : For an abnormal condition after getting ESD */
  215. static void ResetTS(void)
  216. {
  217. pr_info(LOGTAG"%s+\n", __func__);
  218.  
  219. struct mcs8000_ts_device *dev;
  220. dev = &mcs8000_ts_dev;
  221.  
  222. mcs8000_Data_Clear();
  223.  
  224. //disable_irq(dev->num_irq);
  225.  
  226.  
  227. /* add Touch power flag eungjin.kim@lge.com [2012-02-06]*/
  228. if(power_flag==1){
  229. power_flag--;
  230. dev->power(OFF);
  231. }
  232. /* add Touch power flag eungjin.kim@lge.com [2012-02-06]*/
  233.  
  234.  
  235.  
  236. mdelay(20);
  237.  
  238. mcs8000_ts_on();
  239.  
  240. printk(KERN_DEBUG "Reset TS For ESD\n");
  241.  
  242. //enable_irq(dev->num_irq);
  243. pr_info(LOGTAG"%s-\n", __func__);
  244. }
  245. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-12-07]
  246. : For an abnormal condition after getting ESD */
  247.  
  248.  
  249. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-12-07]
  250. : For an abnormal condition after getting ESD */
  251. int CheckTSForESD(unsigned char ucData)
  252. {
  253. pr_info(LOGTAG"%s+\n", __func__);
  254. unsigned char ucStatus;
  255. ucStatus = ucData&0x0f;
  256.  
  257. if (ucStatus == 0x0f) //Abnormal condition
  258. {
  259. ResetTS();
  260. pr_info(LOGTAG"%s returning true\n", __func__);
  261. pr_info(LOGTAG"%s-\n", __func__);
  262. return TRUE;
  263. } else {
  264. pr_info(LOGTAG"%s returning false\n", __func__);
  265. pr_info(LOGTAG"%s-\n", __func__);
  266. return FALSE;
  267. }
  268. }
  269. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-12-07]
  270. : For an abnormal condition after getting ESD */
  271.  
  272. static void Release_All_Fingers(void)
  273. {
  274. struct mcs8000_ts_device *dev;
  275.  
  276. int i=0;
  277. dev = &mcs8000_ts_dev;
  278.  
  279. pr_info(LOGTAG"%s+\n", __func__);
  280. for(i=0; i<MELFAS_MAX_TOUCH; i++) {
  281. if(-1 == g_Mtouch_info[i].strength) {
  282. g_Mtouch_info[i].posX = 0;
  283. g_Mtouch_info[i].posY = 0;
  284. continue;
  285. }
  286.  
  287. g_Mtouch_info[i].strength = 0;
  288.  
  289. input_report_abs(dev->input_dev, ABS_MT_TRACKING_ID, i);
  290. input_report_abs(dev->input_dev, ABS_MT_POSITION_X, g_Mtouch_info[i].posX);
  291. input_report_abs(dev->input_dev, ABS_MT_POSITION_Y, g_Mtouch_info[i].posY);
  292. input_report_abs(dev->input_dev, ABS_MT_TOUCH_MAJOR, g_Mtouch_info[i].strength );
  293. input_report_abs(dev->input_dev, ABS_MT_WIDTH_MAJOR, g_Mtouch_info[i].width);
  294. input_mt_sync(dev->input_dev);
  295.  
  296. g_Mtouch_info[i].posX = 0;
  297. g_Mtouch_info[i].posY = 0;
  298.  
  299. if(0 == g_Mtouch_info[i].strength)
  300. g_Mtouch_info[i].strength = -1;
  301. }
  302. input_sync(dev->input_dev);
  303. pr_info(LOGTAG"%s-\n", __func__);
  304. }
  305.  
  306.  
  307. static void mcs8000_work(struct work_struct *work)
  308. {
  309. int read_num, FingerID;
  310. int touchType = 0, touchState = 0;
  311. struct mcs8000_ts_device *ts = container_of(to_delayed_work(work), struct mcs8000_ts_device, work);
  312. int ret = 0;
  313. int i = 0, j = 0;
  314. uint8_t buf[TS_READ_REGS_LEN];
  315. int keyID = 0;
  316. int iTouchedCnt;
  317.  
  318. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-23]
  319. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  320. int Is_Touch_Valid = 0;
  321. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-23]
  322. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  323.  
  324. #if DEBUG_PRINT
  325. printk(KERN_ERR "melfas_ts_work_func\n");
  326.  
  327. if (ts == NULL)
  328. printk(KERN_ERR "melfas_ts_work_func : TS NULL\n");
  329. #endif
  330.  
  331. pr_info(LOGTAG"%s+\n", __func__);
  332.  
  333. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-09] :
  334. TD1416085584 : After sleep on and off while sensing a touchscreen,
  335. Touchscreen doesn't work*/
  336.  
  337.  
  338. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-09]*/
  339.  
  340.  
  341. buf[0] = TS_READ_START_ADDR;
  342.  
  343. ret = i2c_master_send(ts->client, buf, 1);
  344. if(ret < 0)
  345. {
  346. #if DEBUG_PRINT
  347. printk(KERN_ERR "i2c_master_send: i2c failed\n");
  348. if (irq_flag == 0) {
  349. irq_flag++;
  350. enable_irq(ts->client->irq);
  351. }
  352.  
  353. return ;
  354. #endif
  355. }
  356. ret = i2c_master_recv(ts->client, buf, 1);
  357. if(ret < 0)
  358. {
  359. #if DEBUG_PRINT
  360. printk(KERN_ERR "i2c_master_recv: i2c failed\n");
  361. if (irq_flag == 0) {
  362. irq_flag++;
  363. enable_irq(ts->client->irq);
  364. }
  365.  
  366. return ;
  367. #endif
  368. }
  369.  
  370. read_num = buf[0];
  371.  
  372. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-10-17] :
  373. TD1416085584 : After sleeping on and off while sensing a touchscreen,
  374. Touchscreen doesn't work*/
  375.  
  376. iTouchedCnt = 6*5;
  377.  
  378. if(read_num > iTouchedCnt)
  379. {
  380. if (irq_flag == 0) {
  381. irq_flag++;
  382. enable_irq(ts->client->irq);
  383. }
  384. return ;
  385. }
  386. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-09]*/
  387.  
  388. if(read_num>0)
  389. {
  390. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-23]
  391. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  392. Is_Touch_Valid = 1;
  393. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-23]
  394. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  395.  
  396. buf[0] = TS_READ_START_ADDR2;
  397.  
  398. ret = i2c_master_send(ts->client, buf, 1);
  399. if(ret < 0)
  400. {
  401. #if DEBUG_PRINT
  402. printk(KERN_ERR "melfas_ts_work_func: i2c failed\n");
  403. if (irq_flag == 0) {
  404. irq_flag++;
  405.  
  406. enable_irq(ts->client->irq);
  407. }
  408. return ;
  409. #endif
  410. }
  411. ret = i2c_master_recv(ts->client, buf, read_num);
  412. if(ret < 0)
  413. {
  414. #if DEBUG_PRINT
  415. printk(KERN_ERR "melfas_ts_work_func: i2c failed\n");
  416. if (irq_flag == 0) {
  417. irq_flag++;
  418. enable_irq(ts->client->irq);
  419. }
  420. return ;
  421. #endif
  422. }
  423.  
  424. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-28]
  425. : For an abnormal condition after getting ESD */
  426. ucSensedInfo = buf[0];
  427. if (CheckTSForESD(ucSensedInfo))
  428. {
  429. if (irq_flag == 0) {
  430. irq_flag++;
  431. enable_irq(ts->client->irq);
  432. }
  433.  
  434. return;
  435. }
  436. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-28]
  437. : For an abnormal condition after getting ESD */
  438.  
  439. for(i = 0; i < read_num; i = i + 6)
  440. {
  441. touchType = (buf[i] >> 5) & 0x03;
  442. #if DEBUG_PRINT
  443. printk(KERN_INFO "TouchType : [%d]\n", touchType);
  444. #endif
  445.  
  446. /* Touch Type is Screen */
  447. if (touchType == TOUCH_SCREEN)
  448. {
  449. FingerID = (buf[i] & 0x0F) -1;
  450. touchState = (buf[i] & 0x80);
  451.  
  452. if((FingerID >=0) && (FingerID < MELFAS_MAX_TOUCH)) {
  453. g_Mtouch_info[FingerID].posX= (uint16_t)(buf[i + 1] & 0x0F) << 8 | buf[i + 2];
  454. g_Mtouch_info[FingerID].posY= (uint16_t)(buf[i + 1] & 0xF0) << 4 | buf[i + 3];
  455. g_Mtouch_info[FingerID].width = buf[i + 4];
  456.  
  457. if (touchState)
  458. g_Mtouch_info[FingerID].strength = buf[i + 5];
  459. else
  460. g_Mtouch_info[FingerID].strength = 0;
  461. }
  462. }
  463. /* Touch type is key */
  464. else if (touchType == TOUCH_KEY)
  465. {
  466.  
  467. keyID = (buf[i] & 0x0F);
  468. touchState = (buf[i] & 0x80);
  469.  
  470. if (g_touchLogEnable)
  471. printk(KERN_INFO "keyID: [%d]\n", keyID);
  472.  
  473. switch(keyID) {
  474. case 0x1:
  475. input_report_key(ts->input_dev, KEY_BACK, touchState ? PRESS_KEY : RELEASE_KEY);
  476. break;
  477. case 0x2:
  478. input_report_key(ts->input_dev, KEY_MENU, touchState ? PRESS_KEY : RELEASE_KEY);
  479. break;
  480. case 0x3:
  481. input_report_key(ts->input_dev, KEY_MENU, touchState ? PRESS_KEY : RELEASE_KEY);
  482. break;
  483. #if defined(CONFIG_MACH_MSM7X25A_V1)
  484. case 0x4:
  485. input_report_key(ts->input_dev, KEY_SIM_SWITCH, touchState ? PRESS_KEY : RELEASE_KEY);
  486. break;
  487. #endif
  488. default:
  489. break;
  490. }
  491. }
  492. }
  493.  
  494. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-12-19] :
  495. For the MIP Protocal*/
  496.  
  497. /* 2012-11-27 JongWook-Park(blood9874@lge.com) mms-128s touch work function patch [START] */
  498. if (touchType == TOUCH_SCREEN){
  499. for(j = 0; j < MELFAS_MAX_TOUCH; j++)
  500. {
  501. if(g_Mtouch_info[j].strength== -1)
  502. continue;
  503.  
  504. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-09] :
  505. TD1416085584 : After sleeping on and off while sensing a touchscreen,
  506. Touchscreen doesn't work*/
  507. if(Is_Release_Error[j]==1) {
  508. input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, j);
  509. input_report_abs(ts->input_dev, ABS_MT_POSITION_X, g_Mtouch_info[j].posX);
  510. input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, g_Mtouch_info[j].posY);
  511. input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0/*g_Mtouch_info[j].strength*/ );
  512. input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, g_Mtouch_info[j].width);
  513. input_report_abs(ts->input_dev, ABS_MT_PRESSURE, g_Mtouch_info[j].strength);
  514. input_mt_sync(ts->input_dev);
  515. //input_sync(ts->input_dev);/* LGE_CHANGE_S : wonsang.yoon@lge.com [2011-12-17] blocking*/
  516. Is_Release_Error[j]=0;
  517. }
  518. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-09]*/
  519.  
  520. if (g_Mtouch_info[j].strength > 0) { // Press
  521. input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, j);
  522. input_report_abs(ts->input_dev, ABS_MT_POSITION_X, g_Mtouch_info[j].posX);
  523. input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, g_Mtouch_info[j].posY);
  524. input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, g_Mtouch_info[j].strength);
  525. input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, g_Mtouch_info[j].width);
  526. input_report_abs(ts->input_dev, ABS_MT_PRESSURE, g_Mtouch_info[j].strength);
  527. input_mt_sync(ts->input_dev);
  528. } else { // Release
  529. input_mt_sync(ts->input_dev);
  530. }
  531. if(g_touchLogEnable)
  532. {
  533. printk(KERN_ERR "melfas_ts_work_func: Touch ID: %d, State : %d, x: %d, y: %d, z: %d w: %d\n",
  534. j, (g_Mtouch_info[j].strength>0), g_Mtouch_info[j].posX, g_Mtouch_info[j].posY, g_Mtouch_info[j].strength, g_Mtouch_info[j].width);
  535. }
  536. if(g_Mtouch_info[j].strength == 0){
  537. g_Mtouch_info[j].strength = -1;
  538. }
  539. }
  540.  
  541. }
  542. /* 2012-11-27 JongWook-Park(blood9874@lge.com) mms-128s touch work function patch [END] */
  543.  
  544. input_sync(ts->input_dev);
  545.  
  546. }
  547. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-23]
  548. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  549. if(Is_Touch_Valid){
  550. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-12-20]
  551. : msleep function takes more than setting up delay time*/
  552. //msleep(1);
  553. usleep_range(1000,1000);
  554. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-12-20]
  555. : msleep function takes more than setting up delay time*/
  556. }
  557. else{
  558. #if DEBUG_PRINT
  559. printk("mcs8000_work : Invalid data INT happen !!! Added more delay !!!");
  560. #endif
  561. msleep(20);
  562. }
  563. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-23]
  564. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  565. if (irq_flag == 0) {
  566. irq_flag++;
  567. enable_irq(ts->client->irq);
  568. }
  569. pr_info(LOGTAG"%s+\n", __func__);
  570. }
  571.  
  572. static void mcs8000_Data_Clear(void) /* for touch stable */
  573. {
  574. int i;
  575.  
  576. pr_info(LOGTAG"%s+\n", __func__);
  577. for(i=0; i<MELFAS_MAX_TOUCH; i++)
  578. {
  579. if(g_Mtouch_info[i].strength != -1)
  580. {
  581. Is_Release_Error[i]=1;
  582. g_Mtouch_info[i].strength = -1;
  583. }
  584.  
  585. }
  586. pr_info(LOGTAG"%s-\n", __func__);
  587. }
  588.  
  589.  
  590. static irqreturn_t mcs8000_ts_irq_handler(int irq, void *handle)
  591. {
  592. struct mcs8000_ts_device *dev = (struct mcs8000_ts_device *)handle;
  593.  
  594. pr_info(LOGTAG"%s+\n", __func__);
  595.  
  596. #if DEBUG_PRINT
  597. printk(KERN_ERR "melfas_ts_work_func is sending irq");
  598. #endif
  599. if (irq_flag == 1) {
  600. irq_flag--;
  601. disable_irq_nosync(dev->num_irq);
  602. }
  603. /* schedule_delayed_work(&dev->work, 0); */
  604. //schedule_work(&dev->work);
  605. queue_delayed_work(dev->ts_wq, &dev->work,msecs_to_jiffies(TS_POLLING_TIME));
  606.  
  607. pr_info(LOGTAG"%s-\n", __func__);
  608. return IRQ_HANDLED;
  609. }
  610.  
  611. #if 0
  612. static int mcs8000_ts_off(void)
  613. {
  614. struct mcs8000_ts_device *dev = NULL;
  615. int ret = 0;
  616.  
  617. dev = &mcs8000_ts_dev;
  618.  
  619. /* add Touch power flag eungjin.kim@lge.com [2012-02-06]*/
  620. if(power_flag==1){
  621. power_flag--;
  622. ret = dev->power(OFF);
  623. }
  624. /* add Touch power flag eungjin.kim@lge.com [2012-02-06]*/
  625.  
  626. if (ret < 0) {
  627. printk(KERN_ERR "mcs8000_ts_on power on failed\n");
  628. goto err_power_failed;
  629. }
  630. msleep(10);
  631.  
  632. err_power_failed:
  633. return ret;
  634. }
  635. #endif
  636. /* LGE_CHANGE_S: E1 eungjin.kim@lge.com [2012-02-16]
  637. : For Touch screen non response after wakeup*/
  638. int mcs8000_ts_on(void)
  639. /* LGE_CHANGE_S: E1 eungjin.kim@lge.com [2012-02-16]
  640. : For Touch screen non response after wakeup*/
  641. {
  642. struct mcs8000_ts_device *dev = NULL;
  643. int ret = 0;
  644.  
  645. dev = &mcs8000_ts_dev;
  646.  
  647. pr_info(LOGTAG"%s+\n", __func__);
  648.  
  649. /* add Touch power flag eungjin.kim@lge.com [2012-02-06]*/
  650. if(power_flag==0){
  651. pr_info(LOGTAG"%s: power flag off\n", __func__);
  652. power_flag++;
  653. ret = dev->power(ON);
  654. }
  655. /* add Touch power flag eungjin.kim@lge.com [2012-02-06]*/
  656.  
  657. if (ret < 0) {
  658. printk(KERN_ERR "mcs8000_ts_on power on failed\n");
  659. goto err_power_failed;
  660. }
  661.  
  662. /* LGE_CHANGE_S: E0 kevinzone.han@lge.com [2011-11-23]
  663. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  664. msleep(30);
  665. /* LGE_CHANGE_E: E0 kevinzone.han@lge.com [2011-11-23]
  666.  
  667. : For an abnormal condition of touchscreen after the phone sleeps on and off*/
  668. pr_info(LOGTAG"%s-\n", __func__);
  669. err_power_failed:
  670. return ret;
  671. }
  672.  
  673. /* LGE_CHANGE_S: E1 eungjin.kim@lge.com [2012-02-16]
  674. : For Touch screen non response after wakeup*/
  675. EXPORT_SYMBOL(mcs8000_ts_on);
  676. /* LGE_CHANGE_E: E0 eungjin.kim@lge.com [2012-02-16]
  677. : For For Touch screen non response after wakeup*/
  678.  
  679. void mcs8000_firmware_info(unsigned char *fw_ver, unsigned char *hw_ver,unsigned char *touch_id)
  680. {
  681. unsigned char data;
  682. struct mcs8000_ts_device *dev = NULL;
  683. dev = &mcs8000_ts_dev;
  684.  
  685. i2c_smbus_write_byte(dev->client, 0xf1);
  686. data = i2c_smbus_read_byte(dev->client);
  687. msleep(10);
  688. printk(KERN_INFO "HARDWARE REVISION [0x%x]\n", data);
  689. *hw_ver = data;
  690. ex_hw_ver = *hw_ver;
  691.  
  692. i2c_smbus_write_byte(dev->client, 0xf5);
  693. data = i2c_smbus_read_byte(dev->client);
  694. msleep(10);
  695. printk(KERN_INFO "FIRMWARE_VERSION [0x%x]\n", data);
  696. *fw_ver = data;
  697.  
  698. ex_fw_ver=*fw_ver;
  699.  
  700. data = gpio_get_value(GPIO_TOUCH_ID);
  701. printk(KERN_INFO "TOUCH_ID [0x%x]\n", data);
  702. *touch_id = data;
  703. ex_touch_id = *touch_id;
  704. }
  705. /*
  706. static struct miscdevice mcs8000_ts_misc_dev = {
  707. .minor = MISC_DYNAMIC_MINOR,
  708. .name = "mcs8000-touch",
  709. .fops = &mcs8000_ts_ioctl_fops,
  710. };
  711. */
  712.  
  713. static ssize_t read_touch_version(struct device *dev, struct device_attribute *attr, char *buf)
  714. {
  715. unsigned char temp_fw_ver, temp_hw_ver, temp_touch_id;
  716.  
  717. mcs8000_firmware_info(&temp_fw_ver, &temp_hw_ver, &temp_touch_id);
  718. return sprintf(buf, "M4 Touch ID:%02x,HW:%02x,FW:%02x\n",ex_touch_id,ex_hw_ver,ex_fw_ver);
  719. }
  720.  
  721.  
  722. /* static DEVICE_ATTR(touch_control, S_IRUGO|S_IWUSR,NULL,write_touch_control); */
  723. /* static DEVICE_ATTR(touch_status, S_IRUGO,read_touch_status, NULL); */
  724. static DEVICE_ATTR(version, S_IRUGO /*| S_IWUSR*/, read_touch_version, NULL);
  725. /* static DEVICE_ATTR(dl_status, S_IRUGO,read_touch_dl_status, NULL); */
  726.  
  727. int mcs8000_create_file(struct input_dev *pdev)
  728. {
  729. int ret;
  730.  
  731. ret = device_create_file(&pdev->dev, &dev_attr_version);
  732. if (ret) {
  733. printk(KERN_DEBUG "LG_FW : dev_attr_version create fail\n");
  734. device_remove_file(&pdev->dev, &dev_attr_version);
  735. return ret;
  736. }
  737. /*
  738. ret = device_create_file(&pdev->dev, &dev_attr_dl_status);
  739. if (ret) {
  740. printk( KERN_DEBUG "LG_FW : dev_attr_dl_status create fail\n");
  741. device_remove_file(&pdev->dev, &dev_attr_dl_status);
  742. return ret;
  743. }
  744.  
  745. ret = device_create_file(&pdev->dev, &dev_attr_touch_status);
  746. if (ret) {
  747. printk( KERN_DEBUG "LG_FW : dev_attr_touch_status create fail\n");
  748. device_remove_file(&pdev->dev, &dev_attr_touch_status);
  749. return ret;
  750. }
  751.  
  752. ret = device_create_file(&pdev->dev, &dev_attr_touch_control);
  753. if (ret) {
  754. printk( KERN_DEBUG "LG_FW : dev_attr_touch_control create fail\n");
  755. device_remove_file(&pdev->dev, &dev_attr_touch_control);
  756. return ret;
  757. }
  758. */
  759. return ret;
  760. }
  761.  
  762. int mcs8000_remove_file(struct input_dev *pdev)
  763. {
  764. device_remove_file(&pdev->dev, &dev_attr_version);
  765. /*
  766. * device_remove_file(&pdev->dev, &dev_attr_dl_status);
  767. * device_remove_file(&pdev->dev, &dev_attr_touch_status);
  768. * device_remove_file(&pdev->dev, &dev_attr_touch_control);
  769. */
  770. return 0;
  771. }
  772.  
  773. static int mcs8000_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
  774. {
  775. int err = 0;
  776. /* int try_cnt = 0; */ /* For Touch FW Upgrade */
  777. /* unsigned char data; */ /* For Touch FW Upgrade */
  778. struct touch_platform_data *ts_pdata;
  779. struct mcs8000_ts_device *dev;
  780. unsigned char fw_ver, hw_ver;
  781. int fw_ret=0,vendor=0;
  782.  
  783. /* unsigned char tmp_val, tmp_reg ; */
  784. unsigned char touch_id;
  785. irq_flag = 1;
  786. DMSG("%s: start...\n", __FUNCTION__);
  787.  
  788. pr_info(LOGTAG"%s+\n", __func__);
  789.  
  790. ts_pdata = client->dev.platform_data;
  791.  
  792. input_set_abs_params(mcs8000_ts_input, ABS_MT_POSITION_X, 0, TS_MAX_X_COORD, 0, 0);
  793. input_set_abs_params(mcs8000_ts_input, ABS_MT_POSITION_Y, 0, TS_MAX_Y_COORD, 0, 0);
  794. input_set_abs_params(mcs8000_ts_input, ABS_MT_TOUCH_MAJOR, 0, TS_MAX_Z_TOUCH, 0, 0);
  795. input_set_abs_params(mcs8000_ts_input, ABS_MT_TRACKING_ID, 0, MELFAS_MAX_TOUCH-1, 0, 0);
  796. input_set_abs_params(mcs8000_ts_input, ABS_MT_PRESSURE, 0, 255, 0, 0);
  797.  
  798. #if DEBUG_PRINT
  799. printk(KERN_INFO "ABS_MT_POSITION_X123 : ABS_MT_POSITION_Y = [%d] : [%d] \n", ts_pdata->ts_x_max, ts_pdata->ts_y_max);
  800. #endif
  801.  
  802. dev = &mcs8000_ts_dev;
  803.  
  804. INIT_DELAYED_WORK(&dev->work, mcs8000_work);
  805. //INIT_WORK(&dev->work, mcs8000_work);
  806.  
  807. dev->power = ts_pdata->power;
  808. dev->num_irq = client->irq;
  809. dev->intr_gpio = (client->irq) - NR_MSM_IRQS ;
  810. dev->sda_gpio = ts_pdata->sda;
  811. dev->scl_gpio = ts_pdata->scl;
  812.  
  813.  
  814. dev->input_dev = mcs8000_ts_input;
  815. DMSG("mcs8000 dev->num_irq is %d , dev->intr_gpio is %d\n", dev->num_irq, dev->intr_gpio);
  816.  
  817. dev->client = client;
  818. i2c_set_clientdata(client, dev);
  819.  
  820. if (!(err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C))) {
  821. printk(KERN_ERR "%s: fucntionality check failed\n", __FUNCTION__);
  822. return err;
  823. }
  824.  
  825. err = gpio_request(dev->intr_gpio, "touch_mcs8000");
  826. if (err < 0) {
  827. printk(KERN_ERR "%s: gpio input direction fail\n", __FUNCTION__);
  828. return err;
  829. }
  830.  
  831. err = gpio_direction_input(dev->intr_gpio);
  832. if (err < 0) {
  833. printk(KERN_ERR "%s: gpio input direction fail\n", __FUNCTION__);
  834. return err;
  835. }
  836.  
  837. /* TODO: You have try to change this driver's architecture using request_threaded_irq()
  838. * So, I will change this to request_threaded_irq()
  839. */
  840. err = request_threaded_irq(dev->num_irq, NULL, mcs8000_ts_irq_handler,
  841. IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mcs8000_ts", dev);
  842.  
  843. if (err < 0) {
  844. printk(KERN_ERR "%s: request_irq failed\n", __FUNCTION__);
  845. return err;
  846. }
  847. if (irq_flag == 1) {
  848. irq_flag--;
  849. disable_irq(dev->num_irq);
  850. }
  851.  
  852. // mcs8000_ts_off();
  853. // mdelay(10);
  854. mcs8000_ts_on();
  855. mdelay(30);
  856. mcs8000_firmware_info(&fw_ver, &hw_ver,&touch_id);
  857. mdelay(10);
  858.  
  859.  
  860. //mcs8000_ext_ts = dev;
  861.  
  862.  
  863. mcs8000_create_file(mcs8000_ts_input);
  864.  
  865. #if SET_DOWNLOAD_BY_GPIO
  866. /* buf[0] = TS_READ_VERSION_ADDR;
  867. ret = i2c_master_send(dev->client, buf, 1);
  868. if(ret < 0){
  869. printk(KERN_ERR "melfas_ts_work_func : i2c_master_send [%d]\n", ret);
  870. }
  871.  
  872. ret = i2c_master_recv(dev->client, buf, 4);
  873. if(ret < 0){
  874. printk(KERN_ERR "melfas_ts_work_func : i2c_master_recv [%d]\n", ret);
  875. }
  876.  
  877. */
  878. if(touch_id == 0){ //suntel
  879. if(hw_ver==0x01){
  880. fw_ret = mcsdl_download_binary_data(1, 1,hw_ver,1);
  881. vendor=2;
  882. }
  883. if ( fw_ver !=TS_LATEST_FW_VERSION_EU_SUN ) {
  884. fw_ret = mcsdl_download_binary_data(1, 1,hw_ver,1);
  885. vendor=2;
  886. }
  887. }else{ //for rev C,D,1.1 Innotek
  888. if(hw_ver==0x00){
  889. fw_ret = mcsdl_download_binary_data(1, 1,hw_ver,2);
  890. vendor=3;
  891. }
  892. if ( fw_ver !=TS_LATEST_FW_VERSION_EU_INO ){
  893. fw_ret = mcsdl_download_binary_data(1, 1,hw_ver,2);
  894. vendor=3;
  895. }
  896. }
  897. #endif // SET_DOWNLOAD_BY_GPIO
  898.  
  899. if (irq_flag == 0) {
  900. irq_flag++;
  901. enable_irq(dev->num_irq);
  902. }
  903. mcs8000_firmware_info(&fw_ver, &hw_ver,&touch_id);
  904. if(fw_ret!=0){
  905. mms100_ISC_download_binary_data(0,0,vendor);
  906. }
  907.  
  908.  
  909. #ifdef CONFIG_HAS_EARLYSUSPEND
  910. ts_early_suspend.suspend = mcs8000_early_suspend;
  911. ts_early_suspend.resume = mcs8000_late_resume;
  912. ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1 ;
  913. register_early_suspend(&ts_early_suspend);
  914. #endif
  915.  
  916. pr_info(LOGTAG"%s-\n", __func__);
  917.  
  918. return 0;
  919. }
  920.  
  921. static int mcs8000_ts_remove(struct i2c_client *client)
  922. {
  923. struct mcs8000_ts_device *dev = i2c_get_clientdata(client);
  924.  
  925. free_irq(dev->num_irq, dev);
  926. i2c_set_clientdata(client, NULL);
  927.  
  928. return 0;
  929. }
  930.  
  931. #ifndef CONFIG_HAS_EARLYSUSPEND
  932. static int mcs8000_ts_suspend(struct i2c_client *client, pm_message_t mesg)
  933. {
  934. struct mcs8000_ts_device *dev = i2c_get_clientdata(client);
  935.  
  936. pr_info(LOGTAG"%s+\n", __func__);
  937. DMSG(KERN_INFO"%s: start! \n", __FUNCTION__);
  938. if (irq_flag == 1) {
  939. pr_info(LOGTAG"%s: irq flag 1\n", __func__);
  940. irq_flag--;
  941. disable_irq(dev->num_irq);
  942. }
  943.  
  944. DMSG("%s: irq disable\n", __FUNCTION__);
  945.  
  946. if(power_flag==1){
  947. pr_info(LOGTAG"%s: power flag 1\n", __func__);
  948. power_flag--;
  949. dev->power(OFF);
  950. }
  951.  
  952. pr_info(LOGTAG"%s-\n", __func__);
  953.  
  954. return 0;
  955. }
  956.  
  957. static int mcs8000_ts_resume(struct i2c_client *client)
  958. {
  959. struct mcs8000_ts_device *dev = i2c_get_clientdata(client);
  960.  
  961.  
  962. DMSG(KERN_INFO"%s: start! \n", __FUNCTION__);
  963. pr_info(LOGTAG"%s+\n", __func__);
  964. if(power_flag==0){
  965. pr_info(LOGTAG"%s: power flag 0\n", __func__);
  966. power_flag++;
  967. dev->power(ON);
  968. }
  969.  
  970. if (irq_flag == 0) {
  971. pr_info(LOGTAG"%s: irq flag 0\n", __func__);
  972. irq_flag++;
  973. enable_irq(dev->num_irq);
  974. }
  975.  
  976. DMSG("%s: irq enable\n", __FUNCTION__);
  977. pr_info(LOGTAG"%s-\n", __func__);
  978.  
  979. return 0;
  980. }
  981. #endif
  982.  
  983. #ifdef CONFIG_HAS_EARLYSUSPEND
  984. static void mcs8000_early_suspend(struct early_suspend *h)
  985. {
  986. int ret=0;
  987. struct mcs8000_ts_device *dev = &mcs8000_ts_dev;
  988.  
  989. //mcs8000_Data_Clear();
  990.  
  991. DMSG(KERN_INFO"%s: start! \n", __FUNCTION__);
  992. pr_info(LOGTAG"%s+\n", __func__);
  993. if (irq_flag == 1) {
  994. pr_info(LOGTAG"%s: irq flag 1\n", __func__);
  995. irq_flag--;
  996. disable_irq(dev->num_irq);
  997. DMSG("%s: irq disable\n", __FUNCTION__);
  998. }
  999.  
  1000. ret = cancel_delayed_work_sync(&dev->work);
  1001. Release_All_Fingers();
  1002. if(power_flag==1){
  1003. pr_info(LOGTAG"%s: power flag 1\n", __func__);
  1004. power_flag--;
  1005. dev->power(OFF);
  1006. }
  1007. pr_info(LOGTAG"%s-\n", __func__);
  1008. }
  1009.  
  1010. static void mcs8000_late_resume(struct early_suspend *h)
  1011. {
  1012. struct mcs8000_ts_device *dev = &mcs8000_ts_dev;
  1013.  
  1014.  
  1015. DMSG(KERN_INFO"%s: start! \n", __FUNCTION__);
  1016. pr_info(LOGTAG"%s+\n", __func__);
  1017. if(power_flag==0){
  1018. pr_info(LOGTAG"%s: power flag 0\n", __func__);
  1019. power_flag++;
  1020. dev->power(ON);
  1021. }
  1022.  
  1023. if (irq_flag == 0) {
  1024. pr_info(LOGTAG"%s: irq flag 0\n", __func__);
  1025. irq_flag++;
  1026. enable_irq(dev->num_irq);
  1027. DMSG("%s: irq enable\n", __FUNCTION__);
  1028. }
  1029. pr_info(LOGTAG"%s-\n", __func__);
  1030. }
  1031. #endif
  1032.  
  1033. static const struct i2c_device_id mcs8000_ts_id[] = {
  1034. {"touch_mcs8000", 1},
  1035. { }
  1036. };
  1037.  
  1038.  
  1039. static struct i2c_driver mcs8000_i2c_ts_driver = {
  1040. .probe = mcs8000_ts_probe,
  1041. .remove = mcs8000_ts_remove,
  1042. #ifndef CONFIG_HAS_EARLYSUSPEND
  1043. .suspend = mcs8000_ts_suspend,
  1044. .resume = mcs8000_ts_resume,
  1045. #endif
  1046. .id_table = mcs8000_ts_id,
  1047. .driver = {
  1048. .name = "touch_mcs8000",
  1049. .owner = THIS_MODULE,
  1050. },
  1051. };
  1052.  
  1053. static int __devinit mcs8000_ts_init(void)
  1054. {
  1055. int err = 0;
  1056. struct mcs8000_ts_device *dev;
  1057. dev = &mcs8000_ts_dev;
  1058.  
  1059. memset(&mcs8000_ts_dev, 0, sizeof(struct mcs8000_ts_device));
  1060.  
  1061. mcs8000_ts_input = input_allocate_device();
  1062. if (mcs8000_ts_input == NULL) {
  1063. printk(KERN_ERR "%s: input_allocate: not enough memory\n",
  1064. __FUNCTION__);
  1065. err = -ENOMEM;
  1066. goto err_input_allocate;
  1067. }
  1068.  
  1069. mcs8000_ts_input->name = "touch_mcs8000";
  1070.  
  1071.  
  1072. set_bit(EV_ABS, mcs8000_ts_input->evbit);
  1073. set_bit(EV_KEY, mcs8000_ts_input->evbit);
  1074. set_bit(INPUT_PROP_DIRECT, mcs8000_ts_input->propbit);
  1075.  
  1076. mcs8000_ts_input->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
  1077.  
  1078. mcs8000_ts_input->keybit[BIT_WORD(KEY_BACK)] |= BIT_MASK(KEY_BACK);
  1079. mcs8000_ts_input->keybit[BIT_WORD(KEY_MENU)] |= BIT_MASK(KEY_MENU);
  1080. mcs8000_ts_input->keybit[BIT_WORD(KEY_HOMEPAGE)] |= BIT_MASK(KEY_HOMEPAGE);
  1081. #if defined(CONFIG_MACH_MSM7X25A_V1)
  1082. mcs8000_ts_input->keybit[BIT_WORD(KEY_SIM_SWITCH)] |= BIT_MASK(KEY_SIM_SWITCH);
  1083. #endif
  1084.  
  1085. err = input_register_device(mcs8000_ts_input);
  1086. if (err < 0) {
  1087. printk(KERN_ERR "%s: Fail to register device\n", __FUNCTION__);
  1088. goto err_input_register;
  1089. }
  1090.  
  1091. err = i2c_add_driver(&mcs8000_i2c_ts_driver);
  1092. if (err < 0) {
  1093. printk(KERN_ERR "%s: failed to probe i2c \n", __FUNCTION__);
  1094. goto err_i2c_add_driver;
  1095. }
  1096. /*
  1097. err = misc_register(&mcs8000_ts_misc_dev);
  1098. if (err < 0) {
  1099. printk(KERN_ERR "%s: failed to misc register\n", __FUNCTION__);
  1100. goto err_misc_register;
  1101. }
  1102. */
  1103. dev->ts_wq = create_singlethread_workqueue("ts_wq");
  1104. if (!dev->ts_wq) {
  1105. printk(KERN_ERR "%s: failed to create wp\n", __FUNCTION__);
  1106. err = -1;
  1107. }
  1108. return err;
  1109. /*
  1110. err_misc_register:
  1111. misc_deregister(&mcs8000_ts_misc_dev);
  1112. */
  1113. err_i2c_add_driver:
  1114. i2c_del_driver(&mcs8000_i2c_ts_driver);
  1115. err_input_register:
  1116. input_unregister_device(mcs8000_ts_input);
  1117. err_input_allocate:
  1118. input_free_device(mcs8000_ts_input);
  1119. mcs8000_ts_input = NULL;
  1120. return err;
  1121. }
  1122.  
  1123. static void __exit mcs8000_ts_exit(void)
  1124. {
  1125. struct mcs8000_ts_device *dev;
  1126. dev = &mcs8000_ts_dev;
  1127. /* mcs8000_remove_file(mcs8000_ts_input); */
  1128. i2c_del_driver(&mcs8000_i2c_ts_driver);
  1129. input_unregister_device(mcs8000_ts_input);
  1130. input_free_device(mcs8000_ts_input);
  1131.  
  1132. if (dev->ts_wq)
  1133. destroy_workqueue(dev->ts_wq);
  1134. printk(KERN_INFO "touchscreen driver was unloaded!\nHave a nice day!\n");
  1135. }
  1136.  
  1137. module_init(mcs8000_ts_init);
  1138. module_exit(mcs8000_ts_exit);
  1139.  
  1140. MODULE_DESCRIPTION("MELFAS MCS8000 Touchscreen Driver");
  1141. MODULE_LICENSE("GPL");
Add Comment
Please, Sign In to add comment