brcm2708: update linux 4.4 patches to latest version
[oweals/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