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