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

Input: st1232 - switch to using MT-B protocol

Switch the driver to the slotted variant of multitouch protocol (MT-B)
with in-kernel tracking of the contacts.

Tested-by: Matthias Fend <Matthias.Fend@wolfvision.net>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+56 -54
+56 -54
drivers/input/touchscreen/st1232.c
··· 14 14 #include <linux/gpio/consumer.h> 15 15 #include <linux/i2c.h> 16 16 #include <linux/input.h> 17 + #include <linux/input/mt.h> 18 + #include <linux/input/touchscreen.h> 17 19 #include <linux/interrupt.h> 18 20 #include <linux/module.h> 19 21 #include <linux/of.h> 20 22 #include <linux/pm_qos.h> 21 23 #include <linux/slab.h> 22 24 #include <linux/types.h> 23 - #include <linux/input/touchscreen.h> 24 25 25 26 #define ST1232_TS_NAME "st1232-ts" 26 27 #define ST1633_TS_NAME "st1633-ts" 27 28 28 - struct st1232_ts_finger { 29 - u16 x; 30 - u16 y; 31 - u8 t; 32 - bool is_valid; 33 - }; 29 + #define ST_TS_MAX_FINGERS 10 34 30 35 31 struct st_chip_info { 36 32 bool have_z; ··· 46 50 const struct st_chip_info *chip_info; 47 51 int read_buf_len; 48 52 u8 *read_buf; 49 - struct st1232_ts_finger fingers[]; 50 53 }; 51 54 52 55 static int st1232_ts_read_data(struct st1232_ts_data *ts) 53 56 { 54 - struct st1232_ts_finger *finger = ts->fingers; 55 57 struct i2c_client *client = ts->client; 56 58 u8 start_reg = ts->chip_info->start_reg; 57 59 struct i2c_msg msg[] = { ··· 66 72 } 67 73 }; 68 74 int ret; 69 - int i; 70 - u8 *buf; 71 75 72 76 ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 73 77 if (ret != ARRAY_SIZE(msg)) 74 78 return ret < 0 ? ret : -EIO; 75 79 80 + return 0; 81 + } 82 + 83 + static int st1232_ts_parse_and_report(struct st1232_ts_data *ts) 84 + { 85 + struct input_dev *input = ts->input_dev; 86 + struct input_mt_pos pos[ST_TS_MAX_FINGERS]; 87 + u8 z[ST_TS_MAX_FINGERS]; 88 + int slots[ST_TS_MAX_FINGERS]; 89 + int n_contacts = 0; 90 + int i; 91 + 76 92 for (i = 0; i < ts->chip_info->max_fingers; i++) { 77 - buf = &ts->read_buf[i * 4]; 78 - finger[i].is_valid = buf[0] >> 7; 79 - if (finger[i].is_valid) { 80 - finger[i].x = ((buf[0] & 0x70) << 4) | buf[1]; 81 - finger[i].y = ((buf[0] & 0x07) << 8) | buf[2]; 93 + u8 *buf = &ts->read_buf[i * 4]; 94 + 95 + if (buf[0] & BIT(7)) { 96 + unsigned int x = ((buf[0] & 0x70) << 4) | buf[1]; 97 + unsigned int y = ((buf[0] & 0x07) << 8) | buf[2]; 98 + 99 + touchscreen_set_mt_pos(&pos[n_contacts], 100 + &ts->prop, x, y); 82 101 83 102 /* st1232 includes a z-axis / touch strength */ 84 103 if (ts->chip_info->have_z) 85 - finger[i].t = ts->read_buf[i + 6]; 104 + z[n_contacts] = ts->read_buf[i + 6]; 105 + 106 + n_contacts++; 86 107 } 87 108 } 88 109 89 - return 0; 110 + input_mt_assign_slots(input, slots, pos, n_contacts, 0); 111 + for (i = 0; i < n_contacts; i++) { 112 + input_mt_slot(input, slots[i]); 113 + input_mt_report_slot_state(input, MT_TOOL_FINGER, true); 114 + input_report_abs(input, ABS_MT_POSITION_X, pos[i].x); 115 + input_report_abs(input, ABS_MT_POSITION_Y, pos[i].y); 116 + if (ts->chip_info->have_z) 117 + input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]); 118 + } 119 + 120 + input_mt_sync_frame(input); 121 + input_sync(input); 122 + 123 + return n_contacts; 90 124 } 91 125 92 126 static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) 93 127 { 94 128 struct st1232_ts_data *ts = dev_id; 95 - struct st1232_ts_finger *finger = ts->fingers; 96 - struct input_dev *input_dev = ts->input_dev; 97 - int count = 0; 98 - int i, ret; 129 + int count; 130 + int error; 99 131 100 - ret = st1232_ts_read_data(ts); 101 - if (ret < 0) 102 - goto end; 132 + error = st1232_ts_read_data(ts); 133 + if (error) 134 + goto out; 103 135 104 - /* multi touch protocol */ 105 - for (i = 0; i < ts->chip_info->max_fingers; i++) { 106 - if (!finger[i].is_valid) 107 - continue; 108 - 109 - if (ts->chip_info->have_z) 110 - input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 111 - finger[i].t); 112 - 113 - touchscreen_report_pos(input_dev, &ts->prop, 114 - finger[i].x, finger[i].y, true); 115 - input_mt_sync(input_dev); 116 - count++; 117 - } 118 - 119 - /* SYN_MT_REPORT only if no contact */ 136 + count = st1232_ts_parse_and_report(ts); 120 137 if (!count) { 121 - input_mt_sync(input_dev); 122 138 if (ts->low_latency_req.dev) { 123 139 dev_pm_qos_remove_request(&ts->low_latency_req); 124 140 ts->low_latency_req.dev = NULL; ··· 140 136 DEV_PM_QOS_RESUME_LATENCY, 100); 141 137 } 142 138 143 - /* SYN_REPORT */ 144 - input_sync(input_dev); 145 - 146 - end: 139 + out: 147 140 return IRQ_HANDLED; 148 141 } 149 142 ··· 199 198 return -EINVAL; 200 199 } 201 200 202 - ts = devm_kzalloc(&client->dev, 203 - struct_size(ts, fingers, match->max_fingers), 204 - GFP_KERNEL); 201 + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); 205 202 if (!ts) 206 203 return -ENOMEM; 207 204 ··· 239 240 input_dev->name = "st1232-touchscreen"; 240 241 input_dev->id.bustype = BUS_I2C; 241 242 242 - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 243 - __set_bit(EV_SYN, input_dev->evbit); 244 - __set_bit(EV_KEY, input_dev->evbit); 245 - __set_bit(EV_ABS, input_dev->evbit); 246 - 247 243 if (ts->chip_info->have_z) 248 244 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 249 245 ts->chip_info->max_area, 0, 0); ··· 249 255 0, ts->chip_info->max_y, 0, 0); 250 256 251 257 touchscreen_parse_properties(input_dev, true, &ts->prop); 258 + 259 + error = input_mt_init_slots(input_dev, ts->chip_info->max_fingers, 260 + INPUT_MT_DIRECT | INPUT_MT_TRACK | 261 + INPUT_MT_DROP_UNUSED); 262 + if (error) { 263 + dev_err(&client->dev, "failed to initialize MT slots\n"); 264 + return error; 265 + } 252 266 253 267 error = devm_request_threaded_irq(&client->dev, client->irq, 254 268 NULL, st1232_ts_irq_handler,