ili210x.c (58e16d792a6a8c6b750f637a4649967fcac853dc) | ili210x.c (eb91ecc9fc43fbefdfdfe1ea8b3f136ccbc02f66) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/module.h> 3#include <linux/i2c.h> 4#include <linux/interrupt.h> 5#include <linux/slab.h> 6#include <linux/input.h> 7#include <linux/input/mt.h> 8#include <linux/input/touchscreen.h> 9#include <linux/delay.h> 10#include <linux/workqueue.h> 11#include <linux/gpio/consumer.h> 12#include <linux/of_device.h> 13#include <asm/unaligned.h> 14 15#define ILI210X_TOUCHES 2 | 1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/module.h> 3#include <linux/i2c.h> 4#include <linux/interrupt.h> 5#include <linux/slab.h> 6#include <linux/input.h> 7#include <linux/input/mt.h> 8#include <linux/input/touchscreen.h> 9#include <linux/delay.h> 10#include <linux/workqueue.h> 11#include <linux/gpio/consumer.h> 12#include <linux/of_device.h> 13#include <asm/unaligned.h> 14 15#define ILI210X_TOUCHES 2 |
16#define ILI211X_TOUCHES 10 |
|
16#define ILI251X_TOUCHES 10 17#define DEFAULT_POLL_PERIOD 20 18 19/* Touchscreen commands */ 20#define REG_TOUCHDATA 0x10 21#define REG_PANEL_INFO 0x20 22#define REG_FIRMWARE_VERSION 0x40 23#define REG_CALIBRATE 0xcc 24 25struct firmware_version { 26 u8 id; 27 u8 major; 28 u8 minor; 29} __packed; 30 31enum ili2xxx_model { 32 MODEL_ILI210X, | 17#define ILI251X_TOUCHES 10 18#define DEFAULT_POLL_PERIOD 20 19 20/* Touchscreen commands */ 21#define REG_TOUCHDATA 0x10 22#define REG_PANEL_INFO 0x20 23#define REG_FIRMWARE_VERSION 0x40 24#define REG_CALIBRATE 0xcc 25 26struct firmware_version { 27 u8 id; 28 u8 major; 29 u8 minor; 30} __packed; 31 32enum ili2xxx_model { 33 MODEL_ILI210X, |
34 MODEL_ILI211X, |
|
33 MODEL_ILI251X, 34}; 35 36struct ili210x { 37 struct i2c_client *client; 38 struct input_dev *input; 39 unsigned int poll_period; 40 struct delayed_work dwork; --- 72 unchanged lines hidden (view full) --- 113 return false; 114 115 *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0); 116 *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2); 117 118 return true; 119} 120 | 35 MODEL_ILI251X, 36}; 37 38struct ili210x { 39 struct i2c_client *client; 40 struct input_dev *input; 41 unsigned int poll_period; 42 struct delayed_work dwork; --- 72 unchanged lines hidden (view full) --- 115 return false; 116 117 *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0); 118 *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2); 119 120 return true; 121} 122 |
123static bool ili211x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, 124 unsigned int finger, 125 unsigned int *x, unsigned int *y) 126{ 127 u32 data; 128 129 if (finger >= ILI211X_TOUCHES) 130 return false; 131 132 data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0); 133 if (data == 0xffffffff) /* Finger up */ 134 return false; 135 136 *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) | 137 touchdata[1 + (finger * 4) + 1]; 138 *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) | 139 touchdata[1 + (finger * 4) + 2]; 140 141 return true; 142} 143 |
|
121static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, 122 unsigned int finger, 123 unsigned int *x, unsigned int *y) 124{ 125 if (finger >= ILI251X_TOUCHES) 126 return false; 127 128 *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); --- 12 unchanged lines hidden (view full) --- 141 int i; 142 bool contact = false, touch = false; 143 unsigned int x = 0, y = 0; 144 145 for (i = 0; i < priv->max_touches; i++) { 146 if (priv->model == MODEL_ILI210X) { 147 touch = ili210x_touchdata_to_coords(priv, touchdata, 148 i, &x, &y); | 144static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata, 145 unsigned int finger, 146 unsigned int *x, unsigned int *y) 147{ 148 if (finger >= ILI251X_TOUCHES) 149 return false; 150 151 *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); --- 12 unchanged lines hidden (view full) --- 164 int i; 165 bool contact = false, touch = false; 166 unsigned int x = 0, y = 0; 167 168 for (i = 0; i < priv->max_touches; i++) { 169 if (priv->model == MODEL_ILI210X) { 170 touch = ili210x_touchdata_to_coords(priv, touchdata, 171 i, &x, &y); |
172 } else if (priv->model == MODEL_ILI211X) { 173 touch = ili211x_touchdata_to_coords(priv, touchdata, 174 i, &x, &y); |
|
149 } else if (priv->model == MODEL_ILI251X) { 150 touch = ili251x_touchdata_to_coords(priv, touchdata, 151 i, &x, &y); 152 if (touch) 153 contact = true; 154 } 155 156 input_mt_slot(input, i); --- 14 unchanged lines hidden (view full) --- 171} 172 173static void ili210x_work(struct work_struct *work) 174{ 175 struct ili210x *priv = container_of(work, struct ili210x, 176 dwork.work); 177 struct i2c_client *client = priv->client; 178 u8 touchdata[64] = { 0 }; | 175 } else if (priv->model == MODEL_ILI251X) { 176 touch = ili251x_touchdata_to_coords(priv, touchdata, 177 i, &x, &y); 178 if (touch) 179 contact = true; 180 } 181 182 input_mt_slot(input, i); --- 14 unchanged lines hidden (view full) --- 197} 198 199static void ili210x_work(struct work_struct *work) 200{ 201 struct ili210x *priv = container_of(work, struct ili210x, 202 dwork.work); 203 struct i2c_client *client = priv->client; 204 u8 touchdata[64] = { 0 }; |
205 s16 sum = 0; |
|
179 bool touch; | 206 bool touch; |
180 int error = -EINVAL; | 207 int i, error = -EINVAL; |
181 182 if (priv->model == MODEL_ILI210X) { 183 error = ili210x_read_reg(client, REG_TOUCHDATA, 184 touchdata, sizeof(touchdata)); | 208 209 if (priv->model == MODEL_ILI210X) { 210 error = ili210x_read_reg(client, REG_TOUCHDATA, 211 touchdata, sizeof(touchdata)); |
212 } else if (priv->model == MODEL_ILI211X) { 213 error = ili210x_read(client, touchdata, 43); 214 if (!error) { 215 /* This chip uses custom checksum at the end of data */ 216 for (i = 0; i <= 41; i++) 217 sum = (sum + touchdata[i]) & 0xff; 218 if ((-sum & 0xff) != touchdata[42]) { 219 dev_err(&client->dev, 220 "CRC error (crc=0x%02x expected=0x%02x)\n", 221 sum, touchdata[42]); 222 return; 223 } 224 } |
|
185 } else if (priv->model == MODEL_ILI251X) { 186 error = ili210x_read_reg(client, REG_TOUCHDATA, 187 touchdata, 31); 188 if (!error && touchdata[0] == 2) 189 error = ili210x_read(client, &touchdata[31], 20); 190 } 191 192 if (error) { --- 113 unchanged lines hidden (view full) --- 306 priv->client = client; 307 priv->input = input; 308 priv->poll_period = DEFAULT_POLL_PERIOD; 309 INIT_DELAYED_WORK(&priv->dwork, ili210x_work); 310 priv->reset_gpio = reset_gpio; 311 priv->model = model; 312 if (model == MODEL_ILI210X) 313 priv->max_touches = ILI210X_TOUCHES; | 225 } else if (priv->model == MODEL_ILI251X) { 226 error = ili210x_read_reg(client, REG_TOUCHDATA, 227 touchdata, 31); 228 if (!error && touchdata[0] == 2) 229 error = ili210x_read(client, &touchdata[31], 20); 230 } 231 232 if (error) { --- 113 unchanged lines hidden (view full) --- 346 priv->client = client; 347 priv->input = input; 348 priv->poll_period = DEFAULT_POLL_PERIOD; 349 INIT_DELAYED_WORK(&priv->dwork, ili210x_work); 350 priv->reset_gpio = reset_gpio; 351 priv->model = model; 352 if (model == MODEL_ILI210X) 353 priv->max_touches = ILI210X_TOUCHES; |
354 if (model == MODEL_ILI211X) 355 priv->max_touches = ILI211X_TOUCHES; |
|
314 if (model == MODEL_ILI251X) 315 priv->max_touches = ILI251X_TOUCHES; 316 317 i2c_set_clientdata(client, priv); 318 319 /* Get firmware version */ 320 error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, 321 &firmware, sizeof(firmware)); --- 68 unchanged lines hidden (view full) --- 390 return 0; 391} 392 393static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, 394 ili210x_i2c_suspend, ili210x_i2c_resume); 395 396static const struct i2c_device_id ili210x_i2c_id[] = { 397 { "ili210x", MODEL_ILI210X }, | 356 if (model == MODEL_ILI251X) 357 priv->max_touches = ILI251X_TOUCHES; 358 359 i2c_set_clientdata(client, priv); 360 361 /* Get firmware version */ 362 error = ili210x_read_reg(client, REG_FIRMWARE_VERSION, 363 &firmware, sizeof(firmware)); --- 68 unchanged lines hidden (view full) --- 432 return 0; 433} 434 435static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm, 436 ili210x_i2c_suspend, ili210x_i2c_resume); 437 438static const struct i2c_device_id ili210x_i2c_id[] = { 439 { "ili210x", MODEL_ILI210X }, |
440 { "ili2117", MODEL_ILI211X }, |
|
398 { "ili251x", MODEL_ILI251X }, 399 { } 400}; 401MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); 402 403static const struct of_device_id ili210x_dt_ids[] = { 404 { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, | 441 { "ili251x", MODEL_ILI251X }, 442 { } 443}; 444MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); 445 446static const struct of_device_id ili210x_dt_ids[] = { 447 { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, |
448 { .compatible = "ilitek,ili2117", .data = (void *)MODEL_ILI211X }, |
|
405 { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, 406 { }, 407}; 408MODULE_DEVICE_TABLE(of, ili210x_dt_ids); 409 410static struct i2c_driver ili210x_ts_driver = { 411 .driver = { 412 .name = "ili210x_i2c", --- 12 unchanged lines hidden --- | 449 { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, 450 { }, 451}; 452MODULE_DEVICE_TABLE(of, ili210x_dt_ids); 453 454static struct i2c_driver ili210x_ts_driver = { 455 .driver = { 456 .name = "ili210x_i2c", --- 12 unchanged lines hidden --- |