ili210x.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. #include <linux/module.h>
  2. #include <linux/i2c.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/slab.h>
  5. #include <linux/input.h>
  6. #include <linux/input/mt.h>
  7. #include <linux/delay.h>
  8. #include <linux/workqueue.h>
  9. #include <linux/input/ili210x.h>
  10. #define MAX_TOUCHES 2
  11. #define DEFAULT_POLL_PERIOD 20
  12. /* Touchscreen commands */
  13. #define REG_TOUCHDATA 0x10
  14. #define REG_PANEL_INFO 0x20
  15. #define REG_FIRMWARE_VERSION 0x40
  16. #define REG_CALIBRATE 0xcc
  17. struct finger {
  18. u8 x_low;
  19. u8 x_high;
  20. u8 y_low;
  21. u8 y_high;
  22. } __packed;
  23. struct touchdata {
  24. u8 status;
  25. struct finger finger[MAX_TOUCHES];
  26. } __packed;
  27. struct panel_info {
  28. struct finger finger_max;
  29. u8 xchannel_num;
  30. u8 ychannel_num;
  31. } __packed;
  32. struct firmware_version {
  33. u8 id;
  34. u8 major;
  35. u8 minor;
  36. } __packed;
  37. struct ili210x {
  38. struct i2c_client *client;
  39. struct input_dev *input;
  40. bool (*get_pendown_state)(void);
  41. unsigned int poll_period;
  42. struct delayed_work dwork;
  43. };
  44. static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
  45. size_t len)
  46. {
  47. struct i2c_msg msg[2] = {
  48. {
  49. .addr = client->addr,
  50. .flags = 0,
  51. .len = 1,
  52. .buf = &reg,
  53. },
  54. {
  55. .addr = client->addr,
  56. .flags = I2C_M_RD,
  57. .len = len,
  58. .buf = buf,
  59. }
  60. };
  61. if (i2c_transfer(client->adapter, msg, 2) != 2) {
  62. dev_err(&client->dev, "i2c transfer failed\n");
  63. return -EIO;
  64. }
  65. return 0;
  66. }
  67. static void ili210x_report_events(struct input_dev *input,
  68. const struct touchdata *touchdata)
  69. {
  70. int i;
  71. bool touch;
  72. unsigned int x, y;
  73. const struct finger *finger;
  74. for (i = 0; i < MAX_TOUCHES; i++) {
  75. input_mt_slot(input, i);
  76. finger = &touchdata->finger[i];
  77. touch = touchdata->status & (1 << i);
  78. input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
  79. if (touch) {
  80. x = finger->x_low | (finger->x_high << 8);
  81. y = finger->y_low | (finger->y_high << 8);
  82. input_report_abs(input, ABS_MT_POSITION_X, x);
  83. input_report_abs(input, ABS_MT_POSITION_Y, y);
  84. }
  85. }
  86. input_mt_report_pointer_emulation(input, false);
  87. input_sync(input);
  88. }
  89. static bool get_pendown_state(const struct ili210x *priv)
  90. {
  91. bool state = false;
  92. if (priv->get_pendown_state)
  93. state = priv->get_pendown_state();
  94. return state;
  95. }
  96. static void ili210x_work(struct work_struct *work)
  97. {
  98. struct ili210x *priv = container_of(work, struct ili210x,
  99. dwork.work);
  100. struct i2c_client *client = priv->client;
  101. struct touchdata touchdata;
  102. int error;
  103. error = ili210x_read_reg(client, REG_TOUCHDATA,
  104. &touchdata, sizeof(touchdata));
  105. if (error) {
  106. dev_err(&client->dev,
  107. "Unable to get touchdata, err = %d\n", error);
  108. return;
  109. }
  110. ili210x_report_events(priv->input, &touchdata);
  111. if ((touchdata.status & 0xf3) || get_pendown_state(priv))
  112. schedule_delayed_work(&priv->dwork,
  113. msecs_to_jiffies(priv->poll_period));
  114. }
  115. static irqreturn_t ili210x_irq(int irq, void *irq_data)
  116. {
  117. struct ili210x *priv = irq_data;
  118. schedule_delayed_work(&priv->dwork, 0);
  119. return IRQ_HANDLED;
  120. }
  121. static ssize_t ili210x_calibrate(struct device *dev,
  122. struct device_attribute *attr,
  123. const char *buf, size_t count)
  124. {
  125. struct i2c_client *client = to_i2c_client(dev);
  126. struct ili210x *priv = i2c_get_clientdata(client);
  127. unsigned long calibrate;
  128. int rc;
  129. u8 cmd = REG_CALIBRATE;
  130. if (kstrtoul(buf, 10, &calibrate))
  131. return -EINVAL;
  132. if (calibrate > 1)
  133. return -EINVAL;
  134. if (calibrate) {
  135. rc = i2c_master_send(priv->client, &cmd, sizeof(cmd));
  136. if (rc != sizeof(cmd))
  137. return -EIO;
  138. }
  139. return count;
  140. }
  141. static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate);
  142. static struct attribute *ili210x_attributes[] = {
  143. &dev_attr_calibrate.attr,
  144. NULL,
  145. };
  146. static const struct attribute_group ili210x_attr_group = {
  147. .attrs = ili210x_attributes,
  148. };
  149. static int ili210x_i2c_probe(struct i2c_client *client,
  150. const struct i2c_device_id *id)
  151. {
  152. struct device *dev = &client->dev;
  153. const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
  154. struct ili210x *priv;
  155. struct input_dev *input;
  156. struct panel_info panel;
  157. struct firmware_version firmware;
  158. int xmax, ymax;
  159. int error;
  160. dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
  161. if (!pdata) {
  162. dev_err(dev, "No platform data!\n");
  163. return -EINVAL;
  164. }
  165. if (client->irq <= 0) {
  166. dev_err(dev, "No IRQ!\n");
  167. return -EINVAL;
  168. }
  169. /* Get firmware version */
  170. error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
  171. &firmware, sizeof(firmware));
  172. if (error) {
  173. dev_err(dev, "Failed to get firmware version, err: %d\n",
  174. error);
  175. return error;
  176. }
  177. /* get panel info */
  178. error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
  179. if (error) {
  180. dev_err(dev, "Failed to get panel information, err: %d\n",
  181. error);
  182. return error;
  183. }
  184. xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
  185. ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
  186. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  187. input = input_allocate_device();
  188. if (!priv || !input) {
  189. error = -ENOMEM;
  190. goto err_free_mem;
  191. }
  192. priv->client = client;
  193. priv->input = input;
  194. priv->get_pendown_state = pdata->get_pendown_state;
  195. priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
  196. INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
  197. /* Setup input device */
  198. input->name = "ILI210x Touchscreen";
  199. input->id.bustype = BUS_I2C;
  200. input->dev.parent = dev;
  201. __set_bit(EV_SYN, input->evbit);
  202. __set_bit(EV_KEY, input->evbit);
  203. __set_bit(EV_ABS, input->evbit);
  204. __set_bit(BTN_TOUCH, input->keybit);
  205. /* Single touch */
  206. input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
  207. input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
  208. /* Multi touch */
  209. input_mt_init_slots(input, MAX_TOUCHES, 0);
  210. input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
  211. input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
  212. input_set_drvdata(input, priv);
  213. i2c_set_clientdata(client, priv);
  214. error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
  215. client->name, priv);
  216. if (error) {
  217. dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
  218. error);
  219. goto err_free_mem;
  220. }
  221. error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
  222. if (error) {
  223. dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
  224. error);
  225. goto err_free_irq;
  226. }
  227. error = input_register_device(priv->input);
  228. if (error) {
  229. dev_err(dev, "Cannot register input device, err: %d\n", error);
  230. goto err_remove_sysfs;
  231. }
  232. device_init_wakeup(&client->dev, 1);
  233. dev_dbg(dev,
  234. "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d",
  235. client->irq, firmware.id, firmware.major, firmware.minor);
  236. return 0;
  237. err_remove_sysfs:
  238. sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
  239. err_free_irq:
  240. free_irq(client->irq, priv);
  241. err_free_mem:
  242. input_free_device(input);
  243. kfree(priv);
  244. return error;
  245. }
  246. static int ili210x_i2c_remove(struct i2c_client *client)
  247. {
  248. struct ili210x *priv = i2c_get_clientdata(client);
  249. sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
  250. free_irq(priv->client->irq, priv);
  251. cancel_delayed_work_sync(&priv->dwork);
  252. input_unregister_device(priv->input);
  253. kfree(priv);
  254. return 0;
  255. }
  256. static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
  257. {
  258. struct i2c_client *client = to_i2c_client(dev);
  259. if (device_may_wakeup(&client->dev))
  260. enable_irq_wake(client->irq);
  261. return 0;
  262. }
  263. static int __maybe_unused ili210x_i2c_resume(struct device *dev)
  264. {
  265. struct i2c_client *client = to_i2c_client(dev);
  266. if (device_may_wakeup(&client->dev))
  267. disable_irq_wake(client->irq);
  268. return 0;
  269. }
  270. static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
  271. ili210x_i2c_suspend, ili210x_i2c_resume);
  272. static const struct i2c_device_id ili210x_i2c_id[] = {
  273. { "ili210x", 0 },
  274. { }
  275. };
  276. MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
  277. static struct i2c_driver ili210x_ts_driver = {
  278. .driver = {
  279. .name = "ili210x_i2c",
  280. .pm = &ili210x_i2c_pm,
  281. },
  282. .id_table = ili210x_i2c_id,
  283. .probe = ili210x_i2c_probe,
  284. .remove = ili210x_i2c_remove,
  285. };
  286. module_i2c_driver(ili210x_ts_driver);
  287. MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
  288. MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver");
  289. MODULE_LICENSE("GPL");