0001
0002
0003
0004
0005
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
0019 #define S6SY761_SENSE_ON 0x10
0020 #define S6SY761_SENSE_OFF 0x11
0021 #define S6SY761_TOUCH_FUNCTION 0x30
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
0032 #define S6SY761_EVENT_INFO 0x02
0033 #define S6SY761_EVENT_VENDOR_INFO 0x07
0034
0035
0036 #define S6SY761_INFO_BOOT_COMPLETE 0x00
0037
0038
0039 #define S6SY761_FW_OK 0x80
0040
0041
0042
0043
0044
0045
0046
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
0057 #define S6SY761_BS_BOOT_LOADER 0x10
0058 #define S6SY761_BS_APPLICATION 0x20
0059
0060
0061 #define S6SY761_EVENT_ID_COORDINATE 0x00
0062 #define S6SY761_EVENT_ID_STATUS 0x01
0063
0064
0065 #define S6SY761_MASK_TOUCH_STATE 0xc0
0066 #define S6SY761_MASK_TID 0x3c
0067 #define S6SY761_MASK_EID 0x03
0068 #define S6SY761_MASK_X 0xf0
0069 #define S6SY761_MASK_Y 0x0f
0070 #define S6SY761_MASK_Z 0x3f
0071 #define S6SY761_MASK_LEFT_EVENTS 0x3f
0072 #define S6SY761_MASK_TOUCH_TYPE 0xc0
0073
0074
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
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
0115
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
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
0328 if (ret != S6SY761_BS_APPLICATION)
0329 return -ENODEV;
0330
0331
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];
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
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");