gt811 driver

    1. #include <linux/module.h>
    2. #include <linux/i2c.h>
    3. #include <linux/platform_device.h>
    4. #include <linux/gpio.h>
    5. #include <linux/of.h>
    6. #include <linux/of_platform.h>
    7. #include <linux/of_gpio.h>
    8. #include <linux/input.h>
    9. #include <linux/input/mt.h>
    10. #include <linux/interrupt.h>
    11. #include <linux/delay.h>
    12. struct gt811_ts_platdata
    13. {
    14. u32 size_x;
    15. u32 size_y;
    16. u32 size_p;
    17. u32 swap;
    18. u32 revert_x;
    19. u32 revert_y;
    20. u32 reset_pin;
    21. u32 interrupt_pin;
    22. u32 ponits_max;
    23. struct i2c_client *client;
    24. struct input_dev *input;
    25. struct work_struct work;
    26. };
    27. static const struct of_device_id gt811_ts_of_match[] = {
    28. { .compatible = "gt811,gt811_ts", .data = NULL },
    29. { }
    30. };
    31. static int i2c_write_bytes(struct i2c_client *client, uint8_t *data, int len){
    32. struct i2c_msg msg;
    33. msg.flags=!I2C_M_RD;
    34. msg.addr=client->addr;
    35. msg.len=len;
    36. msg.buf=data;
    37. return i2c_transfer(client->adapter,&msg, 1);
    38. }
    39. static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len){
    40. struct i2c_msg msgs[2];
    41. msgs[0].flags=!I2C_M_RD;
    42. msgs[0].addr=client->addr;
    43. msgs[0].len=2;
    44. msgs[0].buf=&buf[0];
    45. msgs[1].flags=I2C_M_RD;
    46. msgs[1].addr=client->addr;
    47. msgs[1].len=len-2;
    48. msgs[1].buf=&buf[2];
    49. return i2c_transfer(client->adapter,msgs, 2);
    50. }
    51. static void gt811_ts_handler(struct work_struct *work)
    52. {
    53. struct gt811_ts_platdata *pdata = container_of(work, struct gt811_ts_platdata, work);
    54. struct device *dev = &pdata->client->dev;
    55. uint8_t buffer[36] = {0x07, 0x21, 0};
    56. uint8_t count, index, flags, position;
    57. int x, y;
    58. buffer[0] = 0x0f;
    59. buffer[1] = 0xff;
    60. if (i2c_write_bytes(pdata->client,buffer,2) < 0) {
    61. dev_err(dev, "Failed to write wakeup message.\n");
    62. goto reenable_irq;
    63. }
    64. buffer[0] = 0x07;
    65. buffer[1] = 0x21;
    66. if (i2c_read_bytes(pdata->client, buffer, sizeof(buffer)) < 0) {
    67. dev_err(dev, "Failed to read touch message.\n");
    68. goto reenable_irq;
    69. }
    70. buffer[0] = 0x80;
    71. buffer[1] = 0x00;
    72. if (i2c_write_bytes(pdata->client, buffer, 2) < 0) {
    73. dev_err(dev, "Failed to write sleep message.\n");
    74. goto reenable_irq;
    75. }
    76. buffer[25] = buffer[19];
    77. buffer[19] = 0;
    78. flags = buffer[2]&0x1f;
    79. while (flags) {
    80. if (!(flags&0x1)) {
    81. continue;
    82. }
    83. if (index < 3) {
    84. position = 4 + index * 5;
    85. }
    86. else{
    87. position = 25 + (index - 3) * 5;
    88. }
    89. x = (buffer[position] << 8) | buffer[position + 1];
    90. y = (buffer[position + 2] << 8) | buffer[position + 3];
    91. if(pdata->swap) {
    92. swap(x, y);
    93. }
    94. if(pdata->revert_x){
    95. x = pdata->size_x - x;
    96. }
    97. if(pdata->revert_y){
    98. y = pdata->size_y - y;
    99. }
    100. printk("point:(x:%03d, y:%03d)\n", x, y);
    101. }
    102. // 组织检测出来的触摸点信息上报到输入子系统节点即可
    103. reenable_irq:
    104. enable_irq(pdata->client->irq);
    105. }
    106. static irqreturn_t gt811_ts_isr(int irq, void *dev_id)
    107. {
    108. struct gt811_ts_platdata* pdata = (struct gt811_ts_platdata*)dev_id;
    109. disable_irq_nosync(pdata->client->irq);
    110. schedule_work(&pdata->work);
    111. return IRQ_HANDLED;
    112. }
    113. static int gt811_ts_initilize(struct i2c_client *client)
    114. {
    115. struct device *dev = &client->dev;
    116. struct gt811_ts_platdata *pdata = (struct gt811_ts_platdata*)i2c_get_clientdata(client);
    117. int status = 0, count = 0;
    118. uint8_t version[4] = {0x7, 0x17, 0};
    119. uint8_t config[] = {
    120. 0x06,0xA2,
    121. 0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,
    122. 0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,
    123. 0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,
    124. 0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,
    125. 0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,
    126. 0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,
    127. 0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01
    128. };
    129. config[62] = 480 >> 8;
    130. config[61] = 480 & 0xff;
    131. config[64] = 800 >> 8;
    132. config[63] = 800 & 0xff;
    133. if (!gpio_is_valid(pdata->reset_pin)) {
    134. dev_err(dev, "The reset pin number is invalid.\n");
    135. return -EINVAL;
    136. }
    137. count = 3;
    138. while (count--) {
    139. gpio_direction_output(pdata->reset_pin, 0);
    140. msleep(10);
    141. gpio_direction_output(pdata->reset_pin, 1);
    142. msleep(100);
    143. if (i2c_read_bytes(client, version, sizeof(version)) < 0) {
    144. dev_err(dev, "Failed to get the version of GT811, try again...\n");
    145. status = -ENODEV;
    146. }
    147. else {
    148. dev_info(dev, "Gt811 detected, version(%04x)...\n", (version[2]<<8)|version[3]);
    149. status = 0;
    150. break;
    151. }
    152. }
    153. if (status) {
    154. return status;
    155. }
    156. count = 3;
    157. while (count--) {
    158. if (i2c_write_bytes(client, config, sizeof(config)) < 0) {
    159. dev_err(dev, "Failed to configure the GT811, try again...\n");
    160. status = -EINVAL;
    161. }
    162. else {
    163. dev_info(dev, "Gt811 configue succeed\n");
    164. status = 0;
    165. break;
    166. }
    167. }
    168. return status;
    169. }
    170. static struct gt811_ts_platdata *gt811_ts_parse_devtree(struct i2c_client *client)
    171. {
    172. struct device *dev = &client->dev;
    173. struct device_node *node;
    174. struct gt811_ts_platdata *pdata;
    175. enum of_gpio_flags flags;
    176. node = dev->of_node;
    177. if (!node) {
    178. dev_err(dev, "The of_node is NULL.\n");
    179. return ERR_PTR(-ENODEV);
    180. }
    181. pdata = devm_kzalloc(dev, sizeof(struct device_node), GFP_KERNEL);
    182. if (!pdata) {
    183. dev_err(dev, "No enough memory left.\n");
    184. return ERR_PTR(-ENOMEM);
    185. }
    186. pdata->reset_pin = of_get_gpio_flags(node, 0, &flags);
    187. if (pdata->reset_pin < 0) {
    188. dev_err(dev, "Get RST pin failed!\n");
    189. return ERR_PTR(-EINVAL);
    190. }
    191. if (of_property_read_u32(node, "touchscreen-size-x", &pdata->size_x )) {
    192. dev_err(dev, "Failed to get the touch screen x size.\n");
    193. return ERR_PTR(-EINVAL);
    194. }
    195. if (of_property_read_u32(node, "touchscreen-size-y", &pdata->size_y)) {
    196. dev_err(dev, "Failed to get the touch screen y size.\n");
    197. return ERR_PTR(-EINVAL);
    198. }
    199. if (of_property_read_u32(node, "touchscreen-size-p", &pdata->size_p)) {
    200. pdata->size_p = 255;
    201. }
    202. if (of_property_read_u32(node, "touchscreen-swap", &pdata->swap)) {
    203. pdata->swap = 1;
    204. }
    205. if (of_property_read_u32(node, "touchscreen-revert-x", &pdata->revert_x)) {
    206. pdata->revert_x = 1;
    207. }
    208. if (of_property_read_u32(node, "touchscreen-revert-x", &pdata->revert_y)) {
    209. pdata->revert_y = 1;
    210. }
    211. return pdata;
    212. }
    213. static int gt811_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
    214. {
    215. struct device *dev = &client->dev;
    216. struct gt811_ts_platdata *pdata = dev_get_platdata(dev);
    217. struct input_dev *input;
    218. int error = 0;
    219. if (!of_match_device(of_match_ptr(gt811_ts_of_match), dev)) {
    220. dev_err(dev, "Failed to match.\n");
    221. return -EINVAL;
    222. }
    223. if (!pdata) {
    224. pdata = gt811_ts_parse_devtree(client);
    225. if (IS_ERR(pdata)) {
    226. dev_err(dev, "Get device data from device tree failed!\n");
    227. error = -EINVAL;
    228. goto failed_exit;
    229. }
    230. }
    231. pdata->client = client;
    232. i2c_set_clientdata(client, pdata);
    233. input = devm_input_allocate_device(dev);
    234. if (!input) {
    235. dev_err(dev, "Failed to allocate input device\n");
    236. error = -ENOMEM;
    237. goto pdata_free;
    238. }
    239. pdata->input = input;
    240. input->name = client->name;
    241. input->id.bustype = BUS_I2C;
    242. input->id.product = 0xBEEF;
    243. input->id.vendor  =0xDEAD;
    244. input->dev.parent = &client->dev;
    245. __set_bit(EV_KEY, input->evbit);
    246. __set_bit(EV_ABS, input->evbit);
    247. __set_bit(BTN_TOUCH, input->keybit);
    248. input_set_abs_params(input, ABS_X, 0, pdata->size_x, 0, 0);
    249. input_set_abs_params(input, ABS_Y, 0, pdata->size_y, 0, 0);
    250. input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->size_x, 0, 0);
    251. input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->size_y, 0, 0);
    252. error = input_mt_init_slots(input, 5, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
    253. if (error) {
    254. dev_err(dev, "Failed to initialize the multi-touch slots.\n");
    255. goto input_free;
    256. }
    257. input_set_drvdata(input, pdata);
    258. error = input_register_device(input);
    259. if (error) {
    260. dev_err(dev, "Register input device failed!\n");
    261. goto input_free;
    262. }
    263. if (gt811_ts_initilize(client)) {
    264. dev_err(dev, "Failed to initialize GT811.\n");
    265. }
    266. INIT_WORK(&pdata->work, gt811_ts_handler);
    267. error = devm_request_any_context_irq(dev, client->irq, gt811_ts_isr,
    268. IRQF_TRIGGER_FALLING, client->name, pdata);
    269. if (error) {
    270. dev_err(dev, "Failed to request irq(number:%d)\n", client->irq);
    271. goto input_free;
    272. }
    273. return 0;
    274. input_free:
    275. devm_kfree(dev, input);
    276. pdata_free:
    277. devm_kfree(dev, pdata);
    278. failed_exit:
    279. return error;
    280. }
    281. static int gt811_ts_remove(struct i2c_client *client)
    282. {
    283. struct gt811_ts_platdata *pdata = (struct gt811_ts_platdata*)i2c_get_clientdata(client);
    284. devm_free_irq(&client->dev, client->irq, i2c_get_clientdata(client));
    285. input_unregister_device(pdata->input);
    286. devm_kfree(&client->dev, pdata);
    287. return 0;
    288. }
    289. static const struct i2c_device_id gt811_ts_id[] = {
    290. { "gt811_ts", 0 },
    291. { }
    292. };
    293. static struct i2c_driver gt811_ts_driver = {
    294. .driver = {
    295. .owner  = THIS_MODULE,
    296. .name   = "gt811_ts",
    297. .of_match_table = of_match_ptr(gt811_ts_of_match),
    298. },
    299. .probe      = gt811_ts_probe,
    300. .remove     = gt811_ts_remove,
    301. .id_table   = gt811_ts_id,
    302. };
    303. module_i2c_driver(gt811_ts_driver);
    304. MODULE_AUTHOR("girlkoo <nightmeng@gmail.com>");
    305. MODULE_DESCRIPTION("Gt811 I2C Touchscreen Driver");
    306. MODULE_LICENSE("GPL");
上一篇:HDU 4640 状态压缩DP 未写完


下一篇:cf591B Rebranding