root/drivers/input/touchscreen/sis_i2c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sis_read_packet
  2. sis_ts_report_contact
  3. sis_ts_handle_packet
  4. sis_ts_irq_handler
  5. sis_ts_reset
  6. sis_ts_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Touch Screen driver for SiS 9200 family I2C Touch panels
   4  *
   5  * Copyright (C) 2015 SiS, Inc.
   6  * Copyright (C) 2016 Nextfour Group
   7  */
   8 
   9 #include <linux/crc-itu-t.h>
  10 #include <linux/delay.h>
  11 #include <linux/i2c.h>
  12 #include <linux/input.h>
  13 #include <linux/input/mt.h>
  14 #include <linux/interrupt.h>
  15 #include <linux/gpio/consumer.h>
  16 #include <linux/module.h>
  17 #include <linux/slab.h>
  18 #include <asm/unaligned.h>
  19 
  20 #define SIS_I2C_NAME            "sis_i2c_ts"
  21 
  22 /*
  23  * The I2C packet format:
  24  * le16         byte count
  25  * u8           Report ID
  26  * <contact data - variable length>
  27  * u8           Number of contacts
  28  * le16         Scan Time (optional)
  29  * le16         CRC
  30  *
  31  * One touch point information consists of 6+ bytes, the order is:
  32  * u8           contact state
  33  * u8           finger id
  34  * le16         x axis
  35  * le16         y axis
  36  * u8           contact width (optional)
  37  * u8           contact height (optional)
  38  * u8           pressure (optional)
  39  *
  40  * Maximum amount of data transmitted in one shot is 64 bytes, if controller
  41  * needs to report more contacts than fit in one packet it will send true
  42  * number of contacts in first packet and 0 as number of contacts in second
  43  * packet.
  44  */
  45 
  46 #define SIS_MAX_PACKET_SIZE             64
  47 
  48 #define SIS_PKT_LEN_OFFSET              0
  49 #define SIS_PKT_REPORT_OFFSET           2 /* Report ID/type */
  50 #define SIS_PKT_CONTACT_OFFSET          3 /* First contact */
  51 
  52 #define SIS_SCAN_TIME_LEN               2
  53 
  54 /* Supported report types */
  55 #define SIS_ALL_IN_ONE_PACKAGE          0x10
  56 #define SIS_PKT_IS_TOUCH(x)             (((x) & 0x0f) == 0x01)
  57 #define SIS_PKT_IS_HIDI2C(x)            (((x) & 0x0f) == 0x06)
  58 
  59 /* Contact properties within report */
  60 #define SIS_PKT_HAS_AREA(x)             ((x) & BIT(4))
  61 #define SIS_PKT_HAS_PRESSURE(x)         ((x) & BIT(5))
  62 #define SIS_PKT_HAS_SCANTIME(x)         ((x) & BIT(6))
  63 
  64 /* Contact size */
  65 #define SIS_BASE_LEN_PER_CONTACT        6
  66 #define SIS_AREA_LEN_PER_CONTACT        2
  67 #define SIS_PRESSURE_LEN_PER_CONTACT    1
  68 
  69 /* Offsets within contact data */
  70 #define SIS_CONTACT_STATUS_OFFSET       0
  71 #define SIS_CONTACT_ID_OFFSET           1 /* Contact ID */
  72 #define SIS_CONTACT_X_OFFSET            2
  73 #define SIS_CONTACT_Y_OFFSET            4
  74 #define SIS_CONTACT_WIDTH_OFFSET        6
  75 #define SIS_CONTACT_HEIGHT_OFFSET       7
  76 #define SIS_CONTACT_PRESSURE_OFFSET(id) (SIS_PKT_HAS_AREA(id) ? 8 : 6)
  77 
  78 /* Individual contact state */
  79 #define SIS_STATUS_UP                   0x0
  80 #define SIS_STATUS_DOWN                 0x3
  81 
  82 /* Touchscreen parameters */
  83 #define SIS_MAX_FINGERS                 10
  84 #define SIS_MAX_X                       4095
  85 #define SIS_MAX_Y                       4095
  86 #define SIS_MAX_PRESSURE                255
  87 
  88 /* Resolution diagonal */
  89 #define SIS_AREA_LENGTH_LONGER          5792
  90 /*((SIS_MAX_X^2) + (SIS_MAX_Y^2))^0.5*/
  91 #define SIS_AREA_LENGTH_SHORT           5792
  92 #define SIS_AREA_UNIT                   (5792 / 32)
  93 
  94 struct sis_ts_data {
  95         struct i2c_client *client;
  96         struct input_dev *input;
  97 
  98         struct gpio_desc *attn_gpio;
  99         struct gpio_desc *reset_gpio;
 100 
 101         u8 packet[SIS_MAX_PACKET_SIZE];
 102 };
 103 
 104 static int sis_read_packet(struct i2c_client *client, u8 *buf,
 105                            unsigned int *num_contacts,
 106                            unsigned int *contact_size)
 107 {
 108         int count_idx;
 109         int ret;
 110         u16 len;
 111         u16 crc, pkg_crc;
 112         u8 report_id;
 113 
 114         ret = i2c_master_recv(client, buf, SIS_MAX_PACKET_SIZE);
 115         if (ret <= 0)
 116                 return -EIO;
 117 
 118         len = get_unaligned_le16(&buf[SIS_PKT_LEN_OFFSET]);
 119         if (len > SIS_MAX_PACKET_SIZE) {
 120                 dev_err(&client->dev,
 121                         "%s: invalid packet length (%d vs %d)\n",
 122                         __func__, len, SIS_MAX_PACKET_SIZE);
 123                 return -E2BIG;
 124         }
 125 
 126         if (len < 10)
 127                 return -EINVAL;
 128 
 129         report_id = buf[SIS_PKT_REPORT_OFFSET];
 130         count_idx  = len - 1;
 131         *contact_size = SIS_BASE_LEN_PER_CONTACT;
 132 
 133         if (report_id != SIS_ALL_IN_ONE_PACKAGE) {
 134                 if (SIS_PKT_IS_TOUCH(report_id)) {
 135                         /*
 136                          * Calculate CRC ignoring packet length
 137                          * in the beginning and CRC transmitted
 138                          * at the end of the packet.
 139                          */
 140                         crc = crc_itu_t(0, buf + 2, len - 2 - 2);
 141                         pkg_crc = get_unaligned_le16(&buf[len - 2]);
 142 
 143                         if (crc != pkg_crc) {
 144                                 dev_err(&client->dev,
 145                                         "%s: CRC Error (%d vs %d)\n",
 146                                         __func__, crc, pkg_crc);
 147                                 return -EINVAL;
 148                         }
 149 
 150                         count_idx -= 2;
 151 
 152                 } else if (!SIS_PKT_IS_HIDI2C(report_id)) {
 153                         dev_err(&client->dev,
 154                                 "%s: invalid packet ID %#02x\n",
 155                                 __func__, report_id);
 156                         return -EINVAL;
 157                 }
 158 
 159                 if (SIS_PKT_HAS_SCANTIME(report_id))
 160                         count_idx -= SIS_SCAN_TIME_LEN;
 161 
 162                 if (SIS_PKT_HAS_AREA(report_id))
 163                         *contact_size += SIS_AREA_LEN_PER_CONTACT;
 164                 if (SIS_PKT_HAS_PRESSURE(report_id))
 165                         *contact_size += SIS_PRESSURE_LEN_PER_CONTACT;
 166         }
 167 
 168         *num_contacts = buf[count_idx];
 169         return 0;
 170 }
 171 
 172 static int sis_ts_report_contact(struct sis_ts_data *ts, const u8 *data, u8 id)
 173 {
 174         struct input_dev *input = ts->input;
 175         int slot;
 176         u8 status = data[SIS_CONTACT_STATUS_OFFSET];
 177         u8 pressure;
 178         u8 height, width;
 179         u16 x, y;
 180 
 181         if (status != SIS_STATUS_DOWN && status != SIS_STATUS_UP) {
 182                 dev_err(&ts->client->dev, "Unexpected touch status: %#02x\n",
 183                         data[SIS_CONTACT_STATUS_OFFSET]);
 184                 return -EINVAL;
 185         }
 186 
 187         slot = input_mt_get_slot_by_key(input, data[SIS_CONTACT_ID_OFFSET]);
 188         if (slot < 0)
 189                 return -ENOENT;
 190 
 191         input_mt_slot(input, slot);
 192         input_mt_report_slot_state(input, MT_TOOL_FINGER,
 193                                    status == SIS_STATUS_DOWN);
 194 
 195         if (status == SIS_STATUS_DOWN) {
 196                 pressure = height = width = 1;
 197                 if (id != SIS_ALL_IN_ONE_PACKAGE) {
 198                         if (SIS_PKT_HAS_AREA(id)) {
 199                                 width = data[SIS_CONTACT_WIDTH_OFFSET];
 200                                 height = data[SIS_CONTACT_HEIGHT_OFFSET];
 201                         }
 202 
 203                         if (SIS_PKT_HAS_PRESSURE(id))
 204                                 pressure =
 205                                         data[SIS_CONTACT_PRESSURE_OFFSET(id)];
 206                 }
 207 
 208                 x = get_unaligned_le16(&data[SIS_CONTACT_X_OFFSET]);
 209                 y = get_unaligned_le16(&data[SIS_CONTACT_Y_OFFSET]);
 210 
 211                 input_report_abs(input, ABS_MT_TOUCH_MAJOR,
 212                                  width * SIS_AREA_UNIT);
 213                 input_report_abs(input, ABS_MT_TOUCH_MINOR,
 214                                  height * SIS_AREA_UNIT);
 215                 input_report_abs(input, ABS_MT_PRESSURE, pressure);
 216                 input_report_abs(input, ABS_MT_POSITION_X, x);
 217                 input_report_abs(input, ABS_MT_POSITION_Y, y);
 218         }
 219 
 220         return 0;
 221 }
 222 
 223 static void sis_ts_handle_packet(struct sis_ts_data *ts)
 224 {
 225         const u8 *contact;
 226         unsigned int num_to_report = 0;
 227         unsigned int num_contacts;
 228         unsigned int num_reported;
 229         unsigned int contact_size;
 230         int error;
 231         u8 report_id;
 232 
 233         do {
 234                 error = sis_read_packet(ts->client, ts->packet,
 235                                         &num_contacts, &contact_size);
 236                 if (error)
 237                         break;
 238 
 239                 if (num_to_report == 0) {
 240                         num_to_report = num_contacts;
 241                 } else if (num_contacts != 0) {
 242                         dev_err(&ts->client->dev,
 243                                 "%s: nonzero (%d) point count in tail packet\n",
 244                                 __func__, num_contacts);
 245                         break;
 246                 }
 247 
 248                 report_id = ts->packet[SIS_PKT_REPORT_OFFSET];
 249                 contact = &ts->packet[SIS_PKT_CONTACT_OFFSET];
 250                 num_reported = 0;
 251 
 252                 while (num_to_report > 0) {
 253                         error = sis_ts_report_contact(ts, contact, report_id);
 254                         if (error)
 255                                 break;
 256 
 257                         contact += contact_size;
 258                         num_to_report--;
 259                         num_reported++;
 260 
 261                         if (report_id != SIS_ALL_IN_ONE_PACKAGE &&
 262                             num_reported >= 5) {
 263                                 /*
 264                                  * The remainder of contacts is sent
 265                                  * in the 2nd packet.
 266                                  */
 267                                 break;
 268                         }
 269                 }
 270         } while (num_to_report > 0);
 271 
 272         input_mt_sync_frame(ts->input);
 273         input_sync(ts->input);
 274 }
 275 
 276 static irqreturn_t sis_ts_irq_handler(int irq, void *dev_id)
 277 {
 278         struct sis_ts_data *ts = dev_id;
 279 
 280         do {
 281                 sis_ts_handle_packet(ts);
 282         } while (ts->attn_gpio && gpiod_get_value_cansleep(ts->attn_gpio));
 283 
 284         return IRQ_HANDLED;
 285 }
 286 
 287 static void sis_ts_reset(struct sis_ts_data *ts)
 288 {
 289         if (ts->reset_gpio) {
 290                 /* Get out of reset */
 291                 usleep_range(1000, 2000);
 292                 gpiod_set_value(ts->reset_gpio, 1);
 293                 usleep_range(1000, 2000);
 294                 gpiod_set_value(ts->reset_gpio, 0);
 295                 msleep(100);
 296         }
 297 }
 298 
 299 static int sis_ts_probe(struct i2c_client *client,
 300                         const struct i2c_device_id *id)
 301 {
 302         struct sis_ts_data *ts;
 303         struct input_dev *input;
 304         int error;
 305 
 306         ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
 307         if (!ts)
 308                 return -ENOMEM;
 309 
 310         ts->client = client;
 311 
 312         ts->attn_gpio = devm_gpiod_get_optional(&client->dev,
 313                                                 "attn", GPIOD_IN);
 314         if (IS_ERR(ts->attn_gpio)) {
 315                 error = PTR_ERR(ts->attn_gpio);
 316                 if (error != -EPROBE_DEFER)
 317                         dev_err(&client->dev,
 318                                 "Failed to get attention GPIO: %d\n", error);
 319                 return error;
 320         }
 321 
 322         ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
 323                                                  "reset", GPIOD_OUT_LOW);
 324         if (IS_ERR(ts->reset_gpio)) {
 325                 error = PTR_ERR(ts->reset_gpio);
 326                 if (error != -EPROBE_DEFER)
 327                         dev_err(&client->dev,
 328                                 "Failed to get reset GPIO: %d\n", error);
 329                 return error;
 330         }
 331 
 332         sis_ts_reset(ts);
 333 
 334         ts->input = input = devm_input_allocate_device(&client->dev);
 335         if (!input) {
 336                 dev_err(&client->dev, "Failed to allocate input device\n");
 337                 return -ENOMEM;
 338         }
 339 
 340         input->name = "SiS Touchscreen";
 341         input->id.bustype = BUS_I2C;
 342 
 343         input_set_abs_params(input, ABS_MT_POSITION_X, 0, SIS_MAX_X, 0, 0);
 344         input_set_abs_params(input, ABS_MT_POSITION_Y, 0, SIS_MAX_Y, 0, 0);
 345         input_set_abs_params(input, ABS_MT_PRESSURE, 0, SIS_MAX_PRESSURE, 0, 0);
 346         input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
 347                              0, SIS_AREA_LENGTH_LONGER, 0, 0);
 348         input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
 349                              0, SIS_AREA_LENGTH_SHORT, 0, 0);
 350 
 351         error = input_mt_init_slots(input, SIS_MAX_FINGERS, INPUT_MT_DIRECT);
 352         if (error) {
 353                 dev_err(&client->dev,
 354                         "Failed to initialize MT slots: %d\n", error);
 355                 return error;
 356         }
 357 
 358         error = devm_request_threaded_irq(&client->dev, client->irq,
 359                                           NULL, sis_ts_irq_handler,
 360                                           IRQF_ONESHOT,
 361                                           client->name, ts);
 362         if (error) {
 363                 dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
 364                 return error;
 365         }
 366 
 367         error = input_register_device(ts->input);
 368         if (error) {
 369                 dev_err(&client->dev,
 370                         "Failed to register input device: %d\n", error);
 371                 return error;
 372         }
 373 
 374         return 0;
 375 }
 376 
 377 #ifdef CONFIG_OF
 378 static const struct of_device_id sis_ts_dt_ids[] = {
 379         { .compatible = "sis,9200-ts" },
 380         { /* sentinel */ }
 381 };
 382 MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
 383 #endif
 384 
 385 static const struct i2c_device_id sis_ts_id[] = {
 386         { SIS_I2C_NAME, 0 },
 387         { "9200-ts",    0 },
 388         { /* sentinel */  }
 389 };
 390 MODULE_DEVICE_TABLE(i2c, sis_ts_id);
 391 
 392 static struct i2c_driver sis_ts_driver = {
 393         .driver = {
 394                 .name   = SIS_I2C_NAME,
 395                 .of_match_table = of_match_ptr(sis_ts_dt_ids),
 396         },
 397         .probe          = sis_ts_probe,
 398         .id_table       = sis_ts_id,
 399 };
 400 module_i2c_driver(sis_ts_driver);
 401 
 402 MODULE_DESCRIPTION("SiS 9200 Family Touchscreen Driver");
 403 MODULE_LICENSE("GPL v2");
 404 MODULE_AUTHOR("Mika Penttilä <mika.penttila@nextfour.com>");

/* [<][>][^][v][top][bottom][index][help] */