Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Samsung S6SY761 Touchscreen device driver
0003 //
0004 // Copyright (c) 2017 Samsung Electronics Co., Ltd.
0005 // Copyright (c) 2017 Andi Shyti <andi@etezian.org>
0006 
0007 #include <asm/unaligned.h>
0008 #include <linux/delay.h>
0009 #include <linux/i2c.h>
0010 #include <linux/input/mt.h>
0011 #include <linux/input/touchscreen.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/irq.h>
0014 #include <linux/module.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/regulator/consumer.h>
0017 
0018 /* commands */
0019 #define S6SY761_SENSE_ON        0x10
0020 #define S6SY761_SENSE_OFF       0x11
0021 #define S6SY761_TOUCH_FUNCTION      0x30 /* R/W for get/set */
0022 #define S6SY761_FIRMWARE_INTEGRITY  0x21
0023 #define S6SY761_PANEL_INFO      0x23
0024 #define S6SY761_DEVICE_ID       0x52
0025 #define S6SY761_BOOT_STATUS     0x55
0026 #define S6SY761_READ_ONE_EVENT      0x60
0027 #define S6SY761_READ_ALL_EVENT      0x61
0028 #define S6SY761_CLEAR_EVENT_STACK   0x62
0029 #define S6SY761_APPLICATION_MODE    0xe4
0030 
0031 /* events */
0032 #define S6SY761_EVENT_INFO      0x02
0033 #define S6SY761_EVENT_VENDOR_INFO   0x07
0034 
0035 /* info */
0036 #define S6SY761_INFO_BOOT_COMPLETE  0x00
0037 
0038 /* firmware status */
0039 #define S6SY761_FW_OK           0x80
0040 
0041 /*
0042  * the functionalities are put as a reference
0043  * as in the device I am using none of them
0044  * works therefore not used in this driver yet.
0045  */
0046 /* touchscreen functionalities */
0047 #define S6SY761_MASK_TOUCH      BIT(0)
0048 #define S6SY761_MASK_HOVER      BIT(1)
0049 #define S6SY761_MASK_COVER      BIT(2)
0050 #define S6SY761_MASK_GLOVE      BIT(3)
0051 #define S6SY761_MASK_STYLUS     BIT(4)
0052 #define S6SY761_MASK_PALM       BIT(5)
0053 #define S6SY761_MASK_WET        BIT(6)
0054 #define S6SY761_MASK_PROXIMITY      BIT(7)
0055 
0056 /* boot status (BS) */
0057 #define S6SY761_BS_BOOT_LOADER      0x10
0058 #define S6SY761_BS_APPLICATION      0x20
0059 
0060 /* event id */
0061 #define S6SY761_EVENT_ID_COORDINATE 0x00
0062 #define S6SY761_EVENT_ID_STATUS     0x01
0063 
0064 /* event register masks */
0065 #define S6SY761_MASK_TOUCH_STATE    0xc0 /* byte 0 */
0066 #define S6SY761_MASK_TID        0x3c
0067 #define S6SY761_MASK_EID        0x03
0068 #define S6SY761_MASK_X          0xf0 /* byte 3 */
0069 #define S6SY761_MASK_Y          0x0f
0070 #define S6SY761_MASK_Z          0x3f /* byte 6 */
0071 #define S6SY761_MASK_LEFT_EVENTS    0x3f /* byte 7 */
0072 #define S6SY761_MASK_TOUCH_TYPE     0xc0 /* MSB in byte 6, LSB in byte 7 */
0073 
0074 /* event touch state values */
0075 #define S6SY761_TS_NONE         0x00
0076 #define S6SY761_TS_PRESS        0x01
0077 #define S6SY761_TS_MOVE         0x02
0078 #define S6SY761_TS_RELEASE      0x03
0079 
0080 /* application modes */
0081 #define S6SY761_APP_NORMAL      0x0
0082 #define S6SY761_APP_LOW_POWER       0x1
0083 #define S6SY761_APP_TEST        0x2
0084 #define S6SY761_APP_FLASH       0x3
0085 #define S6SY761_APP_SLEEP       0x4
0086 
0087 #define S6SY761_EVENT_SIZE      8
0088 #define S6SY761_EVENT_COUNT     32
0089 #define S6SY761_DEVID_SIZE      3
0090 #define S6SY761_PANEL_ID_SIZE       11
0091 #define S6SY761_TS_STATUS_SIZE      5
0092 #define S6SY761_MAX_FINGERS     10
0093 
0094 #define S6SY761_DEV_NAME    "s6sy761"
0095 
0096 enum s6sy761_regulators {
0097     S6SY761_REGULATOR_VDD,
0098     S6SY761_REGULATOR_AVDD,
0099 };
0100 
0101 struct s6sy761_data {
0102     struct i2c_client *client;
0103     struct regulator_bulk_data regulators[2];
0104     struct input_dev *input;
0105     struct touchscreen_properties prop;
0106 
0107     u8 data[S6SY761_EVENT_SIZE * S6SY761_EVENT_COUNT];
0108 
0109     u16 devid;
0110     u8 tx_channel;
0111 };
0112 
0113 /*
0114  * We can't simply use i2c_smbus_read_i2c_block_data because we
0115  * need to read more than 255 bytes
0116  */
0117 static int s6sy761_read_events(struct s6sy761_data *sdata, u16 n_events)
0118 {
0119     u8 cmd = S6SY761_READ_ALL_EVENT;
0120     struct i2c_msg msgs[2] = {
0121         {
0122             .addr   = sdata->client->addr,
0123             .len    = 1,
0124             .buf    = &cmd,
0125         },
0126         {
0127             .addr   = sdata->client->addr,
0128             .flags  = I2C_M_RD,
0129             .len    = (n_events * S6SY761_EVENT_SIZE),
0130             .buf    = sdata->data + S6SY761_EVENT_SIZE,
0131         },
0132     };
0133     int ret;
0134 
0135     ret = i2c_transfer(sdata->client->adapter, msgs, ARRAY_SIZE(msgs));
0136     if (ret < 0)
0137         return ret;
0138 
0139     return ret == ARRAY_SIZE(msgs) ? 0 : -EIO;
0140 }
0141 
0142 static void s6sy761_report_coordinates(struct s6sy761_data *sdata,
0143                        u8 *event, u8 tid)
0144 {
0145     u8 major = event[4];
0146     u8 minor = event[5];
0147     u8 z = event[6] & S6SY761_MASK_Z;
0148     u16 x = (event[1] << 4) | ((event[3] & S6SY761_MASK_X) >> 4);
0149     u16 y = (event[2] << 4) | (event[3] & S6SY761_MASK_Y);
0150 
0151     input_mt_slot(sdata->input, tid);
0152 
0153     input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
0154     input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
0155     input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
0156     input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, major);
0157     input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, minor);
0158     input_report_abs(sdata->input, ABS_MT_PRESSURE, z);
0159 
0160     input_sync(sdata->input);
0161 }
0162 
0163 static void s6sy761_report_release(struct s6sy761_data *sdata,
0164                    u8 *event, u8 tid)
0165 {
0166     input_mt_slot(sdata->input, tid);
0167     input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, false);
0168 
0169     input_sync(sdata->input);
0170 }
0171 
0172 static void s6sy761_handle_coordinates(struct s6sy761_data *sdata, u8 *event)
0173 {
0174     u8 tid;
0175     u8 touch_state;
0176 
0177     if (unlikely(!(event[0] & S6SY761_MASK_TID)))
0178         return;
0179 
0180     tid = ((event[0] & S6SY761_MASK_TID) >> 2) - 1;
0181     touch_state = (event[0] & S6SY761_MASK_TOUCH_STATE) >> 6;
0182 
0183     switch (touch_state) {
0184 
0185     case S6SY761_TS_NONE:
0186         break;
0187     case S6SY761_TS_RELEASE:
0188         s6sy761_report_release(sdata, event, tid);
0189         break;
0190     case S6SY761_TS_PRESS:
0191     case S6SY761_TS_MOVE:
0192         s6sy761_report_coordinates(sdata, event, tid);
0193         break;
0194     }
0195 }
0196 
0197 static void s6sy761_handle_events(struct s6sy761_data *sdata, u8 n_events)
0198 {
0199     int i;
0200 
0201     for (i = 0; i < n_events; i++) {
0202         u8 *event = &sdata->data[i * S6SY761_EVENT_SIZE];
0203         u8 event_id = event[0] & S6SY761_MASK_EID;
0204 
0205         if (!event[0])
0206             return;
0207 
0208         switch (event_id) {
0209 
0210         case S6SY761_EVENT_ID_COORDINATE:
0211             s6sy761_handle_coordinates(sdata, event);
0212             break;
0213 
0214         case S6SY761_EVENT_ID_STATUS:
0215             break;
0216 
0217         default:
0218             break;
0219         }
0220     }
0221 }
0222 
0223 static irqreturn_t s6sy761_irq_handler(int irq, void *dev)
0224 {
0225     struct s6sy761_data *sdata = dev;
0226     int ret;
0227     u8 n_events;
0228 
0229     ret = i2c_smbus_read_i2c_block_data(sdata->client,
0230                         S6SY761_READ_ONE_EVENT,
0231                         S6SY761_EVENT_SIZE,
0232                         sdata->data);
0233     if (ret < 0) {
0234         dev_err(&sdata->client->dev, "failed to read events\n");
0235         return IRQ_HANDLED;
0236     }
0237 
0238     if (!sdata->data[0])
0239         return IRQ_HANDLED;
0240 
0241     n_events = sdata->data[7] & S6SY761_MASK_LEFT_EVENTS;
0242     if (unlikely(n_events > S6SY761_EVENT_COUNT - 1))
0243         return IRQ_HANDLED;
0244 
0245     if (n_events) {
0246         ret = s6sy761_read_events(sdata, n_events);
0247         if (ret < 0) {
0248             dev_err(&sdata->client->dev, "failed to read events\n");
0249             return IRQ_HANDLED;
0250         }
0251     }
0252 
0253     s6sy761_handle_events(sdata, n_events +  1);
0254 
0255     return IRQ_HANDLED;
0256 }
0257 
0258 static int s6sy761_input_open(struct input_dev *dev)
0259 {
0260     struct s6sy761_data *sdata = input_get_drvdata(dev);
0261 
0262     return i2c_smbus_write_byte(sdata->client, S6SY761_SENSE_ON);
0263 }
0264 
0265 static void s6sy761_input_close(struct input_dev *dev)
0266 {
0267     struct s6sy761_data *sdata = input_get_drvdata(dev);
0268     int ret;
0269 
0270     ret = i2c_smbus_write_byte(sdata->client, S6SY761_SENSE_OFF);
0271     if (ret)
0272         dev_err(&sdata->client->dev, "failed to turn off sensing\n");
0273 }
0274 
0275 static ssize_t s6sy761_sysfs_devid(struct device *dev,
0276                 struct device_attribute *attr, char *buf)
0277 {
0278     struct s6sy761_data *sdata = dev_get_drvdata(dev);
0279 
0280     return sprintf(buf, "%#x\n", sdata->devid);
0281 }
0282 
0283 static DEVICE_ATTR(devid, 0444, s6sy761_sysfs_devid, NULL);
0284 
0285 static struct attribute *s6sy761_sysfs_attrs[] = {
0286     &dev_attr_devid.attr,
0287     NULL
0288 };
0289 
0290 static struct attribute_group s6sy761_attribute_group = {
0291     .attrs = s6sy761_sysfs_attrs
0292 };
0293 
0294 static int s6sy761_power_on(struct s6sy761_data *sdata)
0295 {
0296     u8 buffer[S6SY761_EVENT_SIZE];
0297     u8 event;
0298     int ret;
0299 
0300     ret = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
0301                     sdata->regulators);
0302     if (ret)
0303         return ret;
0304 
0305     msleep(140);
0306 
0307     /* double check whether the touch is functional */
0308     ret = i2c_smbus_read_i2c_block_data(sdata->client,
0309                         S6SY761_READ_ONE_EVENT,
0310                         S6SY761_EVENT_SIZE,
0311                         buffer);
0312     if (ret < 0)
0313         return ret;
0314 
0315     event = (buffer[0] >> 2) & 0xf;
0316 
0317     if ((event != S6SY761_EVENT_INFO &&
0318          event != S6SY761_EVENT_VENDOR_INFO) ||
0319         buffer[1] != S6SY761_INFO_BOOT_COMPLETE) {
0320         return -ENODEV;
0321     }
0322 
0323     ret = i2c_smbus_read_byte_data(sdata->client, S6SY761_BOOT_STATUS);
0324     if (ret < 0)
0325         return ret;
0326 
0327     /* for some reasons the device might be stuck in the bootloader */
0328     if (ret != S6SY761_BS_APPLICATION)
0329         return -ENODEV;
0330 
0331     /* enable touch functionality */
0332     ret = i2c_smbus_write_word_data(sdata->client,
0333                     S6SY761_TOUCH_FUNCTION,
0334                     S6SY761_MASK_TOUCH);
0335     if (ret)
0336         return ret;
0337 
0338     return 0;
0339 }
0340 
0341 static int s6sy761_hw_init(struct s6sy761_data *sdata,
0342                unsigned int *max_x, unsigned int *max_y)
0343 {
0344     u8 buffer[S6SY761_PANEL_ID_SIZE]; /* larger read size */
0345     int ret;
0346 
0347     ret = s6sy761_power_on(sdata);
0348     if (ret)
0349         return ret;
0350 
0351     ret = i2c_smbus_read_i2c_block_data(sdata->client,
0352                         S6SY761_DEVICE_ID,
0353                         S6SY761_DEVID_SIZE,
0354                         buffer);
0355     if (ret < 0)
0356         return ret;
0357 
0358     sdata->devid = get_unaligned_be16(buffer + 1);
0359 
0360     ret = i2c_smbus_read_i2c_block_data(sdata->client,
0361                         S6SY761_PANEL_INFO,
0362                         S6SY761_PANEL_ID_SIZE,
0363                         buffer);
0364     if (ret < 0)
0365         return ret;
0366 
0367     *max_x = get_unaligned_be16(buffer);
0368     *max_y = get_unaligned_be16(buffer + 2);
0369 
0370     /* if no tx channels defined, at least keep one */
0371     sdata->tx_channel = max_t(u8, buffer[8], 1);
0372 
0373     ret = i2c_smbus_read_byte_data(sdata->client,
0374                        S6SY761_FIRMWARE_INTEGRITY);
0375     if (ret < 0)
0376         return ret;
0377     else if (ret != S6SY761_FW_OK)
0378         return -ENODEV;
0379 
0380     return 0;
0381 }
0382 
0383 static void s6sy761_power_off(void *data)
0384 {
0385     struct s6sy761_data *sdata = data;
0386 
0387     disable_irq(sdata->client->irq);
0388     regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
0389                         sdata->regulators);
0390 }
0391 
0392 static int s6sy761_probe(struct i2c_client *client,
0393              const struct i2c_device_id *id)
0394 {
0395     struct s6sy761_data *sdata;
0396     unsigned int max_x, max_y;
0397     int err;
0398 
0399     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
0400                         I2C_FUNC_SMBUS_BYTE_DATA |
0401                         I2C_FUNC_SMBUS_I2C_BLOCK))
0402         return -ENODEV;
0403 
0404     sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL);
0405     if (!sdata)
0406         return -ENOMEM;
0407 
0408     i2c_set_clientdata(client, sdata);
0409     sdata->client = client;
0410 
0411     sdata->regulators[S6SY761_REGULATOR_VDD].supply = "vdd";
0412     sdata->regulators[S6SY761_REGULATOR_AVDD].supply = "avdd";
0413     err = devm_regulator_bulk_get(&client->dev,
0414                       ARRAY_SIZE(sdata->regulators),
0415                       sdata->regulators);
0416     if (err)
0417         return err;
0418 
0419     err = devm_add_action_or_reset(&client->dev, s6sy761_power_off, sdata);
0420     if (err)
0421         return err;
0422 
0423     err = s6sy761_hw_init(sdata, &max_x, &max_y);
0424     if (err)
0425         return err;
0426 
0427     sdata->input = devm_input_allocate_device(&client->dev);
0428     if (!sdata->input)
0429         return -ENOMEM;
0430 
0431     sdata->input->name = S6SY761_DEV_NAME;
0432     sdata->input->id.bustype = BUS_I2C;
0433     sdata->input->open = s6sy761_input_open;
0434     sdata->input->close = s6sy761_input_close;
0435 
0436     input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
0437     input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
0438     input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
0439     input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
0440     input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
0441     input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
0442     input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
0443 
0444     touchscreen_parse_properties(sdata->input, true, &sdata->prop);
0445 
0446     if (!input_abs_get_max(sdata->input, ABS_X) ||
0447         !input_abs_get_max(sdata->input, ABS_Y)) {
0448         dev_warn(&client->dev, "the axis have not been set\n");
0449     }
0450 
0451     err = input_mt_init_slots(sdata->input, sdata->tx_channel,
0452                   INPUT_MT_DIRECT);
0453     if (err)
0454         return err;
0455 
0456     input_set_drvdata(sdata->input, sdata);
0457 
0458     err = input_register_device(sdata->input);
0459     if (err)
0460         return err;
0461 
0462     err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
0463                     s6sy761_irq_handler,
0464                     IRQF_TRIGGER_LOW | IRQF_ONESHOT,
0465                     "s6sy761_irq", sdata);
0466     if (err)
0467         return err;
0468 
0469     err = devm_device_add_group(&client->dev, &s6sy761_attribute_group);
0470     if (err)
0471         return err;
0472 
0473     pm_runtime_enable(&client->dev);
0474 
0475     return 0;
0476 }
0477 
0478 static int s6sy761_remove(struct i2c_client *client)
0479 {
0480     pm_runtime_disable(&client->dev);
0481 
0482     return 0;
0483 }
0484 
0485 static int __maybe_unused s6sy761_runtime_suspend(struct device *dev)
0486 {
0487     struct s6sy761_data *sdata = dev_get_drvdata(dev);
0488 
0489     return i2c_smbus_write_byte_data(sdata->client,
0490                 S6SY761_APPLICATION_MODE, S6SY761_APP_SLEEP);
0491 }
0492 
0493 static int __maybe_unused s6sy761_runtime_resume(struct device *dev)
0494 {
0495     struct s6sy761_data *sdata = dev_get_drvdata(dev);
0496 
0497     return i2c_smbus_write_byte_data(sdata->client,
0498                 S6SY761_APPLICATION_MODE, S6SY761_APP_NORMAL);
0499 }
0500 
0501 static int __maybe_unused s6sy761_suspend(struct device *dev)
0502 {
0503     struct s6sy761_data *sdata = dev_get_drvdata(dev);
0504 
0505     s6sy761_power_off(sdata);
0506 
0507     return 0;
0508 }
0509 
0510 static int __maybe_unused s6sy761_resume(struct device *dev)
0511 {
0512     struct s6sy761_data *sdata = dev_get_drvdata(dev);
0513 
0514     enable_irq(sdata->client->irq);
0515 
0516     return s6sy761_power_on(sdata);
0517 }
0518 
0519 static const struct dev_pm_ops s6sy761_pm_ops = {
0520     SET_SYSTEM_SLEEP_PM_OPS(s6sy761_suspend, s6sy761_resume)
0521     SET_RUNTIME_PM_OPS(s6sy761_runtime_suspend,
0522                 s6sy761_runtime_resume, NULL)
0523 };
0524 
0525 #ifdef CONFIG_OF
0526 static const struct of_device_id s6sy761_of_match[] = {
0527     { .compatible = "samsung,s6sy761", },
0528     { },
0529 };
0530 MODULE_DEVICE_TABLE(of, s6sy761_of_match);
0531 #endif
0532 
0533 static const struct i2c_device_id s6sy761_id[] = {
0534     { "s6sy761", 0 },
0535     { },
0536 };
0537 MODULE_DEVICE_TABLE(i2c, s6sy761_id);
0538 
0539 static struct i2c_driver s6sy761_driver = {
0540     .driver = {
0541         .name = S6SY761_DEV_NAME,
0542         .of_match_table = of_match_ptr(s6sy761_of_match),
0543         .pm = &s6sy761_pm_ops,
0544     },
0545     .probe = s6sy761_probe,
0546     .remove = s6sy761_remove,
0547     .id_table = s6sy761_id,
0548 };
0549 
0550 module_i2c_driver(s6sy761_driver);
0551 
0552 MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
0553 MODULE_DESCRIPTION("Samsung S6SY761 Touch Screen");
0554 MODULE_LICENSE("GPL v2");