12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2a93ad65dSHans de Goede /* 3a93ad65dSHans de Goede * Driver for ChipOne icn8318 i2c touchscreen controller 4a93ad65dSHans de Goede * 5a93ad65dSHans de Goede * Copyright (c) 2015 Red Hat Inc. 6a93ad65dSHans de Goede * 7a93ad65dSHans de Goede * Red Hat authors: 8a93ad65dSHans de Goede * Hans de Goede <hdegoede@redhat.com> 9a93ad65dSHans de Goede */ 10a93ad65dSHans de Goede 11a93ad65dSHans de Goede #include <linux/gpio/consumer.h> 12a93ad65dSHans de Goede #include <linux/interrupt.h> 13a93ad65dSHans de Goede #include <linux/i2c.h> 14a93ad65dSHans de Goede #include <linux/input.h> 15a93ad65dSHans de Goede #include <linux/input/mt.h> 1650dd9f66SHans de Goede #include <linux/input/touchscreen.h> 17a93ad65dSHans de Goede #include <linux/module.h> 18a93ad65dSHans de Goede #include <linux/of.h> 19a93ad65dSHans de Goede 20a93ad65dSHans de Goede #define ICN8318_REG_POWER 4 21a93ad65dSHans de Goede #define ICN8318_REG_TOUCHDATA 16 22a93ad65dSHans de Goede 23a93ad65dSHans de Goede #define ICN8318_POWER_ACTIVE 0 24a93ad65dSHans de Goede #define ICN8318_POWER_MONITOR 1 25a93ad65dSHans de Goede #define ICN8318_POWER_HIBERNATE 2 26a93ad65dSHans de Goede 27a93ad65dSHans de Goede #define ICN8318_MAX_TOUCHES 5 28a93ad65dSHans de Goede 29a93ad65dSHans de Goede struct icn8318_touch { 30a93ad65dSHans de Goede __u8 slot; 31a93ad65dSHans de Goede __be16 x; 32a93ad65dSHans de Goede __be16 y; 33a93ad65dSHans de Goede __u8 pressure; /* Seems more like finger width then pressure really */ 34a93ad65dSHans de Goede __u8 event; 35a93ad65dSHans de Goede /* The difference between 2 and 3 is unclear */ 36a93ad65dSHans de Goede #define ICN8318_EVENT_NO_DATA 1 /* No finger seen yet since wakeup */ 37a93ad65dSHans de Goede #define ICN8318_EVENT_UPDATE1 2 /* New or updated coordinates */ 38a93ad65dSHans de Goede #define ICN8318_EVENT_UPDATE2 3 /* New or updated coordinates */ 39a93ad65dSHans de Goede #define ICN8318_EVENT_END 4 /* Finger lifted */ 40a93ad65dSHans de Goede } __packed; 41a93ad65dSHans de Goede 42a93ad65dSHans de Goede struct icn8318_touch_data { 43a93ad65dSHans de Goede __u8 softbutton; 44a93ad65dSHans de Goede __u8 touch_count; 45a93ad65dSHans de Goede struct icn8318_touch touches[ICN8318_MAX_TOUCHES]; 46a93ad65dSHans de Goede } __packed; 47a93ad65dSHans de Goede 48a93ad65dSHans de Goede struct icn8318_data { 49a93ad65dSHans de Goede struct i2c_client *client; 50a93ad65dSHans de Goede struct input_dev *input; 51a93ad65dSHans de Goede struct gpio_desc *wake_gpio; 5250dd9f66SHans de Goede struct touchscreen_properties prop; 53a93ad65dSHans de Goede }; 54a93ad65dSHans de Goede 55a93ad65dSHans de Goede static int icn8318_read_touch_data(struct i2c_client *client, 56a93ad65dSHans de Goede struct icn8318_touch_data *touch_data) 57a93ad65dSHans de Goede { 58a93ad65dSHans de Goede u8 reg = ICN8318_REG_TOUCHDATA; 59a93ad65dSHans de Goede struct i2c_msg msg[2] = { 60a93ad65dSHans de Goede { 61a93ad65dSHans de Goede .addr = client->addr, 62a93ad65dSHans de Goede .len = 1, 63a93ad65dSHans de Goede .buf = ® 64a93ad65dSHans de Goede }, 65a93ad65dSHans de Goede { 66a93ad65dSHans de Goede .addr = client->addr, 67a93ad65dSHans de Goede .flags = I2C_M_RD, 68a93ad65dSHans de Goede .len = sizeof(struct icn8318_touch_data), 69a93ad65dSHans de Goede .buf = (u8 *)touch_data 70a93ad65dSHans de Goede } 71a93ad65dSHans de Goede }; 72a93ad65dSHans de Goede 73a93ad65dSHans de Goede return i2c_transfer(client->adapter, msg, 2); 74a93ad65dSHans de Goede } 75a93ad65dSHans de Goede 76a93ad65dSHans de Goede static inline bool icn8318_touch_active(u8 event) 77a93ad65dSHans de Goede { 78a93ad65dSHans de Goede return (event == ICN8318_EVENT_UPDATE1) || 79a93ad65dSHans de Goede (event == ICN8318_EVENT_UPDATE2); 80a93ad65dSHans de Goede } 81a93ad65dSHans de Goede 82a93ad65dSHans de Goede static irqreturn_t icn8318_irq(int irq, void *dev_id) 83a93ad65dSHans de Goede { 84a93ad65dSHans de Goede struct icn8318_data *data = dev_id; 85a93ad65dSHans de Goede struct device *dev = &data->client->dev; 86a93ad65dSHans de Goede struct icn8318_touch_data touch_data; 8750dd9f66SHans de Goede int i, ret; 88a93ad65dSHans de Goede 89a93ad65dSHans de Goede ret = icn8318_read_touch_data(data->client, &touch_data); 90a93ad65dSHans de Goede if (ret < 0) { 91a93ad65dSHans de Goede dev_err(dev, "Error reading touch data: %d\n", ret); 92a93ad65dSHans de Goede return IRQ_HANDLED; 93a93ad65dSHans de Goede } 94a93ad65dSHans de Goede 95a93ad65dSHans de Goede if (touch_data.softbutton) { 96a93ad65dSHans de Goede /* 97a93ad65dSHans de Goede * Other data is invalid when a softbutton is pressed. 98a93ad65dSHans de Goede * This needs some extra devicetree bindings to map the icn8318 99a93ad65dSHans de Goede * softbutton codes to evdev codes. Currently no known devices 100a93ad65dSHans de Goede * use this. 101a93ad65dSHans de Goede */ 102a93ad65dSHans de Goede return IRQ_HANDLED; 103a93ad65dSHans de Goede } 104a93ad65dSHans de Goede 105a93ad65dSHans de Goede if (touch_data.touch_count > ICN8318_MAX_TOUCHES) { 106a93ad65dSHans de Goede dev_warn(dev, "Too much touches %d > %d\n", 107a93ad65dSHans de Goede touch_data.touch_count, ICN8318_MAX_TOUCHES); 108a93ad65dSHans de Goede touch_data.touch_count = ICN8318_MAX_TOUCHES; 109a93ad65dSHans de Goede } 110a93ad65dSHans de Goede 111a93ad65dSHans de Goede for (i = 0; i < touch_data.touch_count; i++) { 112a93ad65dSHans de Goede struct icn8318_touch *touch = &touch_data.touches[i]; 113a93ad65dSHans de Goede bool act = icn8318_touch_active(touch->event); 114a93ad65dSHans de Goede 115a93ad65dSHans de Goede input_mt_slot(data->input, touch->slot); 116a93ad65dSHans de Goede input_mt_report_slot_state(data->input, MT_TOOL_FINGER, act); 117a93ad65dSHans de Goede if (!act) 118a93ad65dSHans de Goede continue; 119a93ad65dSHans de Goede 12050dd9f66SHans de Goede touchscreen_report_pos(data->input, &data->prop, 12150dd9f66SHans de Goede be16_to_cpu(touch->x), 12250dd9f66SHans de Goede be16_to_cpu(touch->y), true); 123a93ad65dSHans de Goede } 124a93ad65dSHans de Goede 125a93ad65dSHans de Goede input_mt_sync_frame(data->input); 126a93ad65dSHans de Goede input_sync(data->input); 127a93ad65dSHans de Goede 128a93ad65dSHans de Goede return IRQ_HANDLED; 129a93ad65dSHans de Goede } 130a93ad65dSHans de Goede 131a93ad65dSHans de Goede static int icn8318_start(struct input_dev *dev) 132a93ad65dSHans de Goede { 133a93ad65dSHans de Goede struct icn8318_data *data = input_get_drvdata(dev); 134a93ad65dSHans de Goede 135a93ad65dSHans de Goede enable_irq(data->client->irq); 136a93ad65dSHans de Goede gpiod_set_value_cansleep(data->wake_gpio, 1); 137a93ad65dSHans de Goede 138a93ad65dSHans de Goede return 0; 139a93ad65dSHans de Goede } 140a93ad65dSHans de Goede 141a93ad65dSHans de Goede static void icn8318_stop(struct input_dev *dev) 142a93ad65dSHans de Goede { 143a93ad65dSHans de Goede struct icn8318_data *data = input_get_drvdata(dev); 144a93ad65dSHans de Goede 145a93ad65dSHans de Goede disable_irq(data->client->irq); 146a93ad65dSHans de Goede i2c_smbus_write_byte_data(data->client, ICN8318_REG_POWER, 147a93ad65dSHans de Goede ICN8318_POWER_HIBERNATE); 148a93ad65dSHans de Goede gpiod_set_value_cansleep(data->wake_gpio, 0); 149a93ad65dSHans de Goede } 150a93ad65dSHans de Goede 151a93ad65dSHans de Goede #ifdef CONFIG_PM_SLEEP 152a93ad65dSHans de Goede static int icn8318_suspend(struct device *dev) 153a93ad65dSHans de Goede { 154a93ad65dSHans de Goede struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev)); 155a93ad65dSHans de Goede 156a93ad65dSHans de Goede mutex_lock(&data->input->mutex); 157*d69f0a43SAndrzej Pietrasiewicz if (input_device_enabled(data->input)) 158a93ad65dSHans de Goede icn8318_stop(data->input); 159a93ad65dSHans de Goede mutex_unlock(&data->input->mutex); 160a93ad65dSHans de Goede 161a93ad65dSHans de Goede return 0; 162a93ad65dSHans de Goede } 163a93ad65dSHans de Goede 164a93ad65dSHans de Goede static int icn8318_resume(struct device *dev) 165a93ad65dSHans de Goede { 166a93ad65dSHans de Goede struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev)); 167a93ad65dSHans de Goede 168a93ad65dSHans de Goede mutex_lock(&data->input->mutex); 169*d69f0a43SAndrzej Pietrasiewicz if (input_device_enabled(data->input)) 170a93ad65dSHans de Goede icn8318_start(data->input); 171a93ad65dSHans de Goede mutex_unlock(&data->input->mutex); 172a93ad65dSHans de Goede 173a93ad65dSHans de Goede return 0; 174a93ad65dSHans de Goede } 175a93ad65dSHans de Goede #endif 176a93ad65dSHans de Goede 177a93ad65dSHans de Goede static SIMPLE_DEV_PM_OPS(icn8318_pm_ops, icn8318_suspend, icn8318_resume); 178a93ad65dSHans de Goede 179a93ad65dSHans de Goede static int icn8318_probe(struct i2c_client *client, 180a93ad65dSHans de Goede const struct i2c_device_id *id) 181a93ad65dSHans de Goede { 182a93ad65dSHans de Goede struct device *dev = &client->dev; 183a93ad65dSHans de Goede struct icn8318_data *data; 184a93ad65dSHans de Goede struct input_dev *input; 185a93ad65dSHans de Goede int error; 186a93ad65dSHans de Goede 187a93ad65dSHans de Goede if (!client->irq) { 188a93ad65dSHans de Goede dev_err(dev, "Error no irq specified\n"); 189a93ad65dSHans de Goede return -EINVAL; 190a93ad65dSHans de Goede } 191a93ad65dSHans de Goede 192a93ad65dSHans de Goede data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 193a93ad65dSHans de Goede if (!data) 194a93ad65dSHans de Goede return -ENOMEM; 195a93ad65dSHans de Goede 196a93ad65dSHans de Goede data->wake_gpio = devm_gpiod_get(dev, "wake", GPIOD_OUT_LOW); 197a93ad65dSHans de Goede if (IS_ERR(data->wake_gpio)) { 198a93ad65dSHans de Goede error = PTR_ERR(data->wake_gpio); 199a93ad65dSHans de Goede if (error != -EPROBE_DEFER) 200a93ad65dSHans de Goede dev_err(dev, "Error getting wake gpio: %d\n", error); 201a93ad65dSHans de Goede return error; 202a93ad65dSHans de Goede } 203a93ad65dSHans de Goede 204a93ad65dSHans de Goede input = devm_input_allocate_device(dev); 205a93ad65dSHans de Goede if (!input) 206a93ad65dSHans de Goede return -ENOMEM; 207a93ad65dSHans de Goede 208a93ad65dSHans de Goede input->name = client->name; 209a93ad65dSHans de Goede input->id.bustype = BUS_I2C; 210a93ad65dSHans de Goede input->open = icn8318_start; 211a93ad65dSHans de Goede input->close = icn8318_stop; 212a93ad65dSHans de Goede input->dev.parent = dev; 213a93ad65dSHans de Goede 21450dd9f66SHans de Goede input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); 21550dd9f66SHans de Goede input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); 21650dd9f66SHans de Goede 21750dd9f66SHans de Goede touchscreen_parse_properties(input, true, &data->prop); 21850dd9f66SHans de Goede if (!input_abs_get_max(input, ABS_MT_POSITION_X) || 21950dd9f66SHans de Goede !input_abs_get_max(input, ABS_MT_POSITION_Y)) { 22050dd9f66SHans de Goede dev_err(dev, "Error touchscreen-size-x and/or -y missing\n"); 22150dd9f66SHans de Goede return -EINVAL; 222a93ad65dSHans de Goede } 223a93ad65dSHans de Goede 224a93ad65dSHans de Goede error = input_mt_init_slots(input, ICN8318_MAX_TOUCHES, 225a93ad65dSHans de Goede INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 226a93ad65dSHans de Goede if (error) 227a93ad65dSHans de Goede return error; 228a93ad65dSHans de Goede 229a93ad65dSHans de Goede data->client = client; 230a93ad65dSHans de Goede data->input = input; 231a93ad65dSHans de Goede input_set_drvdata(input, data); 232a93ad65dSHans de Goede 233a93ad65dSHans de Goede error = devm_request_threaded_irq(dev, client->irq, NULL, icn8318_irq, 234a93ad65dSHans de Goede IRQF_ONESHOT, client->name, data); 235a93ad65dSHans de Goede if (error) { 236a93ad65dSHans de Goede dev_err(dev, "Error requesting irq: %d\n", error); 237a93ad65dSHans de Goede return error; 238a93ad65dSHans de Goede } 239a93ad65dSHans de Goede 240a93ad65dSHans de Goede /* Stop device till opened */ 241a93ad65dSHans de Goede icn8318_stop(data->input); 242a93ad65dSHans de Goede 243a93ad65dSHans de Goede error = input_register_device(input); 244a93ad65dSHans de Goede if (error) 245a93ad65dSHans de Goede return error; 246a93ad65dSHans de Goede 247a93ad65dSHans de Goede i2c_set_clientdata(client, data); 248a93ad65dSHans de Goede 249a93ad65dSHans de Goede return 0; 250a93ad65dSHans de Goede } 251a93ad65dSHans de Goede 252a93ad65dSHans de Goede static const struct of_device_id icn8318_of_match[] = { 253a93ad65dSHans de Goede { .compatible = "chipone,icn8318" }, 254a93ad65dSHans de Goede { } 255a93ad65dSHans de Goede }; 256a93ad65dSHans de Goede MODULE_DEVICE_TABLE(of, icn8318_of_match); 257a93ad65dSHans de Goede 258a93ad65dSHans de Goede /* This is useless for OF-enabled devices, but it is needed by I2C subsystem */ 259a93ad65dSHans de Goede static const struct i2c_device_id icn8318_i2c_id[] = { 260a93ad65dSHans de Goede { }, 261a93ad65dSHans de Goede }; 262a93ad65dSHans de Goede MODULE_DEVICE_TABLE(i2c, icn8318_i2c_id); 263a93ad65dSHans de Goede 264a93ad65dSHans de Goede static struct i2c_driver icn8318_driver = { 265a93ad65dSHans de Goede .driver = { 266a93ad65dSHans de Goede .name = "chipone_icn8318", 267a93ad65dSHans de Goede .pm = &icn8318_pm_ops, 268a93ad65dSHans de Goede .of_match_table = icn8318_of_match, 269a93ad65dSHans de Goede }, 270a93ad65dSHans de Goede .probe = icn8318_probe, 271a93ad65dSHans de Goede .id_table = icn8318_i2c_id, 272a93ad65dSHans de Goede }; 273a93ad65dSHans de Goede 274a93ad65dSHans de Goede module_i2c_driver(icn8318_driver); 275a93ad65dSHans de Goede 276a93ad65dSHans de Goede MODULE_DESCRIPTION("ChipOne icn8318 I2C Touchscreen Driver"); 277a93ad65dSHans de Goede MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 278a93ad65dSHans de Goede MODULE_LICENSE("GPL"); 279