1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for Cypress CY8CTMA140 (TMA140) touchscreen
4 * (C) 2020 Linus Walleij <linus.walleij@linaro.org>
6 * (C) 2007 Google, Inc.
8 * Inspired by the tma140_skomer.c driver in the Samsung GT-S7710 code
9 * drop. The GT-S7710 is codenamed "Skomer", the code also indicates
10 * that the same touchscreen was used in a product called "Lucas".
12 * The code drop for GT-S7710 also contains a firmware downloader and
13 * 15 (!) versions of the firmware drop from Cypress. But here we assume
14 * the firmware got downloaded to the touchscreen flash successfully and
15 * just use it to read the fingers. The shipped vendor driver does the
19 #include <asm/unaligned.h>
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/input.h>
23 #include <linux/input/touchscreen.h>
24 #include <linux/input/mt.h>
25 #include <linux/slab.h>
26 #include <linux/interrupt.h>
28 #include <linux/i2c.h>
29 #include <linux/regulator/consumer.h>
30 #include <linux/delay.h>
32 #define CY8CTMA140_NAME "cy8ctma140"
34 #define CY8CTMA140_MAX_FINGERS 4
36 #define CY8CTMA140_GET_FINGERS 0x00
37 #define CY8CTMA140_GET_FW_INFO 0x19
39 /* This message also fits some bytes for touchkeys, if used */
40 #define CY8CTMA140_PACKET_SIZE 31
42 #define CY8CTMA140_INVALID_BUFFER_BIT 5
45 struct input_dev
*input
;
46 struct touchscreen_properties props
;
48 struct i2c_client
*client
;
49 struct regulator_bulk_data regulators
[2];
55 static void cy8ctma140_report(struct cy8ctma140
*ts
, u8
*data
, int n_fingers
)
57 static const u8 contact_offsets
[] = { 0x03, 0x09, 0x10, 0x16 };
65 for (i
= 0; i
< n_fingers
; i
++) {
66 buf
= &data
[contact_offsets
[i
]];
69 * Odd contacts have contact ID in the lower nibble of
70 * the preceding byte, whereas even contacts have it in
71 * the upper nibble of the following byte.
73 id
= i
% 2 ? buf
[-1] & 0x0f : buf
[5] >> 4;
74 slot
= input_mt_get_slot_by_key(ts
->input
, id
);
78 x
= get_unaligned_be16(buf
);
79 y
= get_unaligned_be16(buf
+ 2);
82 dev_dbg(ts
->dev
, "finger %d: ID %02x (%d, %d) w: %d\n",
85 input_mt_slot(ts
->input
, slot
);
86 input_mt_report_slot_state(ts
->input
, MT_TOOL_FINGER
, true);
87 touchscreen_report_pos(ts
->input
, &ts
->props
, x
, y
, true);
88 input_report_abs(ts
->input
, ABS_MT_TOUCH_MAJOR
, w
);
91 input_mt_sync_frame(ts
->input
);
92 input_sync(ts
->input
);
95 static irqreturn_t
cy8ctma140_irq_thread(int irq
, void *d
)
97 struct cy8ctma140
*ts
= d
;
98 u8 cmdbuf
[] = { CY8CTMA140_GET_FINGERS
};
99 u8 buf
[CY8CTMA140_PACKET_SIZE
];
100 struct i2c_msg msg
[] = {
102 .addr
= ts
->client
->addr
,
104 .len
= sizeof(cmdbuf
),
107 .addr
= ts
->client
->addr
,
116 ret
= i2c_transfer(ts
->client
->adapter
, msg
, ARRAY_SIZE(msg
));
117 if (ret
!= ARRAY_SIZE(msg
)) {
119 dev_err(ts
->dev
, "error reading message: %d\n", ret
);
121 dev_err(ts
->dev
, "wrong number of messages\n");
125 if (buf
[1] & BIT(CY8CTMA140_INVALID_BUFFER_BIT
)) {
126 dev_dbg(ts
->dev
, "invalid event\n");
130 n_fingers
= buf
[2] & 0x0f;
131 if (n_fingers
> CY8CTMA140_MAX_FINGERS
) {
132 dev_err(ts
->dev
, "unexpected number of fingers: %d\n",
137 cy8ctma140_report(ts
, buf
, n_fingers
);
143 static int cy8ctma140_init(struct cy8ctma140
*ts
)
149 addr
[0] = CY8CTMA140_GET_FW_INFO
;
150 ret
= i2c_master_send(ts
->client
, addr
, 1);
152 dev_err(ts
->dev
, "error sending FW info message\n");
155 ret
= i2c_master_recv(ts
->client
, buf
, 5);
157 dev_err(ts
->dev
, "error receiving FW info message\n");
161 dev_err(ts
->dev
, "got only %d bytes\n", ret
);
165 dev_dbg(ts
->dev
, "vendor %c%c, HW ID %.2d, FW ver %.4d\n",
166 buf
[0], buf
[1], buf
[3], buf
[4]);
171 static int cy8ctma140_power_up(struct cy8ctma140
*ts
)
175 error
= regulator_bulk_enable(ARRAY_SIZE(ts
->regulators
),
178 dev_err(ts
->dev
, "failed to enable regulators\n");
187 static void cy8ctma140_power_down(struct cy8ctma140
*ts
)
189 regulator_bulk_disable(ARRAY_SIZE(ts
->regulators
),
193 /* Called from the registered devm action */
194 static void cy8ctma140_power_off_action(void *d
)
196 struct cy8ctma140
*ts
= d
;
198 cy8ctma140_power_down(ts
);
201 static int cy8ctma140_probe(struct i2c_client
*client
,
202 const struct i2c_device_id
*id
)
204 struct cy8ctma140
*ts
;
205 struct input_dev
*input
;
206 struct device
*dev
= &client
->dev
;
209 ts
= devm_kzalloc(dev
, sizeof(*ts
), GFP_KERNEL
);
213 input
= devm_input_allocate_device(dev
);
221 input_set_capability(input
, EV_ABS
, ABS_MT_POSITION_X
);
222 input_set_capability(input
, EV_ABS
, ABS_MT_POSITION_Y
);
223 /* One byte for width 0..255 so this is the limit */
224 input_set_abs_params(input
, ABS_MT_TOUCH_MAJOR
, 0, 255, 0, 0);
226 * This sets up event max/min capabilities and fuzz.
227 * Some DT properties are compulsory so we do not need
228 * to provide defaults for X/Y max or pressure max.
230 * We just initialize a very simple MT touchscreen here,
231 * some devices use the capability of this touchscreen to
232 * provide touchkeys, and in that case this needs to be
233 * extended to handle touchkey input.
235 * The firmware takes care of finger tracking and dropping
238 touchscreen_parse_properties(input
, true, &ts
->props
);
239 input_abs_set_fuzz(input
, ABS_MT_POSITION_X
, 0);
240 input_abs_set_fuzz(input
, ABS_MT_POSITION_Y
, 0);
242 error
= input_mt_init_slots(input
, CY8CTMA140_MAX_FINGERS
,
243 INPUT_MT_DIRECT
| INPUT_MT_DROP_UNUSED
);
247 input
->name
= CY8CTMA140_NAME
;
248 input
->id
.bustype
= BUS_I2C
;
249 input_set_drvdata(input
, ts
);
252 * VCPIN is the analog voltage supply
253 * VDD is the digital voltage supply
254 * since the voltage range of VDD overlaps that of VCPIN,
255 * many designs to just supply both with a single voltage
258 ts
->regulators
[0].supply
= "vcpin";
259 ts
->regulators
[1].supply
= "vdd";
260 error
= devm_regulator_bulk_get(dev
, ARRAY_SIZE(ts
->regulators
),
263 if (error
!= -EPROBE_DEFER
)
264 dev_err(dev
, "Failed to get regulators %d\n",
269 error
= cy8ctma140_power_up(ts
);
273 error
= devm_add_action_or_reset(dev
, cy8ctma140_power_off_action
, ts
);
275 dev_err(dev
, "failed to install power off handler\n");
279 error
= devm_request_threaded_irq(dev
, client
->irq
,
280 NULL
, cy8ctma140_irq_thread
,
281 IRQF_ONESHOT
, CY8CTMA140_NAME
, ts
);
283 dev_err(dev
, "irq %d busy? error %d\n", client
->irq
, error
);
287 error
= cy8ctma140_init(ts
);
291 error
= input_register_device(input
);
295 i2c_set_clientdata(client
, ts
);
300 static int __maybe_unused
cy8ctma140_suspend(struct device
*dev
)
302 struct i2c_client
*client
= to_i2c_client(dev
);
303 struct cy8ctma140
*ts
= i2c_get_clientdata(client
);
305 if (!device_may_wakeup(&client
->dev
))
306 cy8ctma140_power_down(ts
);
311 static int __maybe_unused
cy8ctma140_resume(struct device
*dev
)
313 struct i2c_client
*client
= to_i2c_client(dev
);
314 struct cy8ctma140
*ts
= i2c_get_clientdata(client
);
317 if (!device_may_wakeup(&client
->dev
)) {
318 error
= cy8ctma140_power_up(ts
);
326 static SIMPLE_DEV_PM_OPS(cy8ctma140_pm
, cy8ctma140_suspend
, cy8ctma140_resume
);
328 static const struct i2c_device_id cy8ctma140_idtable
[] = {
329 { CY8CTMA140_NAME
, 0 },
332 MODULE_DEVICE_TABLE(i2c
, cy8ctma140_idtable
);
334 static const struct of_device_id cy8ctma140_of_match
[] = {
335 { .compatible
= "cypress,cy8ctma140", },
338 MODULE_DEVICE_TABLE(of
, cy8ctma140_of_match
);
340 static struct i2c_driver cy8ctma140_driver
= {
342 .name
= CY8CTMA140_NAME
,
343 .pm
= &cy8ctma140_pm
,
344 .of_match_table
= cy8ctma140_of_match
,
346 .id_table
= cy8ctma140_idtable
,
347 .probe
= cy8ctma140_probe
,
349 module_i2c_driver(cy8ctma140_driver
);
351 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
352 MODULE_DESCRIPTION("CY8CTMA140 TouchScreen Driver");
353 MODULE_LICENSE("GPL v2");