^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * TSC-40 serial touchscreen driver. It should be compatible with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * TSC-10 and 25.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define PACKET_LENGTH 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct tsc_ser {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) u32 idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned char data[PACKET_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) char phys[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void tsc_process_data(struct tsc_ser *ptsc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct input_dev *dev = ptsc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u8 *data = ptsc->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u32 x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u32 y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) x = ((data[1] & 0x03) << 8) | data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) y = ((data[3] & 0x03) << 8) | data[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) input_report_abs(dev, ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) input_report_abs(dev, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) input_report_key(dev, BTN_TOUCH, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static irqreturn_t tsc_interrupt(struct serio *serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned char data, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct tsc_ser *ptsc = serio_get_drvdata(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct input_dev *dev = ptsc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ptsc->data[ptsc->idx] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) switch (ptsc->idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (unlikely((data & 0x3e) != 0x10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dev_dbg(&serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "unsynchronized packet start (0x%02x)\n", data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ptsc->idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) } else if (!(data & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) input_report_key(dev, BTN_TOUCH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ptsc->idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (unlikely(data & 0xfc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dev_dbg(&serio->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) "unsynchronized data 0x%02x at offset %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) data, ptsc->idx - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ptsc->idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) tsc_process_data(ptsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ptsc->idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int tsc_connect(struct serio *serio, struct serio_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct tsc_ser *ptsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!ptsc || !input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) ptsc->serio = serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ptsc->dev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) input_dev->name = "TSC-10/25/40 Serial TouchScreen";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) input_dev->phys = ptsc->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) input_dev->id.bustype = BUS_RS232;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) input_dev->id.vendor = SERIO_TSC40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) input_dev->id.product = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) input_dev->id.version = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) input_dev->dev.parent = &serio->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) __set_bit(BTN_TOUCH, input_dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) serio_set_drvdata(serio, ptsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) error = serio_open(serio, drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) goto fail2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) error = input_register_device(ptsc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) goto fail3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) fail3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) serio_close(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) fail2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) input_free_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) kfree(ptsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void tsc_disconnect(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct tsc_ser *ptsc = serio_get_drvdata(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) serio_close(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) input_unregister_device(ptsc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) kfree(ptsc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const struct serio_device_id tsc_serio_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .type = SERIO_RS232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .proto = SERIO_TSC40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .id = SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .extra = SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) MODULE_DEVICE_TABLE(serio, tsc_serio_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define DRIVER_DESC "TSC-10/25/40 serial touchscreen driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static struct serio_driver tsc_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .name = "tsc40",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .description = DRIVER_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .id_table = tsc_serio_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .interrupt = tsc_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .connect = tsc_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .disconnect = tsc_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) module_serio_driver(tsc_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) MODULE_LICENSE("GPL v2");