Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: pixcir_i2c_ts - support up to 5 fingers and hardware tracking IDs

Some variants of the Pixcir touch controller support up to 5 simultaneous
fingers and hardware tracking IDs. Prepare the driver for that.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Roger Quadros and committed by
Dmitry Torokhov
36874c7e 62e65b7e

+69 -17
+57 -17
drivers/input/touchscreen/pixcir_i2c_ts.c
··· 27 27 #include <linux/input/pixcir_ts.h> 28 28 #include <linux/gpio.h> 29 29 30 - #define PIXCIR_MAX_SLOTS 2 30 + #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ 31 31 32 32 struct pixcir_i2c_ts_data { 33 33 struct i2c_client *client; 34 34 struct input_dev *input; 35 - const struct pixcir_ts_platform_data *chip; 35 + const struct pixcir_ts_platform_data *pdata; 36 36 bool running; 37 + int max_fingers; /* Max fingers supported in this instance */ 37 38 }; 38 39 39 40 struct pixcir_touch { 40 41 int x; 41 42 int y; 43 + int id; 42 44 }; 43 45 44 46 struct pixcir_report_data { ··· 51 49 static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, 52 50 struct pixcir_report_data *report) 53 51 { 54 - u8 rdbuf[10], wrbuf[1] = { 0 }; 52 + u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5]; 53 + u8 wrbuf[1] = { 0 }; 55 54 u8 *bufptr; 56 55 u8 touch; 57 56 int ret, i; 57 + int readsize; 58 + const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip; 58 59 59 60 memset(report, 0, sizeof(struct pixcir_report_data)); 61 + 62 + i = chip->has_hw_ids ? 1 : 0; 63 + readsize = 2 + tsdata->max_fingers * (4 + i); 64 + if (readsize > sizeof(rdbuf)) 65 + readsize = sizeof(rdbuf); 60 66 61 67 ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); 62 68 if (ret != sizeof(wrbuf)) { ··· 74 64 return; 75 65 } 76 66 77 - ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf)); 67 + ret = i2c_master_recv(tsdata->client, rdbuf, readsize); 78 68 if (ret != sizeof(rdbuf)) { 79 69 dev_err(&tsdata->client->dev, 80 70 "%s: i2c_master_recv failed(), ret=%d\n", ··· 83 73 } 84 74 85 75 touch = rdbuf[0] & 0x7; 86 - if (touch > PIXCIR_MAX_SLOTS) 87 - touch = PIXCIR_MAX_SLOTS; 76 + if (touch > tsdata->max_fingers) 77 + touch = tsdata->max_fingers; 88 78 89 79 report->num_touches = touch; 90 80 bufptr = &rdbuf[2]; ··· 93 83 report->touches[i].x = (bufptr[1] << 8) | bufptr[0]; 94 84 report->touches[i].y = (bufptr[3] << 8) | bufptr[2]; 95 85 96 - bufptr = bufptr + 4; 86 + if (chip->has_hw_ids) { 87 + report->touches[i].id = bufptr[4]; 88 + bufptr = bufptr + 5; 89 + } else { 90 + bufptr = bufptr + 4; 91 + } 97 92 } 98 93 } 99 94 ··· 110 95 struct pixcir_touch *touch; 111 96 int n, i, slot; 112 97 struct device *dev = &ts->client->dev; 98 + const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip; 113 99 114 100 n = report->num_touches; 115 101 if (n > PIXCIR_MAX_SLOTS) 116 102 n = PIXCIR_MAX_SLOTS; 117 103 118 - for (i = 0; i < n; i++) { 119 - touch = &report->touches[i]; 120 - pos[i].x = touch->x; 121 - pos[i].y = touch->y; 104 + if (!chip->has_hw_ids) { 105 + for (i = 0; i < n; i++) { 106 + touch = &report->touches[i]; 107 + pos[i].x = touch->x; 108 + pos[i].y = touch->y; 109 + } 110 + 111 + input_mt_assign_slots(ts->input, slots, pos, n); 122 112 } 123 113 124 - input_mt_assign_slots(ts->input, slots, pos, n); 125 - 126 114 for (i = 0; i < n; i++) { 127 115 touch = &report->touches[i]; 128 - slot = slots[i]; 116 + 117 + if (chip->has_hw_ids) { 118 + slot = input_mt_get_slot_by_key(ts->input, touch->id); 119 + if (slot < 0) { 120 + dev_dbg(dev, "no free slot for id 0x%x\n", 121 + touch->id); 122 + continue; 123 + } 124 + } else { 125 + slot = slots[i]; 126 + } 129 127 130 128 input_mt_slot(ts->input, slot); 131 129 input_mt_report_slot_state(ts->input, ··· 158 130 static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) 159 131 { 160 132 struct pixcir_i2c_ts_data *tsdata = dev_id; 161 - const struct pixcir_ts_platform_data *pdata = tsdata->chip; 133 + const struct pixcir_ts_platform_data *pdata = tsdata->pdata; 162 134 struct pixcir_report_data report; 163 135 164 136 while (tsdata->running) { ··· 427 399 return -EINVAL; 428 400 } 429 401 402 + if (!pdata->chip.max_fingers) { 403 + dev_err(dev, "Invalid max_fingers in pdata\n"); 404 + return -EINVAL; 405 + } 406 + 430 407 tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); 431 408 if (!tsdata) 432 409 return -ENOMEM; ··· 444 411 445 412 tsdata->client = client; 446 413 tsdata->input = input; 447 - tsdata->chip = pdata; 414 + tsdata->pdata = pdata; 448 415 449 416 input->name = client->name; 450 417 input->id.bustype = BUS_I2C; ··· 460 427 input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); 461 428 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); 462 429 463 - error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS, 430 + tsdata->max_fingers = tsdata->pdata->chip.max_fingers; 431 + if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) { 432 + tsdata->max_fingers = PIXCIR_MAX_SLOTS; 433 + dev_info(dev, "Limiting maximum fingers to %d\n", 434 + tsdata->max_fingers); 435 + } 436 + 437 + error = input_mt_init_slots(input, tsdata->max_fingers, 464 438 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 465 439 if (error) { 466 440 dev_err(dev, "Error initializing Multi-Touch slots\n");
+12
include/linux/input/pixcir_ts.h
··· 43 43 #define PIXCIR_INT_ENABLE (1UL << 3) 44 44 #define PIXCIR_INT_POL_HIGH (1UL << 2) 45 45 46 + /** 47 + * struct pixcir_irc_chip_data - chip related data 48 + * @max_fingers: Max number of fingers reported simultaneously by h/w 49 + * @has_hw_ids: Hardware supports finger tracking IDs 50 + * 51 + */ 52 + struct pixcir_i2c_chip_data { 53 + u8 max_fingers; 54 + bool has_hw_ids; 55 + }; 56 + 46 57 struct pixcir_ts_platform_data { 47 58 int x_max; 48 59 int y_max; 49 60 int gpio_attb; /* GPIO connected to ATTB line */ 61 + struct pixcir_i2c_chip_data chip; 50 62 }; 51 63 52 64 #endif