Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Touch Screen driver for SiS 9200 family I2C Touch panels
0004  *
0005  * Copyright (C) 2015 SiS, Inc.
0006  * Copyright (C) 2016 Nextfour Group
0007  */
0008 
0009 #include <linux/crc-itu-t.h>
0010 #include <linux/delay.h>
0011 #include <linux/i2c.h>
0012 #include <linux/input.h>
0013 #include <linux/input/mt.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/gpio/consumer.h>
0016 #include <linux/module.h>
0017 #include <linux/slab.h>
0018 #include <asm/unaligned.h>
0019 
0020 #define SIS_I2C_NAME        "sis_i2c_ts"
0021 
0022 /*
0023  * The I2C packet format:
0024  * le16     byte count
0025  * u8       Report ID
0026  * <contact data - variable length>
0027  * u8       Number of contacts
0028  * le16     Scan Time (optional)
0029  * le16     CRC
0030  *
0031  * One touch point information consists of 6+ bytes, the order is:
0032  * u8       contact state
0033  * u8       finger id
0034  * le16     x axis
0035  * le16     y axis
0036  * u8       contact width (optional)
0037  * u8       contact height (optional)
0038  * u8       pressure (optional)
0039  *
0040  * Maximum amount of data transmitted in one shot is 64 bytes, if controller
0041  * needs to report more contacts than fit in one packet it will send true
0042  * number of contacts in first packet and 0 as number of contacts in second
0043  * packet.
0044  */
0045 
0046 #define SIS_MAX_PACKET_SIZE     64
0047 
0048 #define SIS_PKT_LEN_OFFSET      0
0049 #define SIS_PKT_REPORT_OFFSET       2 /* Report ID/type */
0050 #define SIS_PKT_CONTACT_OFFSET      3 /* First contact */
0051 
0052 #define SIS_SCAN_TIME_LEN       2
0053 
0054 /* Supported report types */
0055 #define SIS_ALL_IN_ONE_PACKAGE      0x10
0056 #define SIS_PKT_IS_TOUCH(x)     (((x) & 0x0f) == 0x01)
0057 #define SIS_PKT_IS_HIDI2C(x)        (((x) & 0x0f) == 0x06)
0058 
0059 /* Contact properties within report */
0060 #define SIS_PKT_HAS_AREA(x)     ((x) & BIT(4))
0061 #define SIS_PKT_HAS_PRESSURE(x)     ((x) & BIT(5))
0062 #define SIS_PKT_HAS_SCANTIME(x)     ((x) & BIT(6))
0063 
0064 /* Contact size */
0065 #define SIS_BASE_LEN_PER_CONTACT    6
0066 #define SIS_AREA_LEN_PER_CONTACT    2
0067 #define SIS_PRESSURE_LEN_PER_CONTACT    1
0068 
0069 /* Offsets within contact data */
0070 #define SIS_CONTACT_STATUS_OFFSET   0
0071 #define SIS_CONTACT_ID_OFFSET       1 /* Contact ID */
0072 #define SIS_CONTACT_X_OFFSET        2
0073 #define SIS_CONTACT_Y_OFFSET        4
0074 #define SIS_CONTACT_WIDTH_OFFSET    6
0075 #define SIS_CONTACT_HEIGHT_OFFSET   7
0076 #define SIS_CONTACT_PRESSURE_OFFSET(id) (SIS_PKT_HAS_AREA(id) ? 8 : 6)
0077 
0078 /* Individual contact state */
0079 #define SIS_STATUS_UP           0x0
0080 #define SIS_STATUS_DOWN         0x3
0081 
0082 /* Touchscreen parameters */
0083 #define SIS_MAX_FINGERS         10
0084 #define SIS_MAX_X           4095
0085 #define SIS_MAX_Y           4095
0086 #define SIS_MAX_PRESSURE        255
0087 
0088 /* Resolution diagonal */
0089 #define SIS_AREA_LENGTH_LONGER      5792
0090 /*((SIS_MAX_X^2) + (SIS_MAX_Y^2))^0.5*/
0091 #define SIS_AREA_LENGTH_SHORT       5792
0092 #define SIS_AREA_UNIT           (5792 / 32)
0093 
0094 struct sis_ts_data {
0095     struct i2c_client *client;
0096     struct input_dev *input;
0097 
0098     struct gpio_desc *attn_gpio;
0099     struct gpio_desc *reset_gpio;
0100 
0101     u8 packet[SIS_MAX_PACKET_SIZE];
0102 };
0103 
0104 static int sis_read_packet(struct i2c_client *client, u8 *buf,
0105                unsigned int *num_contacts,
0106                unsigned int *contact_size)
0107 {
0108     int count_idx;
0109     int ret;
0110     u16 len;
0111     u16 crc, pkg_crc;
0112     u8 report_id;
0113 
0114     ret = i2c_master_recv(client, buf, SIS_MAX_PACKET_SIZE);
0115     if (ret <= 0)
0116         return -EIO;
0117 
0118     len = get_unaligned_le16(&buf[SIS_PKT_LEN_OFFSET]);
0119     if (len > SIS_MAX_PACKET_SIZE) {
0120         dev_err(&client->dev,
0121             "%s: invalid packet length (%d vs %d)\n",
0122             __func__, len, SIS_MAX_PACKET_SIZE);
0123         return -E2BIG;
0124     }
0125 
0126     if (len < 10)
0127         return -EINVAL;
0128 
0129     report_id = buf[SIS_PKT_REPORT_OFFSET];
0130     count_idx  = len - 1;
0131     *contact_size = SIS_BASE_LEN_PER_CONTACT;
0132 
0133     if (report_id != SIS_ALL_IN_ONE_PACKAGE) {
0134         if (SIS_PKT_IS_TOUCH(report_id)) {
0135             /*
0136              * Calculate CRC ignoring packet length
0137              * in the beginning and CRC transmitted
0138              * at the end of the packet.
0139              */
0140             crc = crc_itu_t(0, buf + 2, len - 2 - 2);
0141             pkg_crc = get_unaligned_le16(&buf[len - 2]);
0142 
0143             if (crc != pkg_crc) {
0144                 dev_err(&client->dev,
0145                     "%s: CRC Error (%d vs %d)\n",
0146                     __func__, crc, pkg_crc);
0147                 return -EINVAL;
0148             }
0149 
0150             count_idx -= 2;
0151 
0152         } else if (!SIS_PKT_IS_HIDI2C(report_id)) {
0153             dev_err(&client->dev,
0154                 "%s: invalid packet ID %#02x\n",
0155                 __func__, report_id);
0156             return -EINVAL;
0157         }
0158 
0159         if (SIS_PKT_HAS_SCANTIME(report_id))
0160             count_idx -= SIS_SCAN_TIME_LEN;
0161 
0162         if (SIS_PKT_HAS_AREA(report_id))
0163             *contact_size += SIS_AREA_LEN_PER_CONTACT;
0164         if (SIS_PKT_HAS_PRESSURE(report_id))
0165             *contact_size += SIS_PRESSURE_LEN_PER_CONTACT;
0166     }
0167 
0168     *num_contacts = buf[count_idx];
0169     return 0;
0170 }
0171 
0172 static int sis_ts_report_contact(struct sis_ts_data *ts, const u8 *data, u8 id)
0173 {
0174     struct input_dev *input = ts->input;
0175     int slot;
0176     u8 status = data[SIS_CONTACT_STATUS_OFFSET];
0177     u8 pressure;
0178     u8 height, width;
0179     u16 x, y;
0180 
0181     if (status != SIS_STATUS_DOWN && status != SIS_STATUS_UP) {
0182         dev_err(&ts->client->dev, "Unexpected touch status: %#02x\n",
0183             data[SIS_CONTACT_STATUS_OFFSET]);
0184         return -EINVAL;
0185     }
0186 
0187     slot = input_mt_get_slot_by_key(input, data[SIS_CONTACT_ID_OFFSET]);
0188     if (slot < 0)
0189         return -ENOENT;
0190 
0191     input_mt_slot(input, slot);
0192     input_mt_report_slot_state(input, MT_TOOL_FINGER,
0193                    status == SIS_STATUS_DOWN);
0194 
0195     if (status == SIS_STATUS_DOWN) {
0196         pressure = height = width = 1;
0197         if (id != SIS_ALL_IN_ONE_PACKAGE) {
0198             if (SIS_PKT_HAS_AREA(id)) {
0199                 width = data[SIS_CONTACT_WIDTH_OFFSET];
0200                 height = data[SIS_CONTACT_HEIGHT_OFFSET];
0201             }
0202 
0203             if (SIS_PKT_HAS_PRESSURE(id))
0204                 pressure =
0205                     data[SIS_CONTACT_PRESSURE_OFFSET(id)];
0206         }
0207 
0208         x = get_unaligned_le16(&data[SIS_CONTACT_X_OFFSET]);
0209         y = get_unaligned_le16(&data[SIS_CONTACT_Y_OFFSET]);
0210 
0211         input_report_abs(input, ABS_MT_TOUCH_MAJOR,
0212                  width * SIS_AREA_UNIT);
0213         input_report_abs(input, ABS_MT_TOUCH_MINOR,
0214                  height * SIS_AREA_UNIT);
0215         input_report_abs(input, ABS_MT_PRESSURE, pressure);
0216         input_report_abs(input, ABS_MT_POSITION_X, x);
0217         input_report_abs(input, ABS_MT_POSITION_Y, y);
0218     }
0219 
0220     return 0;
0221 }
0222 
0223 static void sis_ts_handle_packet(struct sis_ts_data *ts)
0224 {
0225     const u8 *contact;
0226     unsigned int num_to_report = 0;
0227     unsigned int num_contacts;
0228     unsigned int num_reported;
0229     unsigned int contact_size;
0230     int error;
0231     u8 report_id;
0232 
0233     do {
0234         error = sis_read_packet(ts->client, ts->packet,
0235                     &num_contacts, &contact_size);
0236         if (error)
0237             break;
0238 
0239         if (num_to_report == 0) {
0240             num_to_report = num_contacts;
0241         } else if (num_contacts != 0) {
0242             dev_err(&ts->client->dev,
0243                 "%s: nonzero (%d) point count in tail packet\n",
0244                 __func__, num_contacts);
0245             break;
0246         }
0247 
0248         report_id = ts->packet[SIS_PKT_REPORT_OFFSET];
0249         contact = &ts->packet[SIS_PKT_CONTACT_OFFSET];
0250         num_reported = 0;
0251 
0252         while (num_to_report > 0) {
0253             error = sis_ts_report_contact(ts, contact, report_id);
0254             if (error)
0255                 break;
0256 
0257             contact += contact_size;
0258             num_to_report--;
0259             num_reported++;
0260 
0261             if (report_id != SIS_ALL_IN_ONE_PACKAGE &&
0262                 num_reported >= 5) {
0263                 /*
0264                  * The remainder of contacts is sent
0265                  * in the 2nd packet.
0266                  */
0267                 break;
0268             }
0269         }
0270     } while (num_to_report > 0);
0271 
0272     input_mt_sync_frame(ts->input);
0273     input_sync(ts->input);
0274 }
0275 
0276 static irqreturn_t sis_ts_irq_handler(int irq, void *dev_id)
0277 {
0278     struct sis_ts_data *ts = dev_id;
0279 
0280     do {
0281         sis_ts_handle_packet(ts);
0282     } while (ts->attn_gpio && gpiod_get_value_cansleep(ts->attn_gpio));
0283 
0284     return IRQ_HANDLED;
0285 }
0286 
0287 static void sis_ts_reset(struct sis_ts_data *ts)
0288 {
0289     if (ts->reset_gpio) {
0290         /* Get out of reset */
0291         usleep_range(1000, 2000);
0292         gpiod_set_value(ts->reset_gpio, 1);
0293         usleep_range(1000, 2000);
0294         gpiod_set_value(ts->reset_gpio, 0);
0295         msleep(100);
0296     }
0297 }
0298 
0299 static int sis_ts_probe(struct i2c_client *client,
0300             const struct i2c_device_id *id)
0301 {
0302     struct sis_ts_data *ts;
0303     struct input_dev *input;
0304     int error;
0305 
0306     ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
0307     if (!ts)
0308         return -ENOMEM;
0309 
0310     ts->client = client;
0311 
0312     ts->attn_gpio = devm_gpiod_get_optional(&client->dev,
0313                         "attn", GPIOD_IN);
0314     if (IS_ERR(ts->attn_gpio)) {
0315         error = PTR_ERR(ts->attn_gpio);
0316         if (error != -EPROBE_DEFER)
0317             dev_err(&client->dev,
0318                 "Failed to get attention GPIO: %d\n", error);
0319         return error;
0320     }
0321 
0322     ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
0323                          "reset", GPIOD_OUT_LOW);
0324     if (IS_ERR(ts->reset_gpio)) {
0325         error = PTR_ERR(ts->reset_gpio);
0326         if (error != -EPROBE_DEFER)
0327             dev_err(&client->dev,
0328                 "Failed to get reset GPIO: %d\n", error);
0329         return error;
0330     }
0331 
0332     sis_ts_reset(ts);
0333 
0334     ts->input = input = devm_input_allocate_device(&client->dev);
0335     if (!input) {
0336         dev_err(&client->dev, "Failed to allocate input device\n");
0337         return -ENOMEM;
0338     }
0339 
0340     input->name = "SiS Touchscreen";
0341     input->id.bustype = BUS_I2C;
0342 
0343     input_set_abs_params(input, ABS_MT_POSITION_X, 0, SIS_MAX_X, 0, 0);
0344     input_set_abs_params(input, ABS_MT_POSITION_Y, 0, SIS_MAX_Y, 0, 0);
0345     input_set_abs_params(input, ABS_MT_PRESSURE, 0, SIS_MAX_PRESSURE, 0, 0);
0346     input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
0347                  0, SIS_AREA_LENGTH_LONGER, 0, 0);
0348     input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
0349                  0, SIS_AREA_LENGTH_SHORT, 0, 0);
0350 
0351     error = input_mt_init_slots(input, SIS_MAX_FINGERS, INPUT_MT_DIRECT);
0352     if (error) {
0353         dev_err(&client->dev,
0354             "Failed to initialize MT slots: %d\n", error);
0355         return error;
0356     }
0357 
0358     error = devm_request_threaded_irq(&client->dev, client->irq,
0359                       NULL, sis_ts_irq_handler,
0360                       IRQF_ONESHOT,
0361                       client->name, ts);
0362     if (error) {
0363         dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
0364         return error;
0365     }
0366 
0367     error = input_register_device(ts->input);
0368     if (error) {
0369         dev_err(&client->dev,
0370             "Failed to register input device: %d\n", error);
0371         return error;
0372     }
0373 
0374     return 0;
0375 }
0376 
0377 #ifdef CONFIG_OF
0378 static const struct of_device_id sis_ts_dt_ids[] = {
0379     { .compatible = "sis,9200-ts" },
0380     { /* sentinel */ }
0381 };
0382 MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
0383 #endif
0384 
0385 static const struct i2c_device_id sis_ts_id[] = {
0386     { SIS_I2C_NAME, 0 },
0387     { "9200-ts",    0 },
0388     { /* sentinel */  }
0389 };
0390 MODULE_DEVICE_TABLE(i2c, sis_ts_id);
0391 
0392 static struct i2c_driver sis_ts_driver = {
0393     .driver = {
0394         .name   = SIS_I2C_NAME,
0395         .of_match_table = of_match_ptr(sis_ts_dt_ids),
0396     },
0397     .probe      = sis_ts_probe,
0398     .id_table   = sis_ts_id,
0399 };
0400 module_i2c_driver(sis_ts_driver);
0401 
0402 MODULE_DESCRIPTION("SiS 9200 Family Touchscreen Driver");
0403 MODULE_LICENSE("GPL v2");
0404 MODULE_AUTHOR("Mika Penttilä <mika.penttila@nextfour.com>");