Skip to content

Commit 24f5778

Browse files
author
James Hughes
committed
Tidy up of the ft5406 driver to use DT
Driver was using a fixed resolution, this commit adds coordinate size, flip and swap features via device tree. Adds overrides so the VC4 can adjust the DT parameters appropriatley, there is a newer version of the VC4 side driver that can now set up the appropriate DT values if requried.
1 parent fec87ed commit 24f5778

File tree

2 files changed

+158
-69
lines changed

2 files changed

+158
-69
lines changed

arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,20 @@
1111
compatible = "rpi,rpi-ft5406";
1212
firmware = <&firmware>;
1313
status = "okay";
14+
touchscreen-size-x = <800>;
15+
touchscreen-size-y = <600>;
16+
touchscreen-inverted-x = <0>;
17+
touchscreen-inverted-y = <0>;
18+
touchscreen-swapped-x-y = <0>;
1419
};
1520
};
1621
};
22+
23+
__overrides__ {
24+
touchscreen-size-x = <&rpi_ft5406>,"touchscreen-size-x:0";
25+
touchscreen-size-y = <&rpi_ft5406>,"touchscreen-size-y:0";
26+
touchscreen-inverted-x = <&rpi_ft5406>,"touchscreen-inverted-x:0";
27+
touchscreen-inverted-y = <&rpi_ft5406>,"touchscreen-inverted-y:0";
28+
touchscreen-swapped-x-y = <&rpi_ft5406>,"touchscreen-swapped-x-y:0";
29+
};
1730
};

drivers/input/touchscreen/rpi-ft5406.c

Lines changed: 145 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
/*
22
* Driver for memory based ft5406 touchscreen
33
*
4-
* Copyright (C) 2015 Raspberry Pi
4+
* Copyright (C) 2015, 2017 Raspberry Pi
55
*
66
*
77
* This program is free software; you can redistribute it and/or modify
88
* it under the terms of the GNU General Public License version 2 as
99
* published by the Free Software Foundation.
1010
*/
1111

12-
1312
#include <linux/module.h>
1413
#include <linux/interrupt.h>
1514
#include <linux/input.h>
@@ -21,11 +20,15 @@
2120
#include <linux/kthread.h>
2221
#include <linux/platform_device.h>
2322
#include <linux/stddef.h>
24-
#include <asm/io.h>
23+
#include <linux/io.h>
2524
#include <linux/dma-mapping.h>
2625
#include <soc/bcm2835/raspberrypi-firmware.h>
2726

2827
#define MAXIMUM_SUPPORTED_POINTS 10
28+
#define FTS_TOUCH_DOWN 0
29+
#define FTS_TOUCH_UP 1
30+
#define FTS_TOUCH_CONTACT 2
31+
2932
struct ft5406_regs {
3033
uint8_t device_mode;
3134
uint8_t gesture_id;
@@ -35,85 +38,126 @@ struct ft5406_regs {
3538
uint8_t xl;
3639
uint8_t yh;
3740
uint8_t yl;
38-
uint8_t res1;
39-
uint8_t res2;
41+
uint8_t pressure; // Not supported.
42+
uint8_t area; // Not supported.
4043
} point[MAXIMUM_SUPPORTED_POINTS];
4144
};
4245

43-
#define SCREEN_WIDTH 800
44-
#define SCREEN_HEIGHT 480
46+
// These are defaults if the DT entries are missing.
47+
#define DEFAULT_SCREEN_WIDTH 800
48+
#define DEFAULT_SCREEN_HEIGHT 480
4549

4650
struct ft5406 {
47-
struct platform_device * pdev;
48-
struct input_dev * input_dev;
49-
void __iomem * ts_base;
50-
dma_addr_t bus_addr;
51-
struct task_struct * thread;
51+
struct platform_device *pdev;
52+
struct input_dev *input_dev;
53+
void __iomem *ts_base;
54+
dma_addr_t bus_addr;
55+
struct task_struct *thread;
56+
57+
uint16_t max_x;
58+
uint16_t max_y;
59+
uint8_t hflip;
60+
uint8_t vflip;
61+
uint8_t xyswap;
5262
};
5363

5464
/* Thread to poll for touchscreen events
55-
*
65+
*
5666
* This thread polls the memory based register copy of the ft5406 registers
5767
* using the number of points register to know whether the copy has been
58-
* updated (we write 99 to the memory copy, the GPU will write between
68+
* updated (we write 99 to the memory copy, the GPU will write between
5969
* 0 - 10 points)
6070
*/
71+
#define ID_TO_BIT(a) (1 << a)
72+
6173
static int ft5406_thread(void *arg)
6274
{
6375
struct ft5406 *ts = (struct ft5406 *) arg;
6476
struct ft5406_regs regs;
6577
int known_ids = 0;
66-
67-
while(!kthread_should_stop())
68-
{
78+
79+
while (!kthread_should_stop()) {
6980
// 60fps polling
7081
msleep_interruptible(17);
7182
memcpy_fromio(&regs, ts->ts_base, sizeof(struct ft5406_regs));
72-
iowrite8(99, ts->ts_base + offsetof(struct ft5406_regs, num_points));
83+
iowrite8(99,
84+
ts->ts_base +
85+
offsetof(struct ft5406_regs, num_points));
86+
7387
// Do not output if theres no new information (num_points is 99)
7488
// or we have no touch points and don't need to release any
75-
if(!(regs.num_points == 99 || (regs.num_points == 0 && known_ids == 0)))
76-
{
89+
if (!(regs.num_points == 99 ||
90+
(regs.num_points == 0 && known_ids == 0))) {
7791
int i;
7892
int modified_ids = 0, released_ids;
79-
for(i = 0; i < regs.num_points; i++)
80-
{
81-
int x = (((int) regs.point[i].xh & 0xf) << 8) + regs.point[i].xl;
82-
int y = (((int) regs.point[i].yh & 0xf) << 8) + regs.point[i].yl;
83-
int touchid = (regs.point[i].yh >> 4) & 0xf;
84-
85-
modified_ids |= 1 << touchid;
86-
87-
if(!((1 << touchid) & known_ids))
88-
dev_dbg(&ts->pdev->dev, "x = %d, y = %d, touchid = %d\n", x, y, touchid);
89-
90-
input_mt_slot(ts->input_dev, touchid);
91-
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
92-
93-
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
94-
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
9593

94+
for (i = 0; i < regs.num_points; i++) {
95+
int x = (((int) regs.point[i].xh & 0xf) << 8) +
96+
regs.point[i].xl;
97+
int y = (((int) regs.point[i].yh & 0xf) << 8) +
98+
regs.point[i].yl;
99+
int touchid = (regs.point[i].yh >> 4) & 0xf;
100+
int event_type = (regs.point[i].xh >> 6) & 0x03;
101+
102+
modified_ids |= ID_TO_BIT(touchid);
103+
104+
if (event_type == FTS_TOUCH_DOWN ||
105+
event_type == FTS_TOUCH_CONTACT) {
106+
if (ts->hflip)
107+
x = ts->max_x - 1 - x;
108+
109+
if (ts->vflip)
110+
y = ts->max_y - 1 - y;
111+
112+
if (ts->xyswap)
113+
swap(x, y);
114+
115+
if (!((ID_TO_BIT(touchid)) & known_ids))
116+
dev_dbg(&ts->pdev->dev,
117+
"x = %d, y = %d, "
118+
"press = %d, "
119+
"touchid = %d\n",
120+
x, y,
121+
regs.point[i].pressure,
122+
touchid);
123+
124+
input_mt_slot(ts->input_dev, touchid);
125+
input_mt_report_slot_state(
126+
ts->input_dev,
127+
MT_TOOL_FINGER,
128+
1);
129+
130+
input_report_abs(ts->input_dev,
131+
ABS_MT_POSITION_X, x);
132+
input_report_abs(ts->input_dev,
133+
ABS_MT_POSITION_Y, y);
134+
}
96135
}
97136

98137
released_ids = known_ids & ~modified_ids;
99-
for(i = 0; released_ids && i < MAXIMUM_SUPPORTED_POINTS; i++)
100-
{
101-
if(released_ids & (1<<i))
102-
{
103-
dev_dbg(&ts->pdev->dev, "Released %d, known = %x modified = %x\n", i, known_ids, modified_ids);
138+
for (i = 0;
139+
released_ids && i < MAXIMUM_SUPPORTED_POINTS;
140+
i++) {
141+
if (released_ids & (1<<i)) {
142+
dev_dbg(&ts->pdev->dev,
143+
"Released %d, known = %x, "
144+
"modified = %x\n",
145+
i, known_ids, modified_ids);
104146
input_mt_slot(ts->input_dev, i);
105-
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
106-
modified_ids &= ~(1 << i);
147+
input_mt_report_slot_state(
148+
ts->input_dev,
149+
MT_TOOL_FINGER,
150+
0);
151+
modified_ids &= ~(ID_TO_BIT(i));
107152
}
108153
}
109154
known_ids = modified_ids;
110-
155+
111156
input_mt_report_pointer_emulation(ts->input_dev, true);
112157
input_sync(ts->input_dev);
113158
}
114-
115159
}
116-
160+
117161
return 0;
118162
}
119163

@@ -122,22 +166,25 @@ static int ft5406_probe(struct platform_device *pdev)
122166
int err = 0;
123167
struct device *dev = &pdev->dev;
124168
struct device_node *np = dev->of_node;
125-
struct ft5406 * ts;
169+
struct ft5406 *ts;
126170
struct device_node *fw_node;
127171
struct rpi_firmware *fw;
128172
u32 touchbuf;
129-
173+
u32 val;
174+
130175
dev_info(dev, "Probing device\n");
131-
176+
132177
fw_node = of_parse_phandle(np, "firmware", 0);
133178
if (!fw_node) {
134179
dev_err(dev, "Missing firmware node\n");
135180
return -ENOENT;
136181
}
137182

138183
fw = rpi_firmware_get(fw_node);
139-
if (!fw)
184+
if (!fw) {
185+
dev_err(dev, "No firmware node - deferring\n");
140186
return -EPROBE_DEFER;
187+
}
141188

142189
ts = devm_kzalloc(dev, sizeof(struct ft5406), GFP_KERNEL);
143190
if (!ts) {
@@ -151,7 +198,8 @@ static int ft5406_probe(struct platform_device *pdev)
151198
return -ENOMEM;
152199
}
153200

154-
ts->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->bus_addr, GFP_KERNEL);
201+
ts->ts_base = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->bus_addr,
202+
GFP_KERNEL);
155203
if (!ts->ts_base) {
156204
pr_err("[%s]: failed to dma_alloc_coherent(%ld)\n",
157205
__func__, PAGE_SIZE);
@@ -164,17 +212,23 @@ static int ft5406_probe(struct platform_device *pdev)
164212
&touchbuf, sizeof(touchbuf));
165213

166214
if (err || touchbuf != 0) {
167-
dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n", err);
215+
dev_warn(dev, "Failed to set touchbuf, trying to get err:%x\n",
216+
err);
168217
dma_free_coherent(dev, PAGE_SIZE, ts->ts_base, ts->bus_addr);
169218
ts->ts_base = 0;
170219
ts->bus_addr = 0;
171220
}
172221

173222
if (!ts->ts_base) {
174-
dev_warn(dev, "set failed, trying get (err:%d touchbuf:%x virt:%p bus:%x)\n", err, touchbuf, ts->ts_base, ts->bus_addr);
175-
176-
err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF,
177-
&touchbuf, sizeof(touchbuf));
223+
dev_warn(dev,
224+
"set failed, trying get"
225+
" (err:%d touchbuf:%x virt:%p bus:%x)\n",
226+
err, touchbuf, ts->ts_base, ts->bus_addr);
227+
228+
err = rpi_firmware_property(
229+
fw,
230+
RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF,
231+
&touchbuf, sizeof(touchbuf));
178232
if (err) {
179233
dev_err(dev, "Failed to get touch buffer\n");
180234
goto out;
@@ -191,31 +245,54 @@ static int ft5406_probe(struct platform_device *pdev)
191245
// mmap the physical memory
192246
touchbuf &= ~0xc0000000;
193247
ts->ts_base = ioremap(touchbuf, sizeof(struct ft5406_regs));
194-
if (ts->ts_base == NULL)
195-
{
248+
if (ts->ts_base == NULL) {
196249
dev_err(dev, "Failed to map physical address\n");
197250
err = -ENOMEM;
198251
goto out;
199252
}
200253
}
201254
platform_set_drvdata(pdev, ts);
202255
ts->pdev = pdev;
203-
256+
204257
ts->input_dev->name = "FT5406 memory based driver";
205-
258+
259+
if (of_property_read_u32(np, "touchscreen-size-x", &val) >= 0)
260+
ts->max_x = val;
261+
else
262+
ts->max_x = DEFAULT_SCREEN_WIDTH;
263+
264+
if (of_property_read_u32(np, "touchscreen-size-y", &val) >= 0)
265+
ts->max_y = val;
266+
else
267+
ts->max_y = DEFAULT_SCREEN_HEIGHT;
268+
269+
if (of_property_read_u32(np, "touchscreen-inverted-x", &val) >= 0)
270+
ts->hflip = val;
271+
272+
if (of_property_read_u32(np, "touchscreen-inverted-y", &val) >= 0)
273+
ts->vflip = val;
274+
275+
if (of_property_read_u32(np, "touchscreen-swapped-x-y", &val) >= 0)
276+
ts->xyswap = val;
277+
278+
dev_dbg(dev,
279+
"Touchscreen parameters (%d,%d), hflip=%d, vflip=%d, xyswap=%d",
280+
ts->max_x, ts->max_y, ts->hflip, ts->vflip, ts->xyswap);
281+
206282
__set_bit(EV_KEY, ts->input_dev->evbit);
207283
__set_bit(EV_SYN, ts->input_dev->evbit);
208284
__set_bit(EV_ABS, ts->input_dev->evbit);
209285

210286
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
211-
SCREEN_WIDTH, 0, 0);
287+
ts->xyswap ? ts->max_y : ts->max_x, 0, 0);
212288
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
213-
SCREEN_HEIGHT, 0, 0);
289+
ts->xyswap ? ts->max_x : ts->max_y, 0, 0);
214290

215-
input_mt_init_slots(ts->input_dev, MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT);
291+
input_mt_init_slots(ts->input_dev,
292+
MAXIMUM_SUPPORTED_POINTS, INPUT_MT_DIRECT);
216293

217294
input_set_drvdata(ts->input_dev, ts);
218-
295+
219296
err = input_register_device(ts->input_dev);
220297
if (err) {
221298
dev_err(dev, "could not register input device, %d\n",
@@ -225,8 +302,7 @@ static int ft5406_probe(struct platform_device *pdev)
225302

226303
// create thread to poll the touch events
227304
ts->thread = kthread_run(ft5406_thread, ts, "ft5406");
228-
if(ts->thread == NULL)
229-
{
305+
if (ts->thread == NULL) {
230306
dev_err(dev, "Failed to create kernel thread");
231307
err = -ENOMEM;
232308
goto out;
@@ -254,9 +330,9 @@ static int ft5406_remove(struct platform_device *pdev)
254330
{
255331
struct device *dev = &pdev->dev;
256332
struct ft5406 *ts = (struct ft5406 *) platform_get_drvdata(pdev);
257-
333+
258334
dev_info(dev, "Removing rpi-ft5406\n");
259-
335+
260336
kthread_stop(ts->thread);
261337

262338
if (ts->bus_addr)
@@ -265,7 +341,7 @@ static int ft5406_remove(struct platform_device *pdev)
265341
iounmap(ts->ts_base);
266342
if (ts->input_dev)
267343
input_unregister_device(ts->input_dev);
268-
344+
269345
return 0;
270346
}
271347

0 commit comments

Comments
 (0)