1*7e577a17SAhmet Inan /* 2*7e577a17SAhmet Inan * Driver for I2C connected EETI EXC3000 multiple touch controller 3*7e577a17SAhmet Inan * 4*7e577a17SAhmet Inan * Copyright (C) 2017 Ahmet Inan <inan@distec.de> 5*7e577a17SAhmet Inan * 6*7e577a17SAhmet Inan * minimal implementation based on egalax_ts.c and egalax_i2c.c 7*7e577a17SAhmet Inan * 8*7e577a17SAhmet Inan * This program is free software; you can redistribute it and/or modify 9*7e577a17SAhmet Inan * it under the terms of the GNU General Public License version 2 as 10*7e577a17SAhmet Inan * published by the Free Software Foundation. 11*7e577a17SAhmet Inan */ 12*7e577a17SAhmet Inan 13*7e577a17SAhmet Inan #include <linux/bitops.h> 14*7e577a17SAhmet Inan #include <linux/device.h> 15*7e577a17SAhmet Inan #include <linux/i2c.h> 16*7e577a17SAhmet Inan #include <linux/input.h> 17*7e577a17SAhmet Inan #include <linux/input/mt.h> 18*7e577a17SAhmet Inan #include <linux/input/touchscreen.h> 19*7e577a17SAhmet Inan #include <linux/interrupt.h> 20*7e577a17SAhmet Inan #include <linux/module.h> 21*7e577a17SAhmet Inan #include <linux/of.h> 22*7e577a17SAhmet Inan #include <linux/timer.h> 23*7e577a17SAhmet Inan #include <asm/unaligned.h> 24*7e577a17SAhmet Inan 25*7e577a17SAhmet Inan #define EXC3000_NUM_SLOTS 10 26*7e577a17SAhmet Inan #define EXC3000_SLOTS_PER_FRAME 5 27*7e577a17SAhmet Inan #define EXC3000_LEN_FRAME 66 28*7e577a17SAhmet Inan #define EXC3000_LEN_POINT 10 29*7e577a17SAhmet Inan #define EXC3000_MT_EVENT 6 30*7e577a17SAhmet Inan #define EXC3000_TIMEOUT_MS 100 31*7e577a17SAhmet Inan 32*7e577a17SAhmet Inan struct exc3000_data { 33*7e577a17SAhmet Inan struct i2c_client *client; 34*7e577a17SAhmet Inan struct input_dev *input; 35*7e577a17SAhmet Inan struct touchscreen_properties prop; 36*7e577a17SAhmet Inan struct timer_list timer; 37*7e577a17SAhmet Inan u8 buf[2 * EXC3000_LEN_FRAME]; 38*7e577a17SAhmet Inan }; 39*7e577a17SAhmet Inan 40*7e577a17SAhmet Inan static void exc3000_report_slots(struct input_dev *input, 41*7e577a17SAhmet Inan struct touchscreen_properties *prop, 42*7e577a17SAhmet Inan const u8 *buf, int num) 43*7e577a17SAhmet Inan { 44*7e577a17SAhmet Inan for (; num--; buf += EXC3000_LEN_POINT) { 45*7e577a17SAhmet Inan if (buf[0] & BIT(0)) { 46*7e577a17SAhmet Inan input_mt_slot(input, buf[1]); 47*7e577a17SAhmet Inan input_mt_report_slot_state(input, MT_TOOL_FINGER, true); 48*7e577a17SAhmet Inan touchscreen_report_pos(input, prop, 49*7e577a17SAhmet Inan get_unaligned_le16(buf + 2), 50*7e577a17SAhmet Inan get_unaligned_le16(buf + 4), 51*7e577a17SAhmet Inan true); 52*7e577a17SAhmet Inan } 53*7e577a17SAhmet Inan } 54*7e577a17SAhmet Inan } 55*7e577a17SAhmet Inan 56*7e577a17SAhmet Inan static void exc3000_timer(struct timer_list *t) 57*7e577a17SAhmet Inan { 58*7e577a17SAhmet Inan struct exc3000_data *data = from_timer(data, t, timer); 59*7e577a17SAhmet Inan 60*7e577a17SAhmet Inan input_mt_sync_frame(data->input); 61*7e577a17SAhmet Inan input_sync(data->input); 62*7e577a17SAhmet Inan } 63*7e577a17SAhmet Inan 64*7e577a17SAhmet Inan static int exc3000_read_frame(struct i2c_client *client, u8 *buf) 65*7e577a17SAhmet Inan { 66*7e577a17SAhmet Inan int ret; 67*7e577a17SAhmet Inan 68*7e577a17SAhmet Inan ret = i2c_master_send(client, "'", 2); 69*7e577a17SAhmet Inan if (ret < 0) 70*7e577a17SAhmet Inan return ret; 71*7e577a17SAhmet Inan 72*7e577a17SAhmet Inan if (ret != 2) 73*7e577a17SAhmet Inan return -EIO; 74*7e577a17SAhmet Inan 75*7e577a17SAhmet Inan ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME); 76*7e577a17SAhmet Inan if (ret < 0) 77*7e577a17SAhmet Inan return ret; 78*7e577a17SAhmet Inan 79*7e577a17SAhmet Inan if (ret != EXC3000_LEN_FRAME) 80*7e577a17SAhmet Inan return -EIO; 81*7e577a17SAhmet Inan 82*7e577a17SAhmet Inan if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME || 83*7e577a17SAhmet Inan buf[2] != EXC3000_MT_EVENT) 84*7e577a17SAhmet Inan return -EINVAL; 85*7e577a17SAhmet Inan 86*7e577a17SAhmet Inan return 0; 87*7e577a17SAhmet Inan } 88*7e577a17SAhmet Inan 89*7e577a17SAhmet Inan static int exc3000_read_data(struct i2c_client *client, 90*7e577a17SAhmet Inan u8 *buf, int *n_slots) 91*7e577a17SAhmet Inan { 92*7e577a17SAhmet Inan int error; 93*7e577a17SAhmet Inan 94*7e577a17SAhmet Inan error = exc3000_read_frame(client, buf); 95*7e577a17SAhmet Inan if (error) 96*7e577a17SAhmet Inan return error; 97*7e577a17SAhmet Inan 98*7e577a17SAhmet Inan *n_slots = buf[3]; 99*7e577a17SAhmet Inan if (!*n_slots || *n_slots > EXC3000_NUM_SLOTS) 100*7e577a17SAhmet Inan return -EINVAL; 101*7e577a17SAhmet Inan 102*7e577a17SAhmet Inan if (*n_slots > EXC3000_SLOTS_PER_FRAME) { 103*7e577a17SAhmet Inan /* Read 2nd frame to get the rest of the contacts. */ 104*7e577a17SAhmet Inan error = exc3000_read_frame(client, buf + EXC3000_LEN_FRAME); 105*7e577a17SAhmet Inan if (error) 106*7e577a17SAhmet Inan return error; 107*7e577a17SAhmet Inan 108*7e577a17SAhmet Inan /* 2nd chunk must have number of contacts set to 0. */ 109*7e577a17SAhmet Inan if (buf[EXC3000_LEN_FRAME + 3] != 0) 110*7e577a17SAhmet Inan return -EINVAL; 111*7e577a17SAhmet Inan } 112*7e577a17SAhmet Inan 113*7e577a17SAhmet Inan return 0; 114*7e577a17SAhmet Inan } 115*7e577a17SAhmet Inan 116*7e577a17SAhmet Inan static irqreturn_t exc3000_interrupt(int irq, void *dev_id) 117*7e577a17SAhmet Inan { 118*7e577a17SAhmet Inan struct exc3000_data *data = dev_id; 119*7e577a17SAhmet Inan struct input_dev *input = data->input; 120*7e577a17SAhmet Inan u8 *buf = data->buf; 121*7e577a17SAhmet Inan int slots, total_slots; 122*7e577a17SAhmet Inan int error; 123*7e577a17SAhmet Inan 124*7e577a17SAhmet Inan error = exc3000_read_data(data->client, buf, &total_slots); 125*7e577a17SAhmet Inan if (error) { 126*7e577a17SAhmet Inan /* Schedule a timer to release "stuck" contacts */ 127*7e577a17SAhmet Inan mod_timer(&data->timer, 128*7e577a17SAhmet Inan jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS)); 129*7e577a17SAhmet Inan goto out; 130*7e577a17SAhmet Inan } 131*7e577a17SAhmet Inan 132*7e577a17SAhmet Inan /* 133*7e577a17SAhmet Inan * We read full state successfully, no contacts will be "stuck". 134*7e577a17SAhmet Inan */ 135*7e577a17SAhmet Inan del_timer_sync(&data->timer); 136*7e577a17SAhmet Inan 137*7e577a17SAhmet Inan while (total_slots > 0) { 138*7e577a17SAhmet Inan slots = min(total_slots, EXC3000_SLOTS_PER_FRAME); 139*7e577a17SAhmet Inan exc3000_report_slots(input, &data->prop, buf + 4, slots); 140*7e577a17SAhmet Inan total_slots -= slots; 141*7e577a17SAhmet Inan buf += EXC3000_LEN_FRAME; 142*7e577a17SAhmet Inan } 143*7e577a17SAhmet Inan 144*7e577a17SAhmet Inan input_mt_sync_frame(input); 145*7e577a17SAhmet Inan input_sync(input); 146*7e577a17SAhmet Inan 147*7e577a17SAhmet Inan out: 148*7e577a17SAhmet Inan return IRQ_HANDLED; 149*7e577a17SAhmet Inan } 150*7e577a17SAhmet Inan 151*7e577a17SAhmet Inan static int exc3000_probe(struct i2c_client *client, 152*7e577a17SAhmet Inan const struct i2c_device_id *id) 153*7e577a17SAhmet Inan { 154*7e577a17SAhmet Inan struct exc3000_data *data; 155*7e577a17SAhmet Inan struct input_dev *input; 156*7e577a17SAhmet Inan int error; 157*7e577a17SAhmet Inan 158*7e577a17SAhmet Inan data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 159*7e577a17SAhmet Inan if (!data) 160*7e577a17SAhmet Inan return -ENOMEM; 161*7e577a17SAhmet Inan 162*7e577a17SAhmet Inan data->client = client; 163*7e577a17SAhmet Inan timer_setup(&data->timer, exc3000_timer, 0); 164*7e577a17SAhmet Inan 165*7e577a17SAhmet Inan input = devm_input_allocate_device(&client->dev); 166*7e577a17SAhmet Inan if (!input) 167*7e577a17SAhmet Inan return -ENOMEM; 168*7e577a17SAhmet Inan 169*7e577a17SAhmet Inan data->input = input; 170*7e577a17SAhmet Inan 171*7e577a17SAhmet Inan input->name = "EETI EXC3000 Touch Screen"; 172*7e577a17SAhmet Inan input->id.bustype = BUS_I2C; 173*7e577a17SAhmet Inan 174*7e577a17SAhmet Inan input_set_abs_params(input, ABS_MT_POSITION_X, 0, 4095, 0, 0); 175*7e577a17SAhmet Inan input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 4095, 0, 0); 176*7e577a17SAhmet Inan touchscreen_parse_properties(input, true, &data->prop); 177*7e577a17SAhmet Inan 178*7e577a17SAhmet Inan error = input_mt_init_slots(input, EXC3000_NUM_SLOTS, 179*7e577a17SAhmet Inan INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 180*7e577a17SAhmet Inan if (error) 181*7e577a17SAhmet Inan return error; 182*7e577a17SAhmet Inan 183*7e577a17SAhmet Inan error = input_register_device(input); 184*7e577a17SAhmet Inan if (error) 185*7e577a17SAhmet Inan return error; 186*7e577a17SAhmet Inan 187*7e577a17SAhmet Inan error = devm_request_threaded_irq(&client->dev, client->irq, 188*7e577a17SAhmet Inan NULL, exc3000_interrupt, IRQF_ONESHOT, 189*7e577a17SAhmet Inan client->name, data); 190*7e577a17SAhmet Inan if (error) 191*7e577a17SAhmet Inan return error; 192*7e577a17SAhmet Inan 193*7e577a17SAhmet Inan return 0; 194*7e577a17SAhmet Inan } 195*7e577a17SAhmet Inan 196*7e577a17SAhmet Inan static const struct i2c_device_id exc3000_id[] = { 197*7e577a17SAhmet Inan { "exc3000", 0 }, 198*7e577a17SAhmet Inan { } 199*7e577a17SAhmet Inan }; 200*7e577a17SAhmet Inan MODULE_DEVICE_TABLE(i2c, exc3000_id); 201*7e577a17SAhmet Inan 202*7e577a17SAhmet Inan #ifdef CONFIG_OF 203*7e577a17SAhmet Inan static const struct of_device_id exc3000_of_match[] = { 204*7e577a17SAhmet Inan { .compatible = "eeti,exc3000" }, 205*7e577a17SAhmet Inan { } 206*7e577a17SAhmet Inan }; 207*7e577a17SAhmet Inan MODULE_DEVICE_TABLE(of, exc3000_of_match); 208*7e577a17SAhmet Inan #endif 209*7e577a17SAhmet Inan 210*7e577a17SAhmet Inan static struct i2c_driver exc3000_driver = { 211*7e577a17SAhmet Inan .driver = { 212*7e577a17SAhmet Inan .name = "exc3000", 213*7e577a17SAhmet Inan .of_match_table = of_match_ptr(exc3000_of_match), 214*7e577a17SAhmet Inan }, 215*7e577a17SAhmet Inan .id_table = exc3000_id, 216*7e577a17SAhmet Inan .probe = exc3000_probe, 217*7e577a17SAhmet Inan }; 218*7e577a17SAhmet Inan 219*7e577a17SAhmet Inan module_i2c_driver(exc3000_driver); 220*7e577a17SAhmet Inan 221*7e577a17SAhmet Inan MODULE_AUTHOR("Ahmet Inan <inan@distec.de>"); 222*7e577a17SAhmet Inan MODULE_DESCRIPTION("I2C connected EETI EXC3000 multiple touch controller driver"); 223*7e577a17SAhmet Inan MODULE_LICENSE("GPL v2"); 224