auo-pixcir-ts.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. /*
  2. * Driver for AUO in-cell touchscreens
  3. *
  4. * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
  5. *
  6. * loosely based on auo_touch.c from Dell Streak vendor-kernel
  7. *
  8. * Copyright (c) 2008 QUALCOMM Incorporated.
  9. * Copyright (c) 2008 QUALCOMM USA, INC.
  10. *
  11. *
  12. * This software is licensed under the terms of the GNU General Public
  13. * License version 2, as published by the Free Software Foundation, and
  14. * may be copied, distributed, and modified under those terms.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. */
  22. #include <linux/kernel.h>
  23. #include <linux/module.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/slab.h>
  26. #include <linux/input.h>
  27. #include <linux/jiffies.h>
  28. #include <linux/i2c.h>
  29. #include <linux/mutex.h>
  30. #include <linux/delay.h>
  31. #include <linux/gpio.h>
  32. #include <linux/input/auo-pixcir-ts.h>
  33. /*
  34. * Coordinate calculation:
  35. * X1 = X1_LSB + X1_MSB*256
  36. * Y1 = Y1_LSB + Y1_MSB*256
  37. * X2 = X2_LSB + X2_MSB*256
  38. * Y2 = Y2_LSB + Y2_MSB*256
  39. */
  40. #define AUO_PIXCIR_REG_X1_LSB 0x00
  41. #define AUO_PIXCIR_REG_X1_MSB 0x01
  42. #define AUO_PIXCIR_REG_Y1_LSB 0x02
  43. #define AUO_PIXCIR_REG_Y1_MSB 0x03
  44. #define AUO_PIXCIR_REG_X2_LSB 0x04
  45. #define AUO_PIXCIR_REG_X2_MSB 0x05
  46. #define AUO_PIXCIR_REG_Y2_LSB 0x06
  47. #define AUO_PIXCIR_REG_Y2_MSB 0x07
  48. #define AUO_PIXCIR_REG_STRENGTH 0x0d
  49. #define AUO_PIXCIR_REG_STRENGTH_X1_LSB 0x0e
  50. #define AUO_PIXCIR_REG_STRENGTH_X1_MSB 0x0f
  51. #define AUO_PIXCIR_REG_RAW_DATA_X 0x2b
  52. #define AUO_PIXCIR_REG_RAW_DATA_Y 0x4f
  53. #define AUO_PIXCIR_REG_X_SENSITIVITY 0x6f
  54. #define AUO_PIXCIR_REG_Y_SENSITIVITY 0x70
  55. #define AUO_PIXCIR_REG_INT_SETTING 0x71
  56. #define AUO_PIXCIR_REG_INT_WIDTH 0x72
  57. #define AUO_PIXCIR_REG_POWER_MODE 0x73
  58. #define AUO_PIXCIR_REG_VERSION 0x77
  59. #define AUO_PIXCIR_REG_CALIBRATE 0x78
  60. #define AUO_PIXCIR_REG_TOUCHAREA_X1 0x1e
  61. #define AUO_PIXCIR_REG_TOUCHAREA_Y1 0x1f
  62. #define AUO_PIXCIR_REG_TOUCHAREA_X2 0x20
  63. #define AUO_PIXCIR_REG_TOUCHAREA_Y2 0x21
  64. #define AUO_PIXCIR_REG_EEPROM_CALIB_X 0x42
  65. #define AUO_PIXCIR_REG_EEPROM_CALIB_Y 0xad
  66. #define AUO_PIXCIR_INT_TPNUM_MASK 0xe0
  67. #define AUO_PIXCIR_INT_TPNUM_SHIFT 5
  68. #define AUO_PIXCIR_INT_RELEASE (1 << 4)
  69. #define AUO_PIXCIR_INT_ENABLE (1 << 3)
  70. #define AUO_PIXCIR_INT_POL_HIGH (1 << 2)
  71. #define AUO_PIXCIR_INT_MODE_MASK 0x03
  72. /*
  73. * Power modes:
  74. * active: scan speed 60Hz
  75. * sleep: scan speed 10Hz can be auto-activated, wakeup on 1st touch
  76. * deep sleep: scan speed 1Hz can only be entered or left manually.
  77. */
  78. #define AUO_PIXCIR_POWER_ACTIVE 0x00
  79. #define AUO_PIXCIR_POWER_SLEEP 0x01
  80. #define AUO_PIXCIR_POWER_DEEP_SLEEP 0x02
  81. #define AUO_PIXCIR_POWER_MASK 0x03
  82. #define AUO_PIXCIR_POWER_ALLOW_SLEEP (1 << 2)
  83. #define AUO_PIXCIR_POWER_IDLE_TIME(ms) ((ms & 0xf) << 4)
  84. #define AUO_PIXCIR_CALIBRATE 0x03
  85. #define AUO_PIXCIR_EEPROM_CALIB_X_LEN 62
  86. #define AUO_PIXCIR_EEPROM_CALIB_Y_LEN 36
  87. #define AUO_PIXCIR_RAW_DATA_X_LEN 18
  88. #define AUO_PIXCIR_RAW_DATA_Y_LEN 11
  89. #define AUO_PIXCIR_STRENGTH_ENABLE (1 << 0)
  90. /* Touchscreen absolute values */
  91. #define AUO_PIXCIR_REPORT_POINTS 2
  92. #define AUO_PIXCIR_MAX_AREA 0xff
  93. #define AUO_PIXCIR_PENUP_TIMEOUT_MS 10
  94. struct auo_pixcir_ts {
  95. struct i2c_client *client;
  96. struct input_dev *input;
  97. char phys[32];
  98. /* special handling for touch_indicate interupt mode */
  99. bool touch_ind_mode;
  100. wait_queue_head_t wait;
  101. bool stopped;
  102. };
  103. struct auo_point_t {
  104. int coord_x;
  105. int coord_y;
  106. int area_major;
  107. int area_minor;
  108. int orientation;
  109. };
  110. static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts,
  111. struct auo_point_t *point)
  112. {
  113. struct i2c_client *client = ts->client;
  114. const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
  115. uint8_t raw_coord[8];
  116. uint8_t raw_area[4];
  117. int i, ret;
  118. /* touch coordinates */
  119. ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_X1_LSB,
  120. 8, raw_coord);
  121. if (ret < 0) {
  122. dev_err(&client->dev, "failed to read coordinate, %d\n", ret);
  123. return ret;
  124. }
  125. /* touch area */
  126. ret = i2c_smbus_read_i2c_block_data(client, AUO_PIXCIR_REG_TOUCHAREA_X1,
  127. 4, raw_area);
  128. if (ret < 0) {
  129. dev_err(&client->dev, "could not read touch area, %d\n", ret);
  130. return ret;
  131. }
  132. for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) {
  133. point[i].coord_x =
  134. raw_coord[4 * i + 1] << 8 | raw_coord[4 * i];
  135. point[i].coord_y =
  136. raw_coord[4 * i + 3] << 8 | raw_coord[4 * i + 2];
  137. if (point[i].coord_x > pdata->x_max ||
  138. point[i].coord_y > pdata->y_max) {
  139. dev_warn(&client->dev, "coordinates (%d,%d) invalid\n",
  140. point[i].coord_x, point[i].coord_y);
  141. point[i].coord_x = point[i].coord_y = 0;
  142. }
  143. /* determine touch major, minor and orientation */
  144. point[i].area_major = max(raw_area[2 * i], raw_area[2 * i + 1]);
  145. point[i].area_minor = min(raw_area[2 * i], raw_area[2 * i + 1]);
  146. point[i].orientation = raw_area[2 * i] > raw_area[2 * i + 1];
  147. }
  148. return 0;
  149. }
  150. static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id)
  151. {
  152. struct auo_pixcir_ts *ts = dev_id;
  153. struct i2c_client *client = ts->client;
  154. const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
  155. struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS];
  156. int i;
  157. int ret;
  158. int fingers = 0;
  159. int abs = -1;
  160. while (!ts->stopped) {
  161. /* check for up event in touch touch_ind_mode */
  162. if (ts->touch_ind_mode) {
  163. if (gpio_get_value(pdata->gpio_int) == 0) {
  164. input_mt_sync(ts->input);
  165. input_report_key(ts->input, BTN_TOUCH, 0);
  166. input_sync(ts->input);
  167. break;
  168. }
  169. }
  170. ret = auo_pixcir_collect_data(ts, point);
  171. if (ret < 0) {
  172. /* we want to loop only in touch_ind_mode */
  173. if (!ts->touch_ind_mode)
  174. break;
  175. wait_event_timeout(ts->wait, ts->stopped,
  176. msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS));
  177. continue;
  178. }
  179. for (i = 0; i < AUO_PIXCIR_REPORT_POINTS; i++) {
  180. if (point[i].coord_x > 0 || point[i].coord_y > 0) {
  181. input_report_abs(ts->input, ABS_MT_POSITION_X,
  182. point[i].coord_x);
  183. input_report_abs(ts->input, ABS_MT_POSITION_Y,
  184. point[i].coord_y);
  185. input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
  186. point[i].area_major);
  187. input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
  188. point[i].area_minor);
  189. input_report_abs(ts->input, ABS_MT_ORIENTATION,
  190. point[i].orientation);
  191. input_mt_sync(ts->input);
  192. /* use first finger as source for singletouch */
  193. if (fingers == 0)
  194. abs = i;
  195. /* number of touch points could also be queried
  196. * via i2c but would require an additional call
  197. */
  198. fingers++;
  199. }
  200. }
  201. input_report_key(ts->input, BTN_TOUCH, fingers > 0);
  202. if (abs > -1) {
  203. input_report_abs(ts->input, ABS_X, point[abs].coord_x);
  204. input_report_abs(ts->input, ABS_Y, point[abs].coord_y);
  205. }
  206. input_sync(ts->input);
  207. /* we want to loop only in touch_ind_mode */
  208. if (!ts->touch_ind_mode)
  209. break;
  210. wait_event_timeout(ts->wait, ts->stopped,
  211. msecs_to_jiffies(AUO_PIXCIR_PENUP_TIMEOUT_MS));
  212. }
  213. return IRQ_HANDLED;
  214. }
  215. /*
  216. * Set the power mode of the device.
  217. * Valid modes are
  218. * - AUO_PIXCIR_POWER_ACTIVE
  219. * - AUO_PIXCIR_POWER_SLEEP - automatically left on first touch
  220. * - AUO_PIXCIR_POWER_DEEP_SLEEP
  221. */
  222. static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode)
  223. {
  224. struct i2c_client *client = ts->client;
  225. int ret;
  226. ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_POWER_MODE);
  227. if (ret < 0) {
  228. dev_err(&client->dev, "unable to read reg %Xh, %d\n",
  229. AUO_PIXCIR_REG_POWER_MODE, ret);
  230. return ret;
  231. }
  232. ret &= ~AUO_PIXCIR_POWER_MASK;
  233. ret |= mode;
  234. ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_POWER_MODE, ret);
  235. if (ret) {
  236. dev_err(&client->dev, "unable to write reg %Xh, %d\n",
  237. AUO_PIXCIR_REG_POWER_MODE, ret);
  238. return ret;
  239. }
  240. return 0;
  241. }
  242. static __devinit int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
  243. int int_setting)
  244. {
  245. struct i2c_client *client = ts->client;
  246. struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
  247. int ret;
  248. ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING);
  249. if (ret < 0) {
  250. dev_err(&client->dev, "unable to read reg %Xh, %d\n",
  251. AUO_PIXCIR_REG_INT_SETTING, ret);
  252. return ret;
  253. }
  254. ret &= ~AUO_PIXCIR_INT_MODE_MASK;
  255. ret |= int_setting;
  256. ret |= AUO_PIXCIR_INT_POL_HIGH; /* always use high for interrupts */
  257. ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING,
  258. ret);
  259. if (ret < 0) {
  260. dev_err(&client->dev, "unable to write reg %Xh, %d\n",
  261. AUO_PIXCIR_REG_INT_SETTING, ret);
  262. return ret;
  263. }
  264. ts->touch_ind_mode = pdata->int_setting == AUO_PIXCIR_INT_TOUCH_IND;
  265. return 0;
  266. }
  267. /* control the generation of interrupts on the device side */
  268. static int auo_pixcir_int_toggle(struct auo_pixcir_ts *ts, bool enable)
  269. {
  270. struct i2c_client *client = ts->client;
  271. int ret;
  272. ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING);
  273. if (ret < 0) {
  274. dev_err(&client->dev, "unable to read reg %Xh, %d\n",
  275. AUO_PIXCIR_REG_INT_SETTING, ret);
  276. return ret;
  277. }
  278. if (enable)
  279. ret |= AUO_PIXCIR_INT_ENABLE;
  280. else
  281. ret &= ~AUO_PIXCIR_INT_ENABLE;
  282. ret = i2c_smbus_write_byte_data(client, AUO_PIXCIR_REG_INT_SETTING,
  283. ret);
  284. if (ret < 0) {
  285. dev_err(&client->dev, "unable to write reg %Xh, %d\n",
  286. AUO_PIXCIR_REG_INT_SETTING, ret);
  287. return ret;
  288. }
  289. return 0;
  290. }
  291. static int auo_pixcir_start(struct auo_pixcir_ts *ts)
  292. {
  293. struct i2c_client *client = ts->client;
  294. int ret;
  295. ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_ACTIVE);
  296. if (ret < 0) {
  297. dev_err(&client->dev, "could not set power mode, %d\n",
  298. ret);
  299. return ret;
  300. }
  301. ts->stopped = false;
  302. mb();
  303. enable_irq(client->irq);
  304. ret = auo_pixcir_int_toggle(ts, 1);
  305. if (ret < 0) {
  306. dev_err(&client->dev, "could not enable interrupt, %d\n",
  307. ret);
  308. disable_irq(client->irq);
  309. return ret;
  310. }
  311. return 0;
  312. }
  313. static int auo_pixcir_stop(struct auo_pixcir_ts *ts)
  314. {
  315. struct i2c_client *client = ts->client;
  316. int ret;
  317. ret = auo_pixcir_int_toggle(ts, 0);
  318. if (ret < 0) {
  319. dev_err(&client->dev, "could not disable interrupt, %d\n",
  320. ret);
  321. return ret;
  322. }
  323. /* disable receiving of interrupts */
  324. disable_irq(client->irq);
  325. ts->stopped = true;
  326. mb();
  327. wake_up(&ts->wait);
  328. return auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_DEEP_SLEEP);
  329. }
  330. static int auo_pixcir_input_open(struct input_dev *dev)
  331. {
  332. struct auo_pixcir_ts *ts = input_get_drvdata(dev);
  333. int ret;
  334. ret = auo_pixcir_start(ts);
  335. if (ret)
  336. return ret;
  337. return 0;
  338. }
  339. static void auo_pixcir_input_close(struct input_dev *dev)
  340. {
  341. struct auo_pixcir_ts *ts = input_get_drvdata(dev);
  342. auo_pixcir_stop(ts);
  343. return;
  344. }
  345. #ifdef CONFIG_PM_SLEEP
  346. static int auo_pixcir_suspend(struct device *dev)
  347. {
  348. struct i2c_client *client = to_i2c_client(dev);
  349. struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
  350. struct input_dev *input = ts->input;
  351. int ret = 0;
  352. mutex_lock(&input->mutex);
  353. /* when configured as wakeup source, device should always wake system
  354. * therefore start device if necessary
  355. */
  356. if (device_may_wakeup(&client->dev)) {
  357. /* need to start device if not open, to be wakeup source */
  358. if (!input->users) {
  359. ret = auo_pixcir_start(ts);
  360. if (ret)
  361. goto unlock;
  362. }
  363. enable_irq_wake(client->irq);
  364. ret = auo_pixcir_power_mode(ts, AUO_PIXCIR_POWER_SLEEP);
  365. } else if (input->users) {
  366. ret = auo_pixcir_stop(ts);
  367. }
  368. unlock:
  369. mutex_unlock(&input->mutex);
  370. return ret;
  371. }
  372. static int auo_pixcir_resume(struct device *dev)
  373. {
  374. struct i2c_client *client = to_i2c_client(dev);
  375. struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
  376. struct input_dev *input = ts->input;
  377. int ret = 0;
  378. mutex_lock(&input->mutex);
  379. if (device_may_wakeup(&client->dev)) {
  380. disable_irq_wake(client->irq);
  381. /* need to stop device if it was not open on suspend */
  382. if (!input->users) {
  383. ret = auo_pixcir_stop(ts);
  384. if (ret)
  385. goto unlock;
  386. }
  387. /* device wakes automatically from SLEEP */
  388. } else if (input->users) {
  389. ret = auo_pixcir_start(ts);
  390. }
  391. unlock:
  392. mutex_unlock(&input->mutex);
  393. return ret;
  394. }
  395. #endif
  396. static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend,
  397. auo_pixcir_resume);
  398. static int __devinit auo_pixcir_probe(struct i2c_client *client,
  399. const struct i2c_device_id *id)
  400. {
  401. const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
  402. struct auo_pixcir_ts *ts;
  403. struct input_dev *input_dev;
  404. int ret;
  405. if (!pdata)
  406. return -EINVAL;
  407. ts = kzalloc(sizeof(struct auo_pixcir_ts), GFP_KERNEL);
  408. if (!ts)
  409. return -ENOMEM;
  410. ret = gpio_request(pdata->gpio_int, "auo_pixcir_ts_int");
  411. if (ret) {
  412. dev_err(&client->dev, "request of gpio %d failed, %d\n",
  413. pdata->gpio_int, ret);
  414. goto err_gpio_int;
  415. }
  416. if (pdata->init_hw)
  417. pdata->init_hw(client);
  418. ts->client = client;
  419. ts->touch_ind_mode = 0;
  420. init_waitqueue_head(&ts->wait);
  421. snprintf(ts->phys, sizeof(ts->phys),
  422. "%s/input0", dev_name(&client->dev));
  423. input_dev = input_allocate_device();
  424. if (!input_dev) {
  425. dev_err(&client->dev, "could not allocate input device\n");
  426. goto err_input_alloc;
  427. }
  428. ts->input = input_dev;
  429. input_dev->name = "AUO-Pixcir touchscreen";
  430. input_dev->phys = ts->phys;
  431. input_dev->id.bustype = BUS_I2C;
  432. input_dev->dev.parent = &client->dev;
  433. input_dev->open = auo_pixcir_input_open;
  434. input_dev->close = auo_pixcir_input_close;
  435. __set_bit(EV_ABS, input_dev->evbit);
  436. __set_bit(EV_KEY, input_dev->evbit);
  437. __set_bit(BTN_TOUCH, input_dev->keybit);
  438. /* For single touch */
  439. input_set_abs_params(input_dev, ABS_X, 0, pdata->x_max, 0, 0);
  440. input_set_abs_params(input_dev, ABS_Y, 0, pdata->y_max, 0, 0);
  441. /* For multi touch */
  442. input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
  443. pdata->x_max, 0, 0);
  444. input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
  445. pdata->y_max, 0, 0);
  446. input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
  447. AUO_PIXCIR_MAX_AREA, 0, 0);
  448. input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
  449. AUO_PIXCIR_MAX_AREA, 0, 0);
  450. input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
  451. ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_VERSION);
  452. if (ret < 0)
  453. goto err_fw_vers;
  454. dev_info(&client->dev, "firmware version 0x%X\n", ret);
  455. ret = auo_pixcir_int_config(ts, pdata->int_setting);
  456. if (ret)
  457. goto err_fw_vers;
  458. input_set_drvdata(ts->input, ts);
  459. ts->stopped = true;
  460. ret = request_threaded_irq(client->irq, NULL, auo_pixcir_interrupt,
  461. IRQF_TRIGGER_RISING | IRQF_ONESHOT,
  462. input_dev->name, ts);
  463. if (ret) {
  464. dev_err(&client->dev, "irq %d requested failed\n", client->irq);
  465. goto err_fw_vers;
  466. }
  467. /* stop device and put it into deep sleep until it is opened */
  468. ret = auo_pixcir_stop(ts);
  469. if (ret < 0)
  470. goto err_input_register;
  471. ret = input_register_device(input_dev);
  472. if (ret) {
  473. dev_err(&client->dev, "could not register input device\n");
  474. goto err_input_register;
  475. }
  476. i2c_set_clientdata(client, ts);
  477. return 0;
  478. err_input_register:
  479. free_irq(client->irq, ts);
  480. err_fw_vers:
  481. input_free_device(input_dev);
  482. err_input_alloc:
  483. if (pdata->exit_hw)
  484. pdata->exit_hw(client);
  485. gpio_free(pdata->gpio_int);
  486. err_gpio_int:
  487. kfree(ts);
  488. return ret;
  489. }
  490. static int __devexit auo_pixcir_remove(struct i2c_client *client)
  491. {
  492. struct auo_pixcir_ts *ts = i2c_get_clientdata(client);
  493. const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data;
  494. free_irq(client->irq, ts);
  495. input_unregister_device(ts->input);
  496. if (pdata->exit_hw)
  497. pdata->exit_hw(client);
  498. gpio_free(pdata->gpio_int);
  499. kfree(ts);
  500. return 0;
  501. }
  502. static const struct i2c_device_id auo_pixcir_idtable[] = {
  503. { "auo_pixcir_ts", 0 },
  504. { }
  505. };
  506. MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable);
  507. static struct i2c_driver auo_pixcir_driver = {
  508. .driver = {
  509. .owner = THIS_MODULE,
  510. .name = "auo_pixcir_ts",
  511. .pm = &auo_pixcir_pm_ops,
  512. },
  513. .probe = auo_pixcir_probe,
  514. .remove = __devexit_p(auo_pixcir_remove),
  515. .id_table = auo_pixcir_idtable,
  516. };
  517. module_i2c_driver(auo_pixcir_driver);
  518. MODULE_DESCRIPTION("AUO-PIXCIR touchscreen driver");
  519. MODULE_LICENSE("GPL v2");
  520. MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");