gt82x.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /*
  2. *
  3. * Copyright (C) 2011 Goodix, Inc.
  4. *
  5. * Author: Scott
  6. * Date: 2012.01.05
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/delay.h>
  11. #include <linux/device.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/io.h>
  14. #include <linux/err.h>
  15. #include <linux/slab.h>
  16. #include <asm/uaccess.h>
  17. #include <linux/proc_fs.h>
  18. #include "gt82x.h"
  19. #define READ_TOUCH_ADDR_H 0x0F
  20. #define READ_TOUCH_ADDR_L 0x40
  21. #define READ_KEY_ADDR_H 0x0F
  22. #define READ_KEY_ADDR_L 0x41
  23. #define READ_COOR_ADDR_H 0x0F
  24. #define READ_COOR_ADDR_L 0x42
  25. #define RESOLUTION_LOC 71
  26. #define TRIGGER_LOC 66
  27. #define GOODIX_I2C_NAME "Goodix-TS"
  28. static struct workqueue_struct *goodix_wq;
  29. static s32 goodix_ts_remove(struct i2c_client *);
  30. #ifdef CONFIG_HAS_EARLYSUSPEND
  31. static void goodix_ts_early_suspend(struct early_suspend *h);
  32. static void goodix_ts_late_resume(struct early_suspend *h);
  33. #endif
  34. #ifdef CREATE_WR_NODE
  35. extern s32 init_wr_node(struct i2c_client*);
  36. extern void uninit_wr_node(void);
  37. #endif
  38. #ifdef AUTO_UPDATE_GUITAR
  39. extern s32 init_update_proc(struct goodix_ts_data *);
  40. #endif
  41. #define _ENABLE_DBG_LEVEL
  42. #ifdef _ENABLE_DBG_LEVEL
  43. #define DBG_INT (1<<0)
  44. #define DBG_INFO (1<<1)
  45. #define DBG_DATA (1<<2)
  46. #define DBG_REPORT (1<<3)
  47. static int dbg_level = DBG_INFO;
  48. #define goodix_dbg(level, fmt, args...) { if( (level&dbg_level)>0 ) \
  49. printk("[goodix]: " fmt, ## args); }
  50. #define PROC_FS_NAME "gt82x_dbg"
  51. #define PROC_FS_MAX_LEN 8
  52. static struct proc_dir_entry *dbgProcFile;
  53. static int gt82x_proc_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data )
  54. {
  55. return sprintf(buffer, "Debug Level: 0x%08X\n", dbg_level);
  56. }
  57. static int gt82x_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
  58. {
  59. char procfs_buffer_size = 0;
  60. int i;
  61. unsigned char procfs_buf[PROC_FS_MAX_LEN+1] = {0};
  62. procfs_buffer_size = count;
  63. if(procfs_buffer_size > PROC_FS_MAX_LEN )
  64. procfs_buffer_size = PROC_FS_MAX_LEN+1;
  65. if( copy_from_user(procfs_buf, buffer, procfs_buffer_size) )
  66. {
  67. printk(" proc_write faied at copy_from_user\n");
  68. return -EFAULT;
  69. }
  70. if (sscanf(procfs_buf, "%x", &i) == 1) {
  71. dbg_level = i&0xFFFFFFFF;
  72. printk(" Switch Debug Level to 0x%08X\n", dbg_level);
  73. }
  74. else {
  75. printk(" Bad Debug Level!\n");
  76. }
  77. return count;
  78. }
  79. #endif
  80. /*******************************************************
  81. 功能:
  82. 读取从机数据
  83. 每个读操作用两条i2c_msg组成,第1条消息用于发送从机地址,
  84. 第2条用于发送读取地址和取回数据;每条消息前发送起始信号
  85. 参数:
  86. client: i2c设备,包含设备地址
  87. buf[0]~buf[1]: 首字节为读取地址
  88. buf[2]~buf[len]:数据缓冲区
  89. len: 读取数据长度
  90. return:
  91. 执行消息数
  92. *********************************************************/
  93. /*Function as i2c_master_send */
  94. static s32 i2c_read_bytes(struct i2c_client *client, u8 *buf, s32 len)
  95. {
  96. struct i2c_msg msgs[2];
  97. s32 ret=-1;
  98. //发送写地址
  99. msgs[0].flags=!I2C_M_RD; //写消息
  100. msgs[0].addr=client->addr;
  101. msgs[0].len=2;
  102. msgs[0].buf=&buf[0];
  103. //接收数据
  104. msgs[1].flags=I2C_M_RD;//读消息
  105. msgs[1].addr=client->addr;
  106. msgs[1].len=len - ADDR_LENGTH;
  107. msgs[1].buf=&buf[2];
  108. ret=i2c_transfer(client->adapter,msgs, 2);
  109. return ret;
  110. }
  111. /*******************************************************
  112. 功能:
  113. 向从机写数据
  114. 参数:
  115. client: i2c设备,包含设备地址
  116. buf[0]~buf[1]: 首字节为写地址
  117. buf[2]~buf[len]:数据缓冲区
  118. len: 数据长度
  119. return:
  120. 执行消息数
  121. *******************************************************/
  122. /*Function as i2c_master_send */
  123. static s32 i2c_write_bytes(struct i2c_client *client,u8 *data,s32 len)
  124. {
  125. struct i2c_msg msg;
  126. s32 ret=-1;
  127. //发送设备地址
  128. msg.flags=!I2C_M_RD;//写消息
  129. msg.addr=client->addr;
  130. msg.len=len;
  131. msg.buf=data;
  132. ret=i2c_transfer(client->adapter,&msg, 1);
  133. return ret;
  134. }
  135. /*******************************************************
  136. 功能:
  137. 发送前缀命令
  138. ts: client私有数据结构体
  139. return:
  140. 执行结果码,0表示正常执行
  141. *******************************************************/
  142. static s32 i2c_pre_cmd(struct goodix_ts_data *ts)
  143. {
  144. s32 ret;
  145. u8 pre_cmd_data[2]={0x0f, 0xff};
  146. ret=i2c_write_bytes(ts->client,pre_cmd_data,2);
  147. return ret;//*/
  148. }
  149. /*******************************************************
  150. 功能:
  151. 发送后缀命令
  152. ts: client私有数据结构体
  153. return:
  154. 执行结果码,0表示正常执行
  155. *******************************************************/
  156. static s32 i2c_end_cmd(struct goodix_ts_data *ts)
  157. {
  158. s32 ret;
  159. u8 end_cmd_data[2]={0x80, 0x00};
  160. ret=i2c_write_bytes(ts->client,end_cmd_data,2);
  161. return ret;//*/
  162. }
  163. /*******************************************************
  164. 功能:
  165. Guitar初始化函数,用于发送配置信息,获取版本信息
  166. 参数:
  167. ts: client私有数据结构体
  168. return:
  169. 执行结果码,0表示正常执行
  170. *******************************************************/
  171. s32 goodix_init_panel(struct goodix_ts_data *ts)
  172. {
  173. s32 ret;
  174. u8 *config = (u8 *)ts->pdata->data;
  175. ret = i2c_write_bytes(ts->client, config, ts->pdata->data_len);
  176. if (ret <= 0)
  177. {
  178. dev_err(&(ts->client->dev),"init panel failed(i2c error %d)\n ", ret);
  179. return fail;
  180. }
  181. else
  182. {
  183. dev_info(&(ts->client->dev),"init panel success\n");
  184. i2c_end_cmd(ts);
  185. msleep(500);
  186. }
  187. return success;
  188. }
  189. /*******************************************************
  190. 功能:
  191. 触摸屏工作函数
  192. 由中断触发,接受1组坐标数据,校验后再分析输出
  193. 参数:
  194. ts: client私有数据结构体
  195. return:
  196. 执行结果码,0表示正常执行
  197. ********************************************************/
  198. static void goodix_ts_work_func(struct work_struct *work)
  199. {
  200. u8 finger, key, key_change;
  201. u8 chk_sum = 0;
  202. u16 x, y;
  203. s32 i, ret;
  204. u8 touch_data[2 + 2 + 5*MAX_FINGER_NUM + 1] = {READ_TOUCH_ADDR_H,READ_TOUCH_ADDR_L,0, 0};
  205. u8 *p;
  206. struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);
  207. ret=i2c_read_bytes(ts->client, touch_data, ARRAY_SIZE(touch_data));
  208. i2c_end_cmd(ts);
  209. finger = touch_data[2] & 0x1f;
  210. key = touch_data[3] & 0x0f;
  211. if(ret <= 0) {
  212. goodix_dbg(DBG_INFO,"I2C transfer error. Number:%d\n ", ret);
  213. goto XFER_ERROR;
  214. }
  215. else if((touch_data[2]&0xC0)!=0x80) {
  216. goodix_dbg(DBG_INFO, "data not ready, may be caused by inormal reset\n");
  217. goto XFER_ERROR;
  218. }
  219. else if (key == 0x0f) {
  220. goodix_dbg(DBG_INFO, "unknown error, pls calibrate again\n");
  221. goto XFER_ERROR;
  222. }
  223. goodix_dbg(DBG_DATA, "touch data:%5x%5x\n", touch_data[2], touch_data[3]);
  224. p = &touch_data[4];
  225. for (i=0; i<MAX_FINGER_NUM; i++) {
  226. if((finger>>i) & 1) {
  227. goodix_dbg(DBG_DATA, "%5x%5x%5x%5x%5x\n", *p, *(p+1), *(p+2), *(p+3), *(p+4));
  228. chk_sum += *p + *(p+1) + *(p+2) + *(p+3) + *(p+4);
  229. p += 5;
  230. }
  231. }
  232. if (chk_sum != *p) {
  233. goodix_dbg(DBG_DATA, "check sum error(%d, %d)\n", *p, chk_sum);
  234. goto XFER_ERROR;
  235. }
  236. if (finger) {
  237. p = &touch_data[4];
  238. for(i=0; i<MAX_FINGER_NUM; i++) {
  239. if((finger>>i) & 1) {
  240. x = (*p << 8) | *(p+1);
  241. y = (*(p+2) << 8) | *(p+3);
  242. if (ts->pdata->swap_xy) swap(x, y);
  243. if (ts->pdata->xpol) x = ts->pdata->xmax+ ts->pdata->xmin - x;
  244. if (ts->pdata->ypol) y = ts->pdata->ymax+ ts->pdata->ymin - x;
  245. input_report_key(ts->input_dev, BTN_TOUCH, 1);
  246. input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
  247. input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
  248. input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
  249. input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,15);
  250. input_mt_sync(ts->input_dev);
  251. p += 5;
  252. goodix_dbg(DBG_REPORT, "point[%d]=(%d, %d)\n", i, x, y);
  253. }
  254. }
  255. }
  256. else {
  257. input_report_key(ts->input_dev, BTN_TOUCH, 0);
  258. input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
  259. input_mt_sync(ts->input_dev);
  260. goodix_dbg(DBG_REPORT, "fingers up!\n\n");
  261. }
  262. key_change = key ^ ts->last_key;
  263. if (ts->pdata->key_list && key_change) {
  264. for(i=0; i<ts->pdata->key_num; i++) {
  265. if ((key_change>>i)&1) {
  266. input_report_key(ts->input_dev, ts->pdata->key_list[i].value, (key>>i)&1);
  267. goodix_dbg(DBG_REPORT, "key %d %s\n", ts->pdata->key_list[i].value, (key>>i)&1 ? "down":"up");
  268. }
  269. }
  270. ts->last_key = key;
  271. }
  272. input_sync(ts->input_dev);
  273. XFER_ERROR:
  274. if(ts->irq_is_disable == 1)
  275. {
  276. ts->irq_is_disable = 0;
  277. enable_irq(ts->client->irq);
  278. }
  279. }
  280. /*******************************************************
  281. 功能:
  282. 中断响应函数
  283. 由中断触发,调度触摸屏处理函数运行
  284. 参数:
  285. timer:函数关联的计时器
  286. return:
  287. 计时器工作模式,HRTIMER_NORESTART表示不需要自动重启
  288. ********************************************************/
  289. static irqreturn_t goodix_ts_irq_handler(s32 irq, void *dev_id)
  290. {
  291. struct goodix_ts_data *ts = (struct goodix_ts_data*)dev_id;
  292. static int irq_count = 0;
  293. goodix_dbg(DBG_INT, "irq_count=%d\n", irq_count++);
  294. if (!ts->irq_is_disable)
  295. {
  296. disable_irq_nosync(ts->client->irq);
  297. ts->irq_is_disable = 1;
  298. queue_work(goodix_wq, &ts->work);
  299. }
  300. return IRQ_HANDLED;
  301. }
  302. static s32 init_input_dev(struct goodix_ts_data *ts)
  303. {
  304. s32 i;
  305. s32 ret = 0;
  306. ts->input_dev = input_allocate_device();
  307. if (ts->input_dev == NULL)
  308. {
  309. dev_dbg(&ts->client->dev,"goodix_ts_probe: Failed to allocate input device\n");
  310. return fail;
  311. }
  312. ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  313. ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
  314. ts->input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);// absolute coor (x,y)
  315. if (ts->pdata->key_list)
  316. for(i = 0; i < ts->pdata->key_num; i++)
  317. input_set_capability(ts->input_dev, EV_KEY, ts->pdata->key_list[i].value);
  318. #ifdef GOODIX_MULTI_TOUCH
  319. input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
  320. input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
  321. input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->pdata->xmax, 0, 0);
  322. input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->pdata->ymax, 0, 0);
  323. #else
  324. input_set_abs_params(ts->input_dev, ABS_X, 0, ts->pdata->xmax, 0, 0);
  325. input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->pdata->ymax, 0, 0);
  326. input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
  327. #endif
  328. memcpy(ts->phys, "input/ts", 8);
  329. ts->input_dev->name = GOODIX_I2C_NAME;
  330. ts->input_dev->phys = ts->phys;
  331. ts->input_dev->id.bustype = BUS_I2C;
  332. ts->input_dev->id.vendor = 0xDEAD;
  333. ts->input_dev->id.product = 0xBEEF;
  334. ts->input_dev->id.version = 10427; //screen firmware version
  335. ret = input_register_device(ts->input_dev);
  336. if (ret)
  337. {
  338. dev_err(&ts->client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);
  339. input_free_device(ts->input_dev);
  340. return fail;
  341. }
  342. DEBUG_MSG("Register input device successfully!\n");
  343. return success;
  344. }
  345. /*******************************************************
  346. 功能:
  347. 触摸屏探测函数
  348. 在注册驱动时调用(要求存在对应的client);
  349. 用于IO,中断等资源申请;设备注册;触摸屏初始化等工作
  350. 参数:
  351. client:待驱动的设备结构体
  352. id:设备ID
  353. return:
  354. 执行结果码,0表示正常执行
  355. ********************************************************/
  356. static s32 goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
  357. {
  358. s32 ret = 0;
  359. s32 retry=0;
  360. struct goodix_ts_data *ts = NULL;
  361. struct ctp_platform_data *pdata = (struct ctp_platform_data *)client->dev.platform_data;
  362. dev_dbg(&client->dev,"Install touch driver.\n");
  363. if (!pdata) {
  364. dev_err(&client->dev, "No platform data, Pls add platform data in bsp!\n");
  365. return -ENODEV;
  366. }
  367. //Check I2C function
  368. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
  369. {
  370. dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
  371. return -ENODEV;
  372. }
  373. ts = kzalloc(sizeof(*ts), GFP_KERNEL);
  374. if (ts == NULL)
  375. {
  376. return -ENOMEM;
  377. }
  378. INIT_WORK(&ts->work, goodix_ts_work_func); //init work_struct
  379. ts->client = client;
  380. ts->pdata = pdata;
  381. i2c_set_clientdata(client, ts);
  382. if (fail == init_input_dev(ts))
  383. {
  384. return -1;
  385. }
  386. goodix_ts_power(ts, 1);
  387. msleep(10);
  388. guitar_reset(ts, 50);
  389. client->irq = pdata->irq;
  390. disable_irq_nosync(client->irq);
  391. ts->irq_is_disable = 1;
  392. if (pdata->init_irq) {
  393. pdata->init_irq();
  394. }
  395. ret = request_irq(ts->client->irq, goodix_ts_irq_handler, pdata->irq_flag,
  396. ts->client->name, ts);
  397. if (ret != 0)
  398. {
  399. DEBUG_MSG("Cannot allocate ts INT(%d)! ERRNO:%d\n", ts->client->irq, ret);
  400. return -1;
  401. }
  402. else
  403. {
  404. DEBUG_MSG("Reques EIRQ %d successed\n", ts->client->irq);
  405. }
  406. #ifdef CONFIG_HAS_EARLYSUSPEND
  407. ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
  408. ts->early_suspend.suspend = goodix_ts_early_suspend;
  409. ts->early_suspend.resume = goodix_ts_late_resume;
  410. register_early_suspend(&ts->early_suspend);
  411. #endif
  412. #ifdef CREATE_WR_NODE
  413. init_wr_node(client);
  414. #endif
  415. #ifdef AUTO_UPDATE_GUITAR
  416. if (0xff == init_update_proc(ts))
  417. {
  418. DEBUG_MSG("Need update!\n");
  419. return 0;
  420. }
  421. #endif
  422. //Test I2C connection.
  423. DEBUG_MSG("Testing I2C connection...\n");
  424. for(retry = 0;retry < 3; retry++)
  425. //while(1) //For debug use!
  426. {
  427. printk("retry pre_cmd %d\n", retry);
  428. ret = i2c_pre_cmd(ts);
  429. if (ret > 0)
  430. break;
  431. msleep(20);
  432. }
  433. if(ret <= 0)
  434. {
  435. dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n");
  436. DEBUG_MSG("I2C test failed. I2C addr:%x\n", client->addr);
  437. //goodix_ts_remove(ts->client);
  438. return -1;
  439. }
  440. //Send config
  441. for (retry = 0; retry < 3; retry++)
  442. {
  443. if (success == goodix_init_panel(ts))
  444. {
  445. DEBUG_MSG("Initialize successfully!\n");
  446. break;
  447. }
  448. }
  449. if (retry >= 3)
  450. {
  451. DEBUG_MSG("Initialize failed!\n");
  452. goodix_ts_remove(ts->client);
  453. return -1;
  454. }
  455. //Enable interrupt
  456. if(ts->irq_is_disable == 1)
  457. {
  458. DEBUG_MSG("gt827 proble finished and enable interrupt!\n");
  459. ts->irq_is_disable = 0;
  460. //enable_irq(client->irq);
  461. }
  462. return 0;
  463. }
  464. /*******************************************************
  465. 功能:
  466. 驱动资源释放
  467. 参数:
  468. client:设备结构体
  469. return:
  470. 执行结果码,success表示正常执行
  471. ********************************************************/
  472. static s32 goodix_ts_remove(struct i2c_client *client)
  473. {
  474. struct goodix_ts_data *ts = i2c_get_clientdata(client);
  475. dev_notice(&client->dev,"The driver is removing...\n");
  476. #ifdef CONFIG_HAS_EARLYSUSPEND
  477. unregister_early_suspend(&ts->early_suspend);
  478. #endif
  479. #ifdef CREATE_WR_NODE
  480. uninit_wr_node();
  481. #endif
  482. free_irq(client->irq, ts);
  483. i2c_set_clientdata(client, NULL);
  484. input_unregister_device(ts->input_dev);
  485. input_free_device(ts->input_dev);
  486. kfree(ts);
  487. return success;
  488. }
  489. //停用设备
  490. static s32 goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg)
  491. {
  492. struct goodix_ts_data *ts = i2c_get_clientdata(client);
  493. if (!ts->irq_is_disable)
  494. {
  495. disable_irq(client->irq);
  496. ts->irq_is_disable = 1;
  497. }
  498. goodix_ts_power(ts, 0);
  499. return 0;
  500. }
  501. static s32 goodix_ts_resume(struct i2c_client *client)
  502. {
  503. struct goodix_ts_data *ts = i2c_get_clientdata(client);
  504. goodix_ts_power(ts, 1);
  505. guitar_reset(ts, 50);
  506. goodix_init_panel(ts);
  507. ts->irq_is_disable = 0;
  508. enable_irq(client->irq);
  509. return success;
  510. }
  511. #ifdef CONFIG_HAS_EARLYSUSPEND
  512. static void goodix_ts_early_suspend(struct early_suspend *h)
  513. {
  514. struct goodix_ts_data *ts;
  515. ts = container_of(h, struct goodix_ts_data, early_suspend);
  516. goodix_ts_suspend(ts->client, PMSG_SUSPEND);
  517. }
  518. static void goodix_ts_late_resume(struct early_suspend *h)
  519. {
  520. struct goodix_ts_data *ts;
  521. ts = container_of(h, struct goodix_ts_data, early_suspend);
  522. goodix_ts_resume(ts->client);
  523. }
  524. #endif
  525. //可用于该驱动的 设备名—设备ID 列表
  526. //only one client
  527. static const struct i2c_device_id goodix_ts_id[] = {
  528. { GOODIX_I2C_NAME, 0 },
  529. { }
  530. };
  531. //设备驱动结构体
  532. static struct i2c_driver goodix_ts_driver = {
  533. .probe = goodix_ts_probe,
  534. .remove = goodix_ts_remove,
  535. //#ifndef CONFIG_HAS_EARLYSUSPEND
  536. // .suspend = goodix_ts_suspend,
  537. // .resume = goodix_ts_resume,
  538. //#endif
  539. .id_table = goodix_ts_id,
  540. .driver = {
  541. .name = GOODIX_I2C_NAME,
  542. .owner = THIS_MODULE,
  543. },
  544. };
  545. /*******************************************************
  546. 功能:
  547. 驱动加载函数
  548. return:
  549. 执行结果码,0表示正常执行
  550. ********************************************************/
  551. static s32 __devinit goodix_ts_init(void)
  552. {
  553. goodix_wq = create_workqueue("goodix_wq"); //create a work queue and worker thread
  554. if (!goodix_wq)
  555. {
  556. DEBUG_MSG(KERN_ALERT "creat workqueue faiked\n");
  557. return -ENOMEM;
  558. }
  559. #ifdef _ENABLE_DBG_LEVEL
  560. dbgProcFile = create_proc_entry(PROC_FS_NAME, 0666, NULL);
  561. if (dbgProcFile == NULL) {
  562. remove_proc_entry(PROC_FS_NAME, NULL);
  563. DEBUG_MSG(KERN_ALERT, " Could not initialize /proc/%s\n", PROC_FS_NAME);
  564. }
  565. else {
  566. dbgProcFile->read_proc = gt82x_proc_read;
  567. dbgProcFile->write_proc = gt82x_proc_write;
  568. DEBUG_MSG(KERN_ALERT" /proc/%s created\n", PROC_FS_NAME);
  569. }
  570. #endif // #ifdef _ENABLE_DBG_LEVEL
  571. return i2c_add_driver(&goodix_ts_driver);
  572. }
  573. /*******************************************************
  574. 功能:
  575. 驱动卸载函数
  576. 参数:
  577. client:设备结构体
  578. ********************************************************/
  579. static void __exit goodix_ts_exit(void)
  580. {
  581. DEBUG_MSG(KERN_ALERT "Touchscreen driver of guitar exited.\n");
  582. i2c_del_driver(&goodix_ts_driver);
  583. if (goodix_wq)
  584. destroy_workqueue(goodix_wq); //release our work queue
  585. #ifdef _ENABLE_DBG_LEVEL
  586. remove_proc_entry(PROC_FS_NAME, NULL);
  587. #endif
  588. }
  589. late_initcall(goodix_ts_init); //最后初始化驱动
  590. module_exit(goodix_ts_exit);
  591. MODULE_DESCRIPTION("Goodix Touchscreen Driver");
  592. MODULE_LICENSE("GPL");