^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Cypress CY8CTMA140 (TMA140) touchscreen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * (C) 2020 Linus Walleij <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) 2007 Cypress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * (C) 2007 Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Inspired by the tma140_skomer.c driver in the Samsung GT-S7710 code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * drop. The GT-S7710 is codenamed "Skomer", the code also indicates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * that the same touchscreen was used in a product called "Lucas".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * The code drop for GT-S7710 also contains a firmware downloader and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 15 (!) versions of the firmware drop from Cypress. But here we assume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * the firmware got downloaded to the touchscreen flash successfully and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * just use it to read the fingers. The shipped vendor driver does the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * same.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/input/touchscreen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CY8CTMA140_NAME "cy8ctma140"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CY8CTMA140_MAX_FINGERS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CY8CTMA140_GET_FINGERS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CY8CTMA140_GET_FW_INFO 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* This message also fits some bytes for touchkeys, if used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CY8CTMA140_PACKET_SIZE 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CY8CTMA140_INVALID_BUFFER_BIT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct cy8ctma140 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct touchscreen_properties props;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct regulator_bulk_data regulators[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u8 prev_fingers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u8 prev_f1id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u8 prev_f2id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static void cy8ctma140_report(struct cy8ctma140 *ts, u8 *data, int n_fingers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static const u8 contact_offsets[] = { 0x03, 0x09, 0x10, 0x16 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u16 x, y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) for (i = 0; i < n_fingers; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) buf = &data[contact_offsets[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Odd contacts have contact ID in the lower nibble of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * the preceding byte, whereas even contacts have it in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * the upper nibble of the following byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) id = i % 2 ? buf[-1] & 0x0f : buf[5] >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) slot = input_mt_get_slot_by_key(ts->input, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (slot < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) x = get_unaligned_be16(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) y = get_unaligned_be16(buf + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) w = buf[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dev_dbg(ts->dev, "finger %d: ID %02x (%d, %d) w: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) slot, id, x, y, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) input_mt_slot(ts->input, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) touchscreen_report_pos(ts->input, &ts->props, x, y, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) input_mt_sync_frame(ts->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) input_sync(ts->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static irqreturn_t cy8ctma140_irq_thread(int irq, void *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct cy8ctma140 *ts = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u8 cmdbuf[] = { CY8CTMA140_GET_FINGERS };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u8 buf[CY8CTMA140_PACKET_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct i2c_msg msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .addr = ts->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .len = sizeof(cmdbuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .buf = cmdbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .addr = ts->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .len = sizeof(buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .buf = buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u8 n_fingers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ret != ARRAY_SIZE(msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dev_err(ts->dev, "error reading message: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dev_err(ts->dev, "wrong number of messages\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (buf[1] & BIT(CY8CTMA140_INVALID_BUFFER_BIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dev_dbg(ts->dev, "invalid event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) n_fingers = buf[2] & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (n_fingers > CY8CTMA140_MAX_FINGERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) dev_err(ts->dev, "unexpected number of fingers: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) n_fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) cy8ctma140_report(ts, buf, n_fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static int cy8ctma140_init(struct cy8ctma140 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u8 addr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u8 buf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) addr[0] = CY8CTMA140_GET_FW_INFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ret = i2c_master_send(ts->client, addr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) dev_err(ts->dev, "error sending FW info message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ret = i2c_master_recv(ts->client, buf, 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dev_err(ts->dev, "error receiving FW info message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ret != 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dev_err(ts->dev, "got only %d bytes\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) dev_dbg(ts->dev, "vendor %c%c, HW ID %.2d, FW ver %.4d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) buf[0], buf[1], buf[3], buf[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int cy8ctma140_power_up(struct cy8ctma140 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ts->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) dev_err(ts->dev, "failed to enable regulators\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) msleep(250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static void cy8ctma140_power_down(struct cy8ctma140 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) regulator_bulk_disable(ARRAY_SIZE(ts->regulators),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ts->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* Called from the registered devm action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static void cy8ctma140_power_off_action(void *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct cy8ctma140 *ts = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) cy8ctma140_power_down(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int cy8ctma140_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct cy8ctma140 *ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct input_dev *input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) input = devm_input_allocate_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ts->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ts->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ts->input = input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* One byte for width 0..255 so this is the limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * This sets up event max/min capabilities and fuzz.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Some DT properties are compulsory so we do not need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * to provide defaults for X/Y max or pressure max.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * We just initialize a very simple MT touchscreen here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * some devices use the capability of this touchscreen to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * provide touchkeys, and in that case this needs to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * extended to handle touchkey input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * The firmware takes care of finger tracking and dropping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * invalid ranges.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) touchscreen_parse_properties(input, true, &ts->props);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) input_abs_set_fuzz(input, ABS_MT_POSITION_X, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) input_abs_set_fuzz(input, ABS_MT_POSITION_Y, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) error = input_mt_init_slots(input, CY8CTMA140_MAX_FINGERS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) input->name = CY8CTMA140_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) input->id.bustype = BUS_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) input_set_drvdata(input, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * VCPIN is the analog voltage supply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * VDD is the digital voltage supply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * since the voltage range of VDD overlaps that of VCPIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * many designs to just supply both with a single voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * source of ~3.3 V.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) ts->regulators[0].supply = "vcpin";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ts->regulators[1].supply = "vdd";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ts->regulators);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (error != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev_err(dev, "Failed to get regulators %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) error = cy8ctma140_power_up(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) error = devm_add_action_or_reset(dev, cy8ctma140_power_off_action, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dev_err(dev, "failed to install power off handler\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) error = devm_request_threaded_irq(dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) NULL, cy8ctma140_irq_thread,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) IRQF_ONESHOT, CY8CTMA140_NAME, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) dev_err(dev, "irq %d busy? error %d\n", client->irq, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) error = cy8ctma140_init(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) error = input_register_device(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) i2c_set_clientdata(client, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int __maybe_unused cy8ctma140_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct cy8ctma140 *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!device_may_wakeup(&client->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) cy8ctma140_power_down(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int __maybe_unused cy8ctma140_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct i2c_client *client = to_i2c_client(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) struct cy8ctma140 *ts = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (!device_may_wakeup(&client->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) error = cy8ctma140_power_up(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static SIMPLE_DEV_PM_OPS(cy8ctma140_pm, cy8ctma140_suspend, cy8ctma140_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static const struct i2c_device_id cy8ctma140_idtable[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { CY8CTMA140_NAME, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) MODULE_DEVICE_TABLE(i2c, cy8ctma140_idtable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static const struct of_device_id cy8ctma140_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) { .compatible = "cypress,cy8ctma140", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) { /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) MODULE_DEVICE_TABLE(of, cy8ctma140_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static struct i2c_driver cy8ctma140_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) .name = CY8CTMA140_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .pm = &cy8ctma140_pm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .of_match_table = cy8ctma140_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) .id_table = cy8ctma140_idtable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) .probe = cy8ctma140_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) module_i2c_driver(cy8ctma140_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MODULE_DESCRIPTION("CY8CTMA140 TouchScreen Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) MODULE_LICENSE("GPL v2");