1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2016, Jelle van der Waa <jelle@vdwaa.nl> 4 */ 5 6 #include <linux/delay.h> 7 #include <linux/i2c.h> 8 #include <linux/input.h> 9 #include <linux/input/mt.h> 10 #include <linux/input/touchscreen.h> 11 #include <linux/interrupt.h> 12 #include <linux/module.h> 13 #include <linux/regulator/consumer.h> 14 #include <asm/unaligned.h> 15 16 #define ZET6223_MAX_FINGERS 16 17 #define ZET6223_MAX_PKT_SIZE (3 + 4 * ZET6223_MAX_FINGERS) 18 19 #define ZET6223_CMD_INFO 0xB2 20 #define ZET6223_CMD_INFO_LENGTH 17 21 #define ZET6223_VALID_PACKET 0x3c 22 23 #define ZET6223_POWER_ON_DELAY_MSEC 30 24 25 struct zet6223_ts { 26 struct i2c_client *client; 27 struct input_dev *input; 28 struct touchscreen_properties prop; 29 struct regulator_bulk_data supplies[2]; 30 u16 max_x; 31 u16 max_y; 32 u8 fingernum; 33 }; 34 35 static int zet6223_start(struct input_dev *dev) 36 { 37 struct zet6223_ts *ts = input_get_drvdata(dev); 38 39 enable_irq(ts->client->irq); 40 41 return 0; 42 } 43 44 static void zet6223_stop(struct input_dev *dev) 45 { 46 struct zet6223_ts *ts = input_get_drvdata(dev); 47 48 disable_irq(ts->client->irq); 49 } 50 51 static irqreturn_t zet6223_irq(int irq, void *dev_id) 52 { 53 struct zet6223_ts *ts = dev_id; 54 u16 finger_bits; 55 56 /* 57 * First 3 bytes are an identifier, two bytes of finger data. 58 * X, Y data per finger is 4 bytes. 59 */ 60 u8 bufsize = 3 + 4 * ts->fingernum; 61 u8 buf[ZET6223_MAX_PKT_SIZE]; 62 int i; 63 int ret; 64 int error; 65 66 ret = i2c_master_recv(ts->client, buf, bufsize); 67 if (ret != bufsize) { 68 error = ret < 0 ? ret : -EIO; 69 dev_err_ratelimited(&ts->client->dev, 70 "Error reading input data: %d\n", error); 71 return IRQ_HANDLED; 72 } 73 74 if (buf[0] != ZET6223_VALID_PACKET) 75 return IRQ_HANDLED; 76 77 finger_bits = get_unaligned_be16(buf + 1); 78 for (i = 0; i < ts->fingernum; i++) { 79 if (!(finger_bits & BIT(15 - i))) 80 continue; 81 82 input_mt_slot(ts->input, i); 83 input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); 84 input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, 85 ((buf[i + 3] >> 4) << 8) + buf[i + 4]); 86 input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, 87 ((buf[i + 3] & 0xF) << 8) + buf[i + 5]); 88 } 89 90 input_mt_sync_frame(ts->input); 91 input_sync(ts->input); 92 93 return IRQ_HANDLED; 94 } 95 96 static void zet6223_power_off(void *_ts) 97 { 98 struct zet6223_ts *ts = _ts; 99 100 regulator_bulk_disable(ARRAY_SIZE(ts->supplies), ts->supplies); 101 } 102 103 static int zet6223_power_on(struct zet6223_ts *ts) 104 { 105 struct device *dev = &ts->client->dev; 106 int error; 107 108 ts->supplies[0].supply = "vio"; 109 ts->supplies[1].supply = "vcc"; 110 111 error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->supplies), 112 ts->supplies); 113 if (error) 114 return error; 115 116 error = regulator_bulk_enable(ARRAY_SIZE(ts->supplies), ts->supplies); 117 if (error) 118 return error; 119 120 msleep(ZET6223_POWER_ON_DELAY_MSEC); 121 122 error = devm_add_action_or_reset(dev, zet6223_power_off, ts); 123 if (error) { 124 dev_err(dev, "failed to install poweroff action: %d\n", error); 125 return error; 126 } 127 128 return 0; 129 } 130 131 static int zet6223_query_device(struct zet6223_ts *ts) 132 { 133 u8 buf[ZET6223_CMD_INFO_LENGTH]; 134 u8 cmd = ZET6223_CMD_INFO; 135 int ret; 136 int error; 137 138 ret = i2c_master_send(ts->client, &cmd, sizeof(cmd)); 139 if (ret != sizeof(cmd)) { 140 error = ret < 0 ? ret : -EIO; 141 dev_err(&ts->client->dev, 142 "touchpanel info cmd failed: %d\n", error); 143 return error; 144 } 145 146 ret = i2c_master_recv(ts->client, buf, sizeof(buf)); 147 if (ret != sizeof(buf)) { 148 error = ret < 0 ? ret : -EIO; 149 dev_err(&ts->client->dev, 150 "failed to retrieve touchpanel info: %d\n", error); 151 return error; 152 } 153 154 ts->fingernum = buf[15] & 0x7F; 155 if (ts->fingernum > ZET6223_MAX_FINGERS) { 156 dev_warn(&ts->client->dev, 157 "touchpanel reports %d fingers, limiting to %d\n", 158 ts->fingernum, ZET6223_MAX_FINGERS); 159 ts->fingernum = ZET6223_MAX_FINGERS; 160 } 161 162 ts->max_x = get_unaligned_le16(&buf[8]); 163 ts->max_y = get_unaligned_le16(&buf[10]); 164 165 return 0; 166 } 167 168 static int zet6223_probe(struct i2c_client *client) 169 { 170 struct device *dev = &client->dev; 171 struct zet6223_ts *ts; 172 struct input_dev *input; 173 int error; 174 175 if (!client->irq) { 176 dev_err(dev, "no irq specified\n"); 177 return -EINVAL; 178 } 179 180 ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); 181 if (!ts) 182 return -ENOMEM; 183 184 ts->client = client; 185 186 error = zet6223_power_on(ts); 187 if (error) 188 return error; 189 190 error = zet6223_query_device(ts); 191 if (error) 192 return error; 193 194 ts->input = input = devm_input_allocate_device(dev); 195 if (!input) 196 return -ENOMEM; 197 198 input_set_drvdata(input, ts); 199 200 input->name = client->name; 201 input->id.bustype = BUS_I2C; 202 input->open = zet6223_start; 203 input->close = zet6223_stop; 204 205 input_set_abs_params(input, ABS_MT_POSITION_X, 0, ts->max_x, 0, 0); 206 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ts->max_y, 0, 0); 207 208 touchscreen_parse_properties(input, true, &ts->prop); 209 210 error = input_mt_init_slots(input, ts->fingernum, 211 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 212 if (error) 213 return error; 214 215 error = devm_request_threaded_irq(dev, client->irq, NULL, zet6223_irq, 216 IRQF_ONESHOT, client->name, ts); 217 if (error) { 218 dev_err(dev, "failed to request irq %d: %d\n", 219 client->irq, error); 220 return error; 221 } 222 223 zet6223_stop(input); 224 225 error = input_register_device(input); 226 if (error) 227 return error; 228 229 return 0; 230 } 231 232 static const struct of_device_id zet6223_of_match[] = { 233 { .compatible = "zeitec,zet6223" }, 234 { } 235 }; 236 MODULE_DEVICE_TABLE(of, zet6223_of_match); 237 238 static const struct i2c_device_id zet6223_id[] = { 239 { "zet6223" }, 240 { } 241 }; 242 MODULE_DEVICE_TABLE(i2c, zet6223_id); 243 244 static struct i2c_driver zet6223_driver = { 245 .driver = { 246 .name = "zet6223", 247 .of_match_table = zet6223_of_match, 248 }, 249 .probe = zet6223_probe, 250 .id_table = zet6223_id 251 }; 252 module_i2c_driver(zet6223_driver); 253 254 MODULE_AUTHOR("Jelle van der Waa <jelle@vdwaa.nl>"); 255 MODULE_DESCRIPTION("ZEITEC zet622x I2C touchscreen driver"); 256 MODULE_LICENSE("GPL"); 257