0532-rpi-ft5406-Create-coherent-buffer-and-push-to-firmwa.patch 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. From bfc9d5f243f9202b699a2716b528be866039d6a4 Mon Sep 17 00:00:00 2001
  2. From: popcornmix <popcornmix@gmail.com>
  3. Date: Fri, 11 Nov 2016 19:32:54 +0000
  4. Subject: [PATCH] rpi-ft5406: Create coherent buffer and push to firmware
  5. ---
  6. drivers/input/touchscreen/rpi-ft5406.c | 152 +++++++++++++++++++----------
  7. include/soc/bcm2835/raspberrypi-firmware.h | 1 +
  8. 2 files changed, 101 insertions(+), 52 deletions(-)
  9. --- a/drivers/input/touchscreen/rpi-ft5406.c
  10. +++ b/drivers/input/touchscreen/rpi-ft5406.c
  11. @@ -21,6 +21,7 @@
  12. #include <linux/kthread.h>
  13. #include <linux/platform_device.h>
  14. #include <asm/io.h>
  15. +#include <linux/dma-mapping.h>
  16. #include <soc/bcm2835/raspberrypi-firmware.h>
  17. #define MAXIMUM_SUPPORTED_POINTS 10
  18. @@ -45,6 +46,7 @@ struct ft5406 {
  19. struct platform_device * pdev;
  20. struct input_dev * input_dev;
  21. void __iomem * ts_base;
  22. + dma_addr_t bus_addr;
  23. struct ft5406_regs * regs;
  24. struct task_struct * thread;
  25. };
  26. @@ -117,18 +119,19 @@ static int ft5406_thread(void *arg)
  27. static int ft5406_probe(struct platform_device *pdev)
  28. {
  29. - int ret;
  30. - struct input_dev * input_dev = input_allocate_device();
  31. + int err = 0;
  32. + struct device *dev = &pdev->dev;
  33. + struct device_node *np = dev->of_node;
  34. struct ft5406 * ts;
  35. struct device_node *fw_node;
  36. struct rpi_firmware *fw;
  37. u32 touchbuf;
  38. - dev_info(&pdev->dev, "Probing device\n");
  39. + dev_info(dev, "Probing device\n");
  40. - fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0);
  41. + fw_node = of_parse_phandle(np, "firmware", 0);
  42. if (!fw_node) {
  43. - dev_err(&pdev->dev, "Missing firmware node\n");
  44. + dev_err(dev, "Missing firmware node\n");
  45. return -ENOENT;
  46. }
  47. @@ -136,62 +139,88 @@ static int ft5406_probe(struct platform_
  48. if (!fw)
  49. return -EPROBE_DEFER;
  50. - ret = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF,
  51. - &touchbuf, sizeof(touchbuf));
  52. - if (ret) {
  53. - dev_err(&pdev->dev, "Failed to get touch buffer\n");
  54. - return ret;
  55. + ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL);
  56. + if (!ts) {
  57. + dev_err(dev, "Failed to allocate memory\n");
  58. + return -ENOMEM;
  59. }
  60. - if (!touchbuf) {
  61. - dev_err(&pdev->dev, "Touchscreen not detected\n");
  62. - return -ENODEV;
  63. + ts->input_dev = input_allocate_device();
  64. + if (!ts->input_dev) {
  65. + dev_err(dev, "Failed to allocate input device\n");
  66. + return -ENOMEM;
  67. }
  68. - dev_dbg(&pdev->dev, "Got TS buffer 0x%x\n", touchbuf);
  69. + ts->ts_base = dma_zalloc_coherent(NULL, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL);
  70. + if (!ts->ts_base) {
  71. + pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n",
  72. + __func__, PAGE_SIZE);
  73. + err = -ENOMEM;
  74. + goto out;
  75. + }
  76. - ts = kzalloc(sizeof(struct ft5406), GFP_KERNEL);
  77. + touchbuf = (u32)ts->bus_addr;
  78. + err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
  79. + &touchbuf, sizeof(touchbuf));
  80. - if (!ts || !input_dev) {
  81. - ret = -ENOMEM;
  82. - dev_err(&pdev->dev, "Failed to allocate memory\n");
  83. - return ret;
  84. + if (err || touchbuf != 0) {
  85. + dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err);
  86. + dma_free_coherent(NULL, PAGE_SIZE, ts->ts_base, ts->bus_addr);
  87. + ts->ts_base = 0;
  88. + ts->bus_addr = 0;
  89. + }
  90. +
  91. + if (!ts->ts_base) {
  92. + dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr);
  93. +
  94. + err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF,
  95. + &touchbuf, sizeof(touchbuf));
  96. + if (err) {
  97. + dev_err(dev, "Failed to get touch buffer\n");
  98. + goto out;
  99. + }
  100. +
  101. + if (!touchbuf) {
  102. + dev_err(dev, "Touchscreen not detected\n");
  103. + err = -ENODEV;
  104. + goto out;
  105. + }
  106. +
  107. + dev_dbg(dev, "Got TS buffer 0x%x\n", touchbuf);
  108. +
  109. + // mmap the physical memory
  110. + touchbuf &= ~0xc0000000;
  111. + ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs));
  112. + if (ts->ts_base == NULL)
  113. + {
  114. + dev_err(dev, "Failed to map physical address\n");
  115. + err = -ENOMEM;
  116. + goto out;
  117. + }
  118. }
  119. - ts->input_dev = input_dev;
  120. platform_set_drvdata(pdev, ts);
  121. ts->pdev = pdev;
  122. - input_dev->name = "FT5406 memory based driver";
  123. + ts->input_dev->name = "FT5406 memory based driver";
  124. - __set_bit(EV_KEY, input_dev->evbit);
  125. - __set_bit(EV_SYN, input_dev->evbit);
  126. - __set_bit(EV_ABS, input_dev->evbit);
  127. + __set_bit(EV_KEY, ts->input_dev->evbit);
  128. + __set_bit(EV_SYN, ts->input_dev->evbit);
  129. + __set_bit(EV_ABS, ts->input_dev->evbit);
  130. - input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
  131. + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
  132. SCREEN_WIDTH, 0, 0);
  133. - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
  134. + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
  135. SCREEN_HEIGHT, 0, 0);
  136. - input_mt_init_slots(input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT);
  137. + input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT);
  138. - input_set_drvdata(input_dev, ts);
  139. + input_set_drvdata(ts->input_dev, ts);
  140. - ret = input_register_device(input_dev);
  141. - if (ret) {
  142. - dev_err(&pdev->dev, "could not register input device, %d\n",
  143. - ret);
  144. - return ret;
  145. - }
  146. -
  147. - // mmap the physical memory
  148. - touchbuf &= ~0xc0000000;
  149. - ts->ts_base = ioremap(touchbuf, sizeof(*ts->regs));
  150. - if(ts->ts_base == NULL)
  151. - {
  152. - dev_err(&pdev->dev, "Failed to map physical address\n");
  153. - input_unregister_device(input_dev);
  154. - kzfree(ts);
  155. - return -ENOMEM;
  156. + err = input_register_device(ts->input_dev);
  157. + if (err) {
  158. + dev_err(dev, "could not register input device, %d\n",
  159. + err);
  160. + goto out;
  161. }
  162. ts->regs = (struct ft5406_regs *) ts->ts_base;
  163. @@ -200,25 +229,44 @@ static int ft5406_probe(struct platform_
  164. ts->thread = kthread_run(ft5406_thread, ts, "ft5406");
  165. if(ts->thread == NULL)
  166. {
  167. - dev_err(&pdev->dev, "Failed to create kernel thread");
  168. - iounmap(ts->ts_base);
  169. - input_unregister_device(input_dev);
  170. - kzfree(ts);
  171. + dev_err(dev, "Failed to create kernel thread");
  172. + err = -ENOMEM;
  173. + goto out;
  174. }
  175. return 0;
  176. +
  177. +out:
  178. + if (ts->bus_addr) {
  179. + dma_free_coherent(NULL, PAGE_SIZE, ts->ts_base, ts->bus_addr);
  180. + ts->bus_addr = 0;
  181. + ts->ts_base = NULL;
  182. + } else if (ts->ts_base) {
  183. + iounmap(ts->ts_base);
  184. + ts->ts_base = NULL;
  185. + }
  186. + if (ts->input_dev) {
  187. + input_unregister_device(ts->input_dev);
  188. + ts->input_dev = NULL;
  189. + }
  190. + return err;
  191. }
  192. static int ft5406_remove(struct platform_device *pdev)
  193. {
  194. + struct device *dev = &pdev->dev;
  195. struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev);
  196. - dev_info(&pdev->dev, "Removing rpi-ft5406\n");
  197. + dev_info(dev, "Removing rpi-ft5406\n");
  198. kthread_stop(ts->thread);
  199. - iounmap(ts->ts_base);
  200. - input_unregister_device(ts->input_dev);
  201. - kzfree(ts);
  202. +
  203. + if (ts->bus_addr)
  204. + dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr);
  205. + else if (ts->ts_base)
  206. + iounmap(ts->ts_base);
  207. + if (ts->input_dev)
  208. + input_unregister_device(ts->input_dev);
  209. return 0;
  210. }
  211. --- a/include/soc/bcm2835/raspberrypi-firmware.h
  212. +++ b/include/soc/bcm2835/raspberrypi-firmware.h
  213. @@ -117,6 +117,7 @@ enum rpi_firmware_property_tag {
  214. RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
  215. RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
  216. RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
  217. + RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
  218. RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
  219. RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,