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