imagis.c (8750B)
1// SPDX-License-Identifier: GPL-2.0-only 2 3#include <linux/bits.h> 4#include <linux/delay.h> 5#include <linux/i2c.h> 6#include <linux/input.h> 7#include <linux/input/mt.h> 8#include <linux/input/touchscreen.h> 9#include <linux/kernel.h> 10#include <linux/module.h> 11#include <linux/property.h> 12#include <linux/regulator/consumer.h> 13 14#define IST3038C_HIB_ACCESS (0x800B << 16) 15#define IST3038C_DIRECT_ACCESS BIT(31) 16#define IST3038C_REG_CHIPID 0x40001000 17#define IST3038C_REG_HIB_BASE 0x30000100 18#define IST3038C_REG_TOUCH_STATUS (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS) 19#define IST3038C_REG_TOUCH_COORD (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x8) 20#define IST3038C_REG_INTR_MESSAGE (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x4) 21#define IST3038C_WHOAMI 0x38c 22#define IST3038C_CHIP_ON_DELAY_MS 60 23#define IST3038C_I2C_RETRY_COUNT 3 24#define IST3038C_MAX_FINGER_NUM 10 25#define IST3038C_X_MASK GENMASK(23, 12) 26#define IST3038C_X_SHIFT 12 27#define IST3038C_Y_MASK GENMASK(11, 0) 28#define IST3038C_AREA_MASK GENMASK(27, 24) 29#define IST3038C_AREA_SHIFT 24 30#define IST3038C_FINGER_COUNT_MASK GENMASK(15, 12) 31#define IST3038C_FINGER_COUNT_SHIFT 12 32#define IST3038C_FINGER_STATUS_MASK GENMASK(9, 0) 33 34struct imagis_ts { 35 struct i2c_client *client; 36 struct input_dev *input_dev; 37 struct touchscreen_properties prop; 38 struct regulator_bulk_data supplies[2]; 39}; 40 41static int imagis_i2c_read_reg(struct imagis_ts *ts, 42 unsigned int reg, u32 *data) 43{ 44 __be32 ret_be; 45 __be32 reg_be = cpu_to_be32(reg); 46 struct i2c_msg msg[] = { 47 { 48 .addr = ts->client->addr, 49 .flags = 0, 50 .buf = (unsigned char *)®_be, 51 .len = sizeof(reg_be), 52 }, { 53 .addr = ts->client->addr, 54 .flags = I2C_M_RD, 55 .buf = (unsigned char *)&ret_be, 56 .len = sizeof(ret_be), 57 }, 58 }; 59 int ret, error; 60 int retry = IST3038C_I2C_RETRY_COUNT; 61 62 /* Retry in case the controller fails to respond */ 63 do { 64 ret = i2c_transfer(ts->client->adapter, msg, ARRAY_SIZE(msg)); 65 if (ret == ARRAY_SIZE(msg)) { 66 *data = be32_to_cpu(ret_be); 67 return 0; 68 } 69 70 error = ret < 0 ? ret : -EIO; 71 dev_err(&ts->client->dev, 72 "%s - i2c_transfer failed: %d (%d)\n", 73 __func__, error, ret); 74 } while (--retry); 75 76 return error; 77} 78 79static irqreturn_t imagis_interrupt(int irq, void *dev_id) 80{ 81 struct imagis_ts *ts = dev_id; 82 u32 intr_message, finger_status; 83 unsigned int finger_count, finger_pressed; 84 int i; 85 int error; 86 87 error = imagis_i2c_read_reg(ts, IST3038C_REG_INTR_MESSAGE, 88 &intr_message); 89 if (error) { 90 dev_err(&ts->client->dev, 91 "failed to read the interrupt message: %d\n", error); 92 goto out; 93 } 94 95 finger_count = (intr_message & IST3038C_FINGER_COUNT_MASK) >> 96 IST3038C_FINGER_COUNT_SHIFT; 97 if (finger_count > IST3038C_MAX_FINGER_NUM) { 98 dev_err(&ts->client->dev, 99 "finger count %d is more than maximum supported\n", 100 finger_count); 101 goto out; 102 } 103 104 finger_pressed = intr_message & IST3038C_FINGER_STATUS_MASK; 105 106 for (i = 0; i < finger_count; i++) { 107 error = imagis_i2c_read_reg(ts, 108 IST3038C_REG_TOUCH_COORD + (i * 4), 109 &finger_status); 110 if (error) { 111 dev_err(&ts->client->dev, 112 "failed to read coordinates for finger %d: %d\n", 113 i, error); 114 goto out; 115 } 116 117 input_mt_slot(ts->input_dev, i); 118 input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 119 finger_pressed & BIT(i)); 120 touchscreen_report_pos(ts->input_dev, &ts->prop, 121 (finger_status & IST3038C_X_MASK) >> 122 IST3038C_X_SHIFT, 123 finger_status & IST3038C_Y_MASK, 1); 124 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 125 (finger_status & IST3038C_AREA_MASK) >> 126 IST3038C_AREA_SHIFT); 127 } 128 129 input_mt_sync_frame(ts->input_dev); 130 input_sync(ts->input_dev); 131 132out: 133 return IRQ_HANDLED; 134} 135 136static void imagis_power_off(void *_ts) 137{ 138 struct imagis_ts *ts = _ts; 139 140 regulator_bulk_disable(ARRAY_SIZE(ts->supplies), ts->supplies); 141} 142 143static int imagis_power_on(struct imagis_ts *ts) 144{ 145 int error; 146 147 error = regulator_bulk_enable(ARRAY_SIZE(ts->supplies), ts->supplies); 148 if (error) 149 return error; 150 151 msleep(IST3038C_CHIP_ON_DELAY_MS); 152 153 return 0; 154} 155 156static int imagis_start(struct imagis_ts *ts) 157{ 158 int error; 159 160 error = imagis_power_on(ts); 161 if (error) 162 return error; 163 164 enable_irq(ts->client->irq); 165 166 return 0; 167} 168 169static int imagis_stop(struct imagis_ts *ts) 170{ 171 disable_irq(ts->client->irq); 172 173 imagis_power_off(ts); 174 175 return 0; 176} 177 178static int imagis_input_open(struct input_dev *dev) 179{ 180 struct imagis_ts *ts = input_get_drvdata(dev); 181 182 return imagis_start(ts); 183} 184 185static void imagis_input_close(struct input_dev *dev) 186{ 187 struct imagis_ts *ts = input_get_drvdata(dev); 188 189 imagis_stop(ts); 190} 191 192static int imagis_init_input_dev(struct imagis_ts *ts) 193{ 194 struct input_dev *input_dev; 195 int error; 196 197 input_dev = devm_input_allocate_device(&ts->client->dev); 198 if (!input_dev) 199 return -ENOMEM; 200 201 ts->input_dev = input_dev; 202 203 input_dev->name = "Imagis capacitive touchscreen"; 204 input_dev->phys = "input/ts"; 205 input_dev->id.bustype = BUS_I2C; 206 input_dev->open = imagis_input_open; 207 input_dev->close = imagis_input_close; 208 209 input_set_drvdata(input_dev, ts); 210 211 input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); 212 input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); 213 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); 214 215 touchscreen_parse_properties(input_dev, true, &ts->prop); 216 if (!ts->prop.max_x || !ts->prop.max_y) { 217 dev_err(&ts->client->dev, 218 "Touchscreen-size-x and/or touchscreen-size-y not set in dts\n"); 219 return -EINVAL; 220 } 221 222 error = input_mt_init_slots(input_dev, 223 IST3038C_MAX_FINGER_NUM, 224 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 225 if (error) { 226 dev_err(&ts->client->dev, 227 "Failed to initialize MT slots: %d", error); 228 return error; 229 } 230 231 error = input_register_device(input_dev); 232 if (error) { 233 dev_err(&ts->client->dev, 234 "Failed to register input device: %d", error); 235 return error; 236 } 237 238 return 0; 239} 240 241static int imagis_init_regulators(struct imagis_ts *ts) 242{ 243 struct i2c_client *client = ts->client; 244 245 ts->supplies[0].supply = "vdd"; 246 ts->supplies[1].supply = "vddio"; 247 return devm_regulator_bulk_get(&client->dev, 248 ARRAY_SIZE(ts->supplies), 249 ts->supplies); 250} 251 252static int imagis_probe(struct i2c_client *i2c) 253{ 254 struct device *dev = &i2c->dev; 255 struct imagis_ts *ts; 256 int chip_id, error; 257 258 ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); 259 if (!ts) 260 return -ENOMEM; 261 262 ts->client = i2c; 263 264 error = imagis_init_regulators(ts); 265 if (error) { 266 dev_err(dev, "regulator init error: %d\n", error); 267 return error; 268 } 269 270 error = imagis_power_on(ts); 271 if (error) { 272 dev_err(dev, "failed to enable regulators: %d\n", error); 273 return error; 274 } 275 276 error = devm_add_action_or_reset(dev, imagis_power_off, ts); 277 if (error) { 278 dev_err(dev, "failed to install poweroff action: %d\n", error); 279 return error; 280 } 281 282 error = imagis_i2c_read_reg(ts, 283 IST3038C_REG_CHIPID | IST3038C_DIRECT_ACCESS, 284 &chip_id); 285 if (error) { 286 dev_err(dev, "chip ID read failure: %d\n", error); 287 return error; 288 } 289 290 if (chip_id != IST3038C_WHOAMI) { 291 dev_err(dev, "unknown chip ID: 0x%x\n", chip_id); 292 return -EINVAL; 293 } 294 295 error = devm_request_threaded_irq(dev, i2c->irq, 296 NULL, imagis_interrupt, 297 IRQF_ONESHOT | IRQF_NO_AUTOEN, 298 "imagis-touchscreen", ts); 299 if (error) { 300 dev_err(dev, "IRQ %d allocation failure: %d\n", 301 i2c->irq, error); 302 return error; 303 } 304 305 error = imagis_init_input_dev(ts); 306 if (error) 307 return error; 308 309 return 0; 310} 311 312static int __maybe_unused imagis_suspend(struct device *dev) 313{ 314 struct i2c_client *client = to_i2c_client(dev); 315 struct imagis_ts *ts = i2c_get_clientdata(client); 316 int retval = 0; 317 318 mutex_lock(&ts->input_dev->mutex); 319 320 if (input_device_enabled(ts->input_dev)) 321 retval = imagis_stop(ts); 322 323 mutex_unlock(&ts->input_dev->mutex); 324 325 return retval; 326} 327 328static int __maybe_unused imagis_resume(struct device *dev) 329{ 330 struct i2c_client *client = to_i2c_client(dev); 331 struct imagis_ts *ts = i2c_get_clientdata(client); 332 int retval = 0; 333 334 mutex_lock(&ts->input_dev->mutex); 335 336 if (input_device_enabled(ts->input_dev)) 337 retval = imagis_start(ts); 338 339 mutex_unlock(&ts->input_dev->mutex); 340 341 return retval; 342} 343 344static SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume); 345 346#ifdef CONFIG_OF 347static const struct of_device_id imagis_of_match[] = { 348 { .compatible = "imagis,ist3038c", }, 349 { }, 350}; 351MODULE_DEVICE_TABLE(of, imagis_of_match); 352#endif 353 354static struct i2c_driver imagis_ts_driver = { 355 .driver = { 356 .name = "imagis-touchscreen", 357 .pm = &imagis_pm_ops, 358 .of_match_table = of_match_ptr(imagis_of_match), 359 }, 360 .probe_new = imagis_probe, 361}; 362 363module_i2c_driver(imagis_ts_driver); 364 365MODULE_DESCRIPTION("Imagis IST3038C Touchscreen Driver"); 366MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>"); 367MODULE_LICENSE("GPL");