eeti_ts.c (7055B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Touch Screen driver for EETI's I2C connected touch screen panels 4 * Copyright (c) 2009,2018 Daniel Mack <daniel@zonque.org> 5 * 6 * See EETI's software guide for the protocol specification: 7 * http://home.eeti.com.tw/documentation.html 8 * 9 * Based on migor_ts.c 10 * Copyright (c) 2008 Magnus Damm 11 * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com> 12 */ 13 14#include <linux/module.h> 15#include <linux/kernel.h> 16#include <linux/input.h> 17#include <linux/input/touchscreen.h> 18#include <linux/interrupt.h> 19#include <linux/i2c.h> 20#include <linux/timer.h> 21#include <linux/gpio/consumer.h> 22#include <linux/of.h> 23#include <linux/slab.h> 24#include <asm/unaligned.h> 25 26struct eeti_ts { 27 struct i2c_client *client; 28 struct input_dev *input; 29 struct gpio_desc *attn_gpio; 30 struct touchscreen_properties props; 31 struct mutex mutex; 32 bool running; 33}; 34 35#define EETI_TS_BITDEPTH (11) 36#define EETI_MAXVAL ((1 << (EETI_TS_BITDEPTH + 1)) - 1) 37 38#define REPORT_BIT_PRESSED BIT(0) 39#define REPORT_BIT_AD0 BIT(1) 40#define REPORT_BIT_AD1 BIT(2) 41#define REPORT_BIT_HAS_PRESSURE BIT(6) 42#define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) 43 44static void eeti_ts_report_event(struct eeti_ts *eeti, u8 *buf) 45{ 46 unsigned int res; 47 u16 x, y; 48 49 res = REPORT_RES_BITS(buf[0] & (REPORT_BIT_AD0 | REPORT_BIT_AD1)); 50 51 x = get_unaligned_be16(&buf[1]); 52 y = get_unaligned_be16(&buf[3]); 53 54 /* fix the range to 11 bits */ 55 x >>= res - EETI_TS_BITDEPTH; 56 y >>= res - EETI_TS_BITDEPTH; 57 58 if (buf[0] & REPORT_BIT_HAS_PRESSURE) 59 input_report_abs(eeti->input, ABS_PRESSURE, buf[5]); 60 61 touchscreen_report_pos(eeti->input, &eeti->props, x, y, false); 62 input_report_key(eeti->input, BTN_TOUCH, buf[0] & REPORT_BIT_PRESSED); 63 input_sync(eeti->input); 64} 65 66static int eeti_ts_read(struct eeti_ts *eeti) 67{ 68 int len, error; 69 char buf[6]; 70 71 len = i2c_master_recv(eeti->client, buf, sizeof(buf)); 72 if (len != sizeof(buf)) { 73 error = len < 0 ? len : -EIO; 74 dev_err(&eeti->client->dev, 75 "failed to read touchscreen data: %d\n", 76 error); 77 return error; 78 } 79 80 /* Motion packet */ 81 if (buf[0] & 0x80) 82 eeti_ts_report_event(eeti, buf); 83 84 return 0; 85} 86 87static irqreturn_t eeti_ts_isr(int irq, void *dev_id) 88{ 89 struct eeti_ts *eeti = dev_id; 90 int error; 91 92 mutex_lock(&eeti->mutex); 93 94 do { 95 /* 96 * If we have attention GPIO, trust it. Otherwise we'll read 97 * once and exit. We assume that in this case we are using 98 * level triggered interrupt and it will get raised again 99 * if/when there is more data. 100 */ 101 if (eeti->attn_gpio && 102 !gpiod_get_value_cansleep(eeti->attn_gpio)) { 103 break; 104 } 105 106 error = eeti_ts_read(eeti); 107 if (error) 108 break; 109 110 } while (eeti->running && eeti->attn_gpio); 111 112 mutex_unlock(&eeti->mutex); 113 return IRQ_HANDLED; 114} 115 116static void eeti_ts_start(struct eeti_ts *eeti) 117{ 118 mutex_lock(&eeti->mutex); 119 120 eeti->running = true; 121 enable_irq(eeti->client->irq); 122 123 /* 124 * Kick the controller in case we are using edge interrupt and 125 * we missed our edge while interrupt was disabled. We expect 126 * the attention GPIO to be wired in this case. 127 */ 128 if (eeti->attn_gpio && gpiod_get_value_cansleep(eeti->attn_gpio)) 129 eeti_ts_read(eeti); 130 131 mutex_unlock(&eeti->mutex); 132} 133 134static void eeti_ts_stop(struct eeti_ts *eeti) 135{ 136 /* 137 * Not locking here, just setting a flag and expect that the 138 * interrupt thread will notice the flag eventually. 139 */ 140 eeti->running = false; 141 wmb(); 142 disable_irq(eeti->client->irq); 143} 144 145static int eeti_ts_open(struct input_dev *dev) 146{ 147 struct eeti_ts *eeti = input_get_drvdata(dev); 148 149 eeti_ts_start(eeti); 150 151 return 0; 152} 153 154static void eeti_ts_close(struct input_dev *dev) 155{ 156 struct eeti_ts *eeti = input_get_drvdata(dev); 157 158 eeti_ts_stop(eeti); 159} 160 161static int eeti_ts_probe(struct i2c_client *client, 162 const struct i2c_device_id *idp) 163{ 164 struct device *dev = &client->dev; 165 struct eeti_ts *eeti; 166 struct input_dev *input; 167 int error; 168 169 /* 170 * In contrast to what's described in the datasheet, there seems 171 * to be no way of probing the presence of that device using I2C 172 * commands. So we need to blindly believe it is there, and wait 173 * for interrupts to occur. 174 */ 175 176 eeti = devm_kzalloc(dev, sizeof(*eeti), GFP_KERNEL); 177 if (!eeti) { 178 dev_err(dev, "failed to allocate driver data\n"); 179 return -ENOMEM; 180 } 181 182 mutex_init(&eeti->mutex); 183 184 input = devm_input_allocate_device(dev); 185 if (!input) { 186 dev_err(dev, "Failed to allocate input device.\n"); 187 return -ENOMEM; 188 } 189 190 input_set_capability(input, EV_KEY, BTN_TOUCH); 191 192 input_set_abs_params(input, ABS_X, 0, EETI_MAXVAL, 0, 0); 193 input_set_abs_params(input, ABS_Y, 0, EETI_MAXVAL, 0, 0); 194 input_set_abs_params(input, ABS_PRESSURE, 0, 0xff, 0, 0); 195 196 touchscreen_parse_properties(input, false, &eeti->props); 197 198 input->name = client->name; 199 input->id.bustype = BUS_I2C; 200 input->open = eeti_ts_open; 201 input->close = eeti_ts_close; 202 203 eeti->client = client; 204 eeti->input = input; 205 206 eeti->attn_gpio = devm_gpiod_get_optional(dev, "attn", GPIOD_IN); 207 if (IS_ERR(eeti->attn_gpio)) 208 return PTR_ERR(eeti->attn_gpio); 209 210 i2c_set_clientdata(client, eeti); 211 input_set_drvdata(input, eeti); 212 213 error = devm_request_threaded_irq(dev, client->irq, 214 NULL, eeti_ts_isr, 215 IRQF_ONESHOT, 216 client->name, eeti); 217 if (error) { 218 dev_err(dev, "Unable to request touchscreen IRQ: %d\n", 219 error); 220 return error; 221 } 222 223 /* 224 * Disable the device for now. It will be enabled once the 225 * input device is opened. 226 */ 227 eeti_ts_stop(eeti); 228 229 error = input_register_device(input); 230 if (error) 231 return error; 232 233 return 0; 234} 235 236static int __maybe_unused eeti_ts_suspend(struct device *dev) 237{ 238 struct i2c_client *client = to_i2c_client(dev); 239 struct eeti_ts *eeti = i2c_get_clientdata(client); 240 struct input_dev *input_dev = eeti->input; 241 242 mutex_lock(&input_dev->mutex); 243 244 if (input_device_enabled(input_dev)) 245 eeti_ts_stop(eeti); 246 247 mutex_unlock(&input_dev->mutex); 248 249 if (device_may_wakeup(&client->dev)) 250 enable_irq_wake(client->irq); 251 252 return 0; 253} 254 255static int __maybe_unused eeti_ts_resume(struct device *dev) 256{ 257 struct i2c_client *client = to_i2c_client(dev); 258 struct eeti_ts *eeti = i2c_get_clientdata(client); 259 struct input_dev *input_dev = eeti->input; 260 261 if (device_may_wakeup(&client->dev)) 262 disable_irq_wake(client->irq); 263 264 mutex_lock(&input_dev->mutex); 265 266 if (input_device_enabled(input_dev)) 267 eeti_ts_start(eeti); 268 269 mutex_unlock(&input_dev->mutex); 270 271 return 0; 272} 273 274static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume); 275 276static const struct i2c_device_id eeti_ts_id[] = { 277 { "eeti_ts", 0 }, 278 { } 279}; 280MODULE_DEVICE_TABLE(i2c, eeti_ts_id); 281 282#ifdef CONFIG_OF 283static const struct of_device_id of_eeti_ts_match[] = { 284 { .compatible = "eeti,exc3000-i2c", }, 285 { } 286}; 287#endif 288 289static struct i2c_driver eeti_ts_driver = { 290 .driver = { 291 .name = "eeti_ts", 292 .pm = &eeti_ts_pm, 293 .of_match_table = of_match_ptr(of_eeti_ts_match), 294 }, 295 .probe = eeti_ts_probe, 296 .id_table = eeti_ts_id, 297}; 298 299module_i2c_driver(eeti_ts_driver); 300 301MODULE_DESCRIPTION("EETI Touchscreen driver"); 302MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>"); 303MODULE_LICENSE("GPL");