Get rid of the packed structures for representing data as that does not apply to other similar Ilitek touchscreens. Instead, implement a function which parses the data and reports touch events and coordinates. Signed-off-by: Marek Vasut <marex@xxxxxxx> Cc: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx> Cc: Henrik Rydberg <rydberg@xxxxxxxxxxx> Cc: Olivier Sobrie <olivier@xxxxxxxxx> To: linux-input@xxxxxxxxxxxxxxx --- drivers/input/touchscreen/ili210x.c | 54 ++++++++++++++++------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 7579cf16b3663..2354e487c796a 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -16,20 +16,11 @@ #define REG_FIRMWARE_VERSION 0x40 #define REG_CALIBRATE 0xcc -struct finger { +struct panel_info { u8 x_low; u8 x_high; u8 y_low; u8 y_high; -} __packed; - -struct touchdata { - u8 status; - struct finger finger[MAX_TOUCHES]; -} __packed; - -struct panel_info { - struct finger finger_max; u8 xchannel_num; u8 ychannel_num; } __packed; @@ -72,25 +63,40 @@ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, return 0; } -static void ili210x_report_events(struct input_dev *input, - const struct touchdata *touchdata) +static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, + unsigned int finger, + unsigned int *x, unsigned int *y) +{ + u8 x_low, x_high, y_low, y_high; + + if (finger >= MAX_TOUCHES) + return false; + + if (touchdata[0] & BIT(finger)) + return false; + + x_high = touchdata[1 + (finger * 4) + 0]; + x_low = touchdata[1 + (finger * 4) + 1]; + y_high = touchdata[1 + (finger * 4) + 2]; + y_low = touchdata[1 + (finger * 4) + 3]; + *x = x_low | (x_high << 8); + *y = y_low | (y_high << 8); + + return true; +} + +static void ili210x_report_events(struct ili210x *priv, u8 *touchdata) { int i; bool touch; unsigned int x, y; - const struct finger *finger; for (i = 0; i < MAX_TOUCHES; i++) { input_mt_slot(input, i); - finger = &touchdata->finger[i]; - - touch = touchdata->status & (1 << i); + touch = ili210x_touchdata_to_coords(priv, touchdata, i, &x, &y); input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); if (touch) { - x = finger->x_low | (finger->x_high << 8); - y = finger->y_low | (finger->y_high << 8); - input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); } @@ -104,18 +110,18 @@ static irqreturn_t ili210x_irq(int irq, void *irq_data) { struct ili210x *priv = irq_data; struct i2c_client *client = priv->client; - struct touchdata touchdata; + u8 touchdata[1 + 4 * MAX_TOUCHES]; int error; error = ili210x_read_reg(client, REG_TOUCHDATA, - &touchdata, sizeof(touchdata)); + touchdata, sizeof(touchdata)); if (error) { dev_err(&client->dev, "Unable to get touchdata, err = %d\n", error); return IRQ_HANDLED; } - ili210x_report_events(priv, &touchdata); + ili210x_report_events(priv, touchdata); return IRQ_HANDLED; } @@ -202,8 +208,8 @@ static int ili210x_i2c_probe(struct i2c_client *client, return error; } - xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8); - ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8); + xmax = panel.x_low | (panel.x_high << 8); + ymax = panel.y_low | (panel.y_high << 8); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); input = devm_input_allocate_device(dev); -- 2.18.0