1f8c5938fSAndi Shyti // SPDX-License-Identifier: GPL-2.0 2f8c5938fSAndi Shyti // STMicroelectronics FTS Touchscreen device driver 3f8c5938fSAndi Shyti // 4f8c5938fSAndi Shyti // Copyright (c) 2017 Samsung Electronics Co., Ltd. 5adf313f4SAndi Shyti // Copyright (c) 2017 Andi Shyti <andi@etezian.org> 678bcac7bSAndi Shyti 778bcac7bSAndi Shyti #include <linux/delay.h> 878bcac7bSAndi Shyti #include <linux/i2c.h> 978bcac7bSAndi Shyti #include <linux/input/mt.h> 1078bcac7bSAndi Shyti #include <linux/input/touchscreen.h> 1178bcac7bSAndi Shyti #include <linux/interrupt.h> 1278bcac7bSAndi Shyti #include <linux/irq.h> 1378bcac7bSAndi Shyti #include <linux/leds.h> 1478bcac7bSAndi Shyti #include <linux/module.h> 1578bcac7bSAndi Shyti #include <linux/pm_runtime.h> 1678bcac7bSAndi Shyti #include <linux/regulator/consumer.h> 1778bcac7bSAndi Shyti 1878bcac7bSAndi Shyti /* I2C commands */ 1978bcac7bSAndi Shyti #define STMFTS_READ_INFO 0x80 2078bcac7bSAndi Shyti #define STMFTS_READ_STATUS 0x84 2178bcac7bSAndi Shyti #define STMFTS_READ_ONE_EVENT 0x85 2278bcac7bSAndi Shyti #define STMFTS_READ_ALL_EVENT 0x86 2378bcac7bSAndi Shyti #define STMFTS_LATEST_EVENT 0x87 2478bcac7bSAndi Shyti #define STMFTS_SLEEP_IN 0x90 2578bcac7bSAndi Shyti #define STMFTS_SLEEP_OUT 0x91 2678bcac7bSAndi Shyti #define STMFTS_MS_MT_SENSE_OFF 0x92 2778bcac7bSAndi Shyti #define STMFTS_MS_MT_SENSE_ON 0x93 2878bcac7bSAndi Shyti #define STMFTS_SS_HOVER_SENSE_OFF 0x94 2978bcac7bSAndi Shyti #define STMFTS_SS_HOVER_SENSE_ON 0x95 3078bcac7bSAndi Shyti #define STMFTS_MS_KEY_SENSE_OFF 0x9a 3178bcac7bSAndi Shyti #define STMFTS_MS_KEY_SENSE_ON 0x9b 3278bcac7bSAndi Shyti #define STMFTS_SYSTEM_RESET 0xa0 3378bcac7bSAndi Shyti #define STMFTS_CLEAR_EVENT_STACK 0xa1 3478bcac7bSAndi Shyti #define STMFTS_FULL_FORCE_CALIBRATION 0xa2 3578bcac7bSAndi Shyti #define STMFTS_MS_CX_TUNING 0xa3 3678bcac7bSAndi Shyti #define STMFTS_SS_CX_TUNING 0xa4 3778bcac7bSAndi Shyti 3878bcac7bSAndi Shyti /* events */ 3978bcac7bSAndi Shyti #define STMFTS_EV_NO_EVENT 0x00 4078bcac7bSAndi Shyti #define STMFTS_EV_MULTI_TOUCH_DETECTED 0x02 4178bcac7bSAndi Shyti #define STMFTS_EV_MULTI_TOUCH_ENTER 0x03 4278bcac7bSAndi Shyti #define STMFTS_EV_MULTI_TOUCH_LEAVE 0x04 4378bcac7bSAndi Shyti #define STMFTS_EV_MULTI_TOUCH_MOTION 0x05 4478bcac7bSAndi Shyti #define STMFTS_EV_HOVER_ENTER 0x07 4578bcac7bSAndi Shyti #define STMFTS_EV_HOVER_LEAVE 0x08 4678bcac7bSAndi Shyti #define STMFTS_EV_HOVER_MOTION 0x09 4778bcac7bSAndi Shyti #define STMFTS_EV_KEY_STATUS 0x0e 4878bcac7bSAndi Shyti #define STMFTS_EV_ERROR 0x0f 4978bcac7bSAndi Shyti #define STMFTS_EV_CONTROLLER_READY 0x10 5078bcac7bSAndi Shyti #define STMFTS_EV_SLEEP_OUT_CONTROLLER_READY 0x11 5178bcac7bSAndi Shyti #define STMFTS_EV_STATUS 0x16 5278bcac7bSAndi Shyti #define STMFTS_EV_DEBUG 0xdb 5378bcac7bSAndi Shyti 5478bcac7bSAndi Shyti /* multi touch related event masks */ 5578bcac7bSAndi Shyti #define STMFTS_MASK_EVENT_ID 0x0f 5678bcac7bSAndi Shyti #define STMFTS_MASK_TOUCH_ID 0xf0 5778bcac7bSAndi Shyti #define STMFTS_MASK_LEFT_EVENT 0x0f 5878bcac7bSAndi Shyti #define STMFTS_MASK_X_MSB 0x0f 5978bcac7bSAndi Shyti #define STMFTS_MASK_Y_LSB 0xf0 6078bcac7bSAndi Shyti 6178bcac7bSAndi Shyti /* key related event masks */ 6278bcac7bSAndi Shyti #define STMFTS_MASK_KEY_NO_TOUCH 0x00 6378bcac7bSAndi Shyti #define STMFTS_MASK_KEY_MENU 0x01 6478bcac7bSAndi Shyti #define STMFTS_MASK_KEY_BACK 0x02 6578bcac7bSAndi Shyti 6678bcac7bSAndi Shyti #define STMFTS_EVENT_SIZE 8 6778bcac7bSAndi Shyti #define STMFTS_STACK_DEPTH 32 6878bcac7bSAndi Shyti #define STMFTS_DATA_MAX_SIZE (STMFTS_EVENT_SIZE * STMFTS_STACK_DEPTH) 6978bcac7bSAndi Shyti #define STMFTS_MAX_FINGERS 10 7078bcac7bSAndi Shyti #define STMFTS_DEV_NAME "stmfts" 7178bcac7bSAndi Shyti 7278bcac7bSAndi Shyti enum stmfts_regulators { 7378bcac7bSAndi Shyti STMFTS_REGULATOR_VDD, 7478bcac7bSAndi Shyti STMFTS_REGULATOR_AVDD, 7578bcac7bSAndi Shyti }; 7678bcac7bSAndi Shyti 7778bcac7bSAndi Shyti struct stmfts_data { 7878bcac7bSAndi Shyti struct i2c_client *client; 7978bcac7bSAndi Shyti struct input_dev *input; 8078bcac7bSAndi Shyti struct led_classdev led_cdev; 8178bcac7bSAndi Shyti struct mutex mutex; 8278bcac7bSAndi Shyti 8378bcac7bSAndi Shyti struct touchscreen_properties prop; 8478bcac7bSAndi Shyti 8578bcac7bSAndi Shyti struct regulator_bulk_data regulators[2]; 8678bcac7bSAndi Shyti 8778bcac7bSAndi Shyti /* 8878bcac7bSAndi Shyti * Presence of ledvdd will be used also to check 8978bcac7bSAndi Shyti * whether the LED is supported. 9078bcac7bSAndi Shyti */ 9178bcac7bSAndi Shyti struct regulator *ledvdd; 9278bcac7bSAndi Shyti 9378bcac7bSAndi Shyti u16 chip_id; 9478bcac7bSAndi Shyti u8 chip_ver; 9578bcac7bSAndi Shyti u16 fw_ver; 9678bcac7bSAndi Shyti u8 config_id; 9778bcac7bSAndi Shyti u8 config_ver; 9878bcac7bSAndi Shyti 9978bcac7bSAndi Shyti u8 data[STMFTS_DATA_MAX_SIZE]; 10078bcac7bSAndi Shyti 10178bcac7bSAndi Shyti struct completion cmd_done; 10278bcac7bSAndi Shyti 10378bcac7bSAndi Shyti bool use_key; 10478bcac7bSAndi Shyti bool led_status; 10578bcac7bSAndi Shyti bool hover_enabled; 10678bcac7bSAndi Shyti bool running; 10778bcac7bSAndi Shyti }; 10878bcac7bSAndi Shyti 109937c4e55SDmitry Torokhov static int stmfts_brightness_set(struct led_classdev *led_cdev, 11078bcac7bSAndi Shyti enum led_brightness value) 11178bcac7bSAndi Shyti { 11278bcac7bSAndi Shyti struct stmfts_data *sdata = container_of(led_cdev, 11378bcac7bSAndi Shyti struct stmfts_data, led_cdev); 11478bcac7bSAndi Shyti int err; 11578bcac7bSAndi Shyti 116937c4e55SDmitry Torokhov if (value != sdata->led_status && sdata->ledvdd) { 11778bcac7bSAndi Shyti if (!value) { 11878bcac7bSAndi Shyti regulator_disable(sdata->ledvdd); 11978bcac7bSAndi Shyti } else { 12078bcac7bSAndi Shyti err = regulator_enable(sdata->ledvdd); 121937c4e55SDmitry Torokhov if (err) { 12278bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 12378bcac7bSAndi Shyti "failed to disable ledvdd regulator: %d\n", 12478bcac7bSAndi Shyti err); 125937c4e55SDmitry Torokhov return err; 126937c4e55SDmitry Torokhov } 127937c4e55SDmitry Torokhov } 128937c4e55SDmitry Torokhov sdata->led_status = value; 12978bcac7bSAndi Shyti } 13078bcac7bSAndi Shyti 131937c4e55SDmitry Torokhov return 0; 13278bcac7bSAndi Shyti } 13378bcac7bSAndi Shyti 13478bcac7bSAndi Shyti static enum led_brightness stmfts_brightness_get(struct led_classdev *led_cdev) 13578bcac7bSAndi Shyti { 13678bcac7bSAndi Shyti struct stmfts_data *sdata = container_of(led_cdev, 13778bcac7bSAndi Shyti struct stmfts_data, led_cdev); 13878bcac7bSAndi Shyti 13978bcac7bSAndi Shyti return !!regulator_is_enabled(sdata->ledvdd); 14078bcac7bSAndi Shyti } 14178bcac7bSAndi Shyti 14278bcac7bSAndi Shyti /* 14378bcac7bSAndi Shyti * We can't simply use i2c_smbus_read_i2c_block_data because we 14478bcac7bSAndi Shyti * need to read more than 255 bytes ( 14578bcac7bSAndi Shyti */ 14678bcac7bSAndi Shyti static int stmfts_read_events(struct stmfts_data *sdata) 14778bcac7bSAndi Shyti { 14878bcac7bSAndi Shyti u8 cmd = STMFTS_READ_ALL_EVENT; 14978bcac7bSAndi Shyti struct i2c_msg msgs[2] = { 15078bcac7bSAndi Shyti { 15178bcac7bSAndi Shyti .addr = sdata->client->addr, 15278bcac7bSAndi Shyti .len = 1, 15378bcac7bSAndi Shyti .buf = &cmd, 15478bcac7bSAndi Shyti }, 15578bcac7bSAndi Shyti { 15678bcac7bSAndi Shyti .addr = sdata->client->addr, 15778bcac7bSAndi Shyti .flags = I2C_M_RD, 15878bcac7bSAndi Shyti .len = STMFTS_DATA_MAX_SIZE, 15978bcac7bSAndi Shyti .buf = sdata->data, 16078bcac7bSAndi Shyti }, 16178bcac7bSAndi Shyti }; 16278bcac7bSAndi Shyti int ret; 16378bcac7bSAndi Shyti 16478bcac7bSAndi Shyti ret = i2c_transfer(sdata->client->adapter, msgs, ARRAY_SIZE(msgs)); 16578bcac7bSAndi Shyti if (ret < 0) 16678bcac7bSAndi Shyti return ret; 16778bcac7bSAndi Shyti 16878bcac7bSAndi Shyti return ret == ARRAY_SIZE(msgs) ? 0 : -EIO; 16978bcac7bSAndi Shyti } 17078bcac7bSAndi Shyti 17178bcac7bSAndi Shyti static void stmfts_report_contact_event(struct stmfts_data *sdata, 17278bcac7bSAndi Shyti const u8 event[]) 17378bcac7bSAndi Shyti { 17478bcac7bSAndi Shyti u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4; 17578bcac7bSAndi Shyti u16 x = event[1] | ((event[2] & STMFTS_MASK_X_MSB) << 8); 17678bcac7bSAndi Shyti u16 y = (event[2] >> 4) | (event[3] << 4); 17778bcac7bSAndi Shyti u8 maj = event[4]; 17878bcac7bSAndi Shyti u8 min = event[5]; 17978bcac7bSAndi Shyti u8 orientation = event[6]; 18078bcac7bSAndi Shyti u8 area = event[7]; 18178bcac7bSAndi Shyti 18278bcac7bSAndi Shyti input_mt_slot(sdata->input, slot_id); 18378bcac7bSAndi Shyti 18478bcac7bSAndi Shyti input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true); 18578bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_MT_POSITION_X, x); 18678bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_MT_POSITION_Y, y); 18778bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, maj); 18878bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, min); 18978bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_MT_PRESSURE, area); 19078bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_MT_ORIENTATION, orientation); 19178bcac7bSAndi Shyti 19278bcac7bSAndi Shyti input_sync(sdata->input); 19378bcac7bSAndi Shyti } 19478bcac7bSAndi Shyti 19578bcac7bSAndi Shyti static void stmfts_report_contact_release(struct stmfts_data *sdata, 19678bcac7bSAndi Shyti const u8 event[]) 19778bcac7bSAndi Shyti { 19878bcac7bSAndi Shyti u8 slot_id = (event[0] & STMFTS_MASK_TOUCH_ID) >> 4; 19978bcac7bSAndi Shyti 20078bcac7bSAndi Shyti input_mt_slot(sdata->input, slot_id); 2015fc70e35SJiada Wang input_mt_report_slot_inactive(sdata->input); 20278bcac7bSAndi Shyti 20378bcac7bSAndi Shyti input_sync(sdata->input); 20478bcac7bSAndi Shyti } 20578bcac7bSAndi Shyti 20678bcac7bSAndi Shyti static void stmfts_report_hover_event(struct stmfts_data *sdata, 20778bcac7bSAndi Shyti const u8 event[]) 20878bcac7bSAndi Shyti { 20978bcac7bSAndi Shyti u16 x = (event[2] << 4) | (event[4] >> 4); 21078bcac7bSAndi Shyti u16 y = (event[3] << 4) | (event[4] & STMFTS_MASK_Y_LSB); 21178bcac7bSAndi Shyti u8 z = event[5]; 21278bcac7bSAndi Shyti 21378bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_X, x); 21478bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_Y, y); 21578bcac7bSAndi Shyti input_report_abs(sdata->input, ABS_DISTANCE, z); 21678bcac7bSAndi Shyti 21778bcac7bSAndi Shyti input_sync(sdata->input); 21878bcac7bSAndi Shyti } 21978bcac7bSAndi Shyti 22078bcac7bSAndi Shyti static void stmfts_report_key_event(struct stmfts_data *sdata, const u8 event[]) 22178bcac7bSAndi Shyti { 22278bcac7bSAndi Shyti switch (event[2]) { 22378bcac7bSAndi Shyti case 0: 22478bcac7bSAndi Shyti input_report_key(sdata->input, KEY_BACK, 0); 22578bcac7bSAndi Shyti input_report_key(sdata->input, KEY_MENU, 0); 22678bcac7bSAndi Shyti break; 22778bcac7bSAndi Shyti 22878bcac7bSAndi Shyti case STMFTS_MASK_KEY_BACK: 22978bcac7bSAndi Shyti input_report_key(sdata->input, KEY_BACK, 1); 23078bcac7bSAndi Shyti break; 23178bcac7bSAndi Shyti 23278bcac7bSAndi Shyti case STMFTS_MASK_KEY_MENU: 23378bcac7bSAndi Shyti input_report_key(sdata->input, KEY_MENU, 1); 23478bcac7bSAndi Shyti break; 23578bcac7bSAndi Shyti 23678bcac7bSAndi Shyti default: 23778bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 23878bcac7bSAndi Shyti "unknown key event: %#02x\n", event[2]); 23978bcac7bSAndi Shyti break; 24078bcac7bSAndi Shyti } 24178bcac7bSAndi Shyti 24278bcac7bSAndi Shyti input_sync(sdata->input); 24378bcac7bSAndi Shyti } 24478bcac7bSAndi Shyti 24578bcac7bSAndi Shyti static void stmfts_parse_events(struct stmfts_data *sdata) 24678bcac7bSAndi Shyti { 24778bcac7bSAndi Shyti int i; 24878bcac7bSAndi Shyti 24978bcac7bSAndi Shyti for (i = 0; i < STMFTS_STACK_DEPTH; i++) { 25078bcac7bSAndi Shyti u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE]; 25178bcac7bSAndi Shyti 25278bcac7bSAndi Shyti switch (event[0]) { 25378bcac7bSAndi Shyti 25478bcac7bSAndi Shyti case STMFTS_EV_CONTROLLER_READY: 25578bcac7bSAndi Shyti case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY: 25678bcac7bSAndi Shyti case STMFTS_EV_STATUS: 25778bcac7bSAndi Shyti complete(&sdata->cmd_done); 2586f49c4f5SGustavo A. R. Silva fallthrough; 25978bcac7bSAndi Shyti 26078bcac7bSAndi Shyti case STMFTS_EV_NO_EVENT: 26178bcac7bSAndi Shyti case STMFTS_EV_DEBUG: 26278bcac7bSAndi Shyti return; 26378bcac7bSAndi Shyti } 26478bcac7bSAndi Shyti 26578bcac7bSAndi Shyti switch (event[0] & STMFTS_MASK_EVENT_ID) { 26678bcac7bSAndi Shyti 26778bcac7bSAndi Shyti case STMFTS_EV_MULTI_TOUCH_ENTER: 26878bcac7bSAndi Shyti case STMFTS_EV_MULTI_TOUCH_MOTION: 26978bcac7bSAndi Shyti stmfts_report_contact_event(sdata, event); 27078bcac7bSAndi Shyti break; 27178bcac7bSAndi Shyti 27278bcac7bSAndi Shyti case STMFTS_EV_MULTI_TOUCH_LEAVE: 27378bcac7bSAndi Shyti stmfts_report_contact_release(sdata, event); 27478bcac7bSAndi Shyti break; 27578bcac7bSAndi Shyti 27678bcac7bSAndi Shyti case STMFTS_EV_HOVER_ENTER: 27778bcac7bSAndi Shyti case STMFTS_EV_HOVER_LEAVE: 27878bcac7bSAndi Shyti case STMFTS_EV_HOVER_MOTION: 27978bcac7bSAndi Shyti stmfts_report_hover_event(sdata, event); 28078bcac7bSAndi Shyti break; 28178bcac7bSAndi Shyti 28278bcac7bSAndi Shyti case STMFTS_EV_KEY_STATUS: 28378bcac7bSAndi Shyti stmfts_report_key_event(sdata, event); 28478bcac7bSAndi Shyti break; 28578bcac7bSAndi Shyti 28678bcac7bSAndi Shyti case STMFTS_EV_ERROR: 28778bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 28878bcac7bSAndi Shyti "error code: 0x%x%x%x%x%x%x", 28978bcac7bSAndi Shyti event[6], event[5], event[4], 29078bcac7bSAndi Shyti event[3], event[2], event[1]); 29178bcac7bSAndi Shyti break; 29278bcac7bSAndi Shyti 29378bcac7bSAndi Shyti default: 29478bcac7bSAndi Shyti dev_err(&sdata->client->dev, 29578bcac7bSAndi Shyti "unknown event %#02x\n", event[0]); 29678bcac7bSAndi Shyti } 29778bcac7bSAndi Shyti } 29878bcac7bSAndi Shyti } 29978bcac7bSAndi Shyti 30078bcac7bSAndi Shyti static irqreturn_t stmfts_irq_handler(int irq, void *dev) 30178bcac7bSAndi Shyti { 30278bcac7bSAndi Shyti struct stmfts_data *sdata = dev; 30378bcac7bSAndi Shyti int err; 30478bcac7bSAndi Shyti 30578bcac7bSAndi Shyti mutex_lock(&sdata->mutex); 30678bcac7bSAndi Shyti 30778bcac7bSAndi Shyti err = stmfts_read_events(sdata); 30878bcac7bSAndi Shyti if (unlikely(err)) 30978bcac7bSAndi Shyti dev_err(&sdata->client->dev, 31078bcac7bSAndi Shyti "failed to read events: %d\n", err); 31178bcac7bSAndi Shyti else 31278bcac7bSAndi Shyti stmfts_parse_events(sdata); 31378bcac7bSAndi Shyti 31478bcac7bSAndi Shyti mutex_unlock(&sdata->mutex); 31578bcac7bSAndi Shyti return IRQ_HANDLED; 31678bcac7bSAndi Shyti } 31778bcac7bSAndi Shyti 31878bcac7bSAndi Shyti static int stmfts_command(struct stmfts_data *sdata, const u8 cmd) 31978bcac7bSAndi Shyti { 32078bcac7bSAndi Shyti int err; 32178bcac7bSAndi Shyti 32278bcac7bSAndi Shyti reinit_completion(&sdata->cmd_done); 32378bcac7bSAndi Shyti 32478bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, cmd); 32578bcac7bSAndi Shyti if (err) 32678bcac7bSAndi Shyti return err; 32778bcac7bSAndi Shyti 32878bcac7bSAndi Shyti if (!wait_for_completion_timeout(&sdata->cmd_done, 32978bcac7bSAndi Shyti msecs_to_jiffies(1000))) 33078bcac7bSAndi Shyti return -ETIMEDOUT; 33178bcac7bSAndi Shyti 33278bcac7bSAndi Shyti return 0; 33378bcac7bSAndi Shyti } 33478bcac7bSAndi Shyti 33578bcac7bSAndi Shyti static int stmfts_input_open(struct input_dev *dev) 33678bcac7bSAndi Shyti { 33778bcac7bSAndi Shyti struct stmfts_data *sdata = input_get_drvdata(dev); 33878bcac7bSAndi Shyti int err; 33978bcac7bSAndi Shyti 34078bcac7bSAndi Shyti err = pm_runtime_get_sync(&sdata->client->dev); 34178bcac7bSAndi Shyti if (err < 0) 34278bcac7bSAndi Shyti return err; 34378bcac7bSAndi Shyti 34478bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_ON); 34578bcac7bSAndi Shyti if (err) 34678bcac7bSAndi Shyti return err; 34778bcac7bSAndi Shyti 34878bcac7bSAndi Shyti mutex_lock(&sdata->mutex); 34978bcac7bSAndi Shyti sdata->running = true; 35078bcac7bSAndi Shyti 35178bcac7bSAndi Shyti if (sdata->hover_enabled) { 35278bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, 35378bcac7bSAndi Shyti STMFTS_SS_HOVER_SENSE_ON); 35478bcac7bSAndi Shyti if (err) 35578bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 35678bcac7bSAndi Shyti "failed to enable hover\n"); 35778bcac7bSAndi Shyti } 35878bcac7bSAndi Shyti mutex_unlock(&sdata->mutex); 35978bcac7bSAndi Shyti 36078bcac7bSAndi Shyti if (sdata->use_key) { 36178bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, 36278bcac7bSAndi Shyti STMFTS_MS_KEY_SENSE_ON); 36378bcac7bSAndi Shyti if (err) 36478bcac7bSAndi Shyti /* I can still use only the touch screen */ 36578bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 36678bcac7bSAndi Shyti "failed to enable touchkey\n"); 36778bcac7bSAndi Shyti } 36878bcac7bSAndi Shyti 36978bcac7bSAndi Shyti return 0; 37078bcac7bSAndi Shyti } 37178bcac7bSAndi Shyti 37278bcac7bSAndi Shyti static void stmfts_input_close(struct input_dev *dev) 37378bcac7bSAndi Shyti { 37478bcac7bSAndi Shyti struct stmfts_data *sdata = input_get_drvdata(dev); 37578bcac7bSAndi Shyti int err; 37678bcac7bSAndi Shyti 37778bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_OFF); 37878bcac7bSAndi Shyti if (err) 37978bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 38078bcac7bSAndi Shyti "failed to disable touchscreen: %d\n", err); 38178bcac7bSAndi Shyti 38278bcac7bSAndi Shyti mutex_lock(&sdata->mutex); 38378bcac7bSAndi Shyti 38478bcac7bSAndi Shyti sdata->running = false; 38578bcac7bSAndi Shyti 38678bcac7bSAndi Shyti if (sdata->hover_enabled) { 38778bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, 38878bcac7bSAndi Shyti STMFTS_SS_HOVER_SENSE_OFF); 38978bcac7bSAndi Shyti if (err) 39078bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 39178bcac7bSAndi Shyti "failed to disable hover: %d\n", err); 39278bcac7bSAndi Shyti } 39378bcac7bSAndi Shyti mutex_unlock(&sdata->mutex); 39478bcac7bSAndi Shyti 39578bcac7bSAndi Shyti if (sdata->use_key) { 39678bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, 39778bcac7bSAndi Shyti STMFTS_MS_KEY_SENSE_OFF); 39878bcac7bSAndi Shyti if (err) 39978bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 40078bcac7bSAndi Shyti "failed to disable touchkey: %d\n", err); 40178bcac7bSAndi Shyti } 40278bcac7bSAndi Shyti 40378bcac7bSAndi Shyti pm_runtime_put_sync(&sdata->client->dev); 40478bcac7bSAndi Shyti } 40578bcac7bSAndi Shyti 40678bcac7bSAndi Shyti static ssize_t stmfts_sysfs_chip_id(struct device *dev, 40778bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 40878bcac7bSAndi Shyti { 40978bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 41078bcac7bSAndi Shyti 41178bcac7bSAndi Shyti return sprintf(buf, "%#x\n", sdata->chip_id); 41278bcac7bSAndi Shyti } 41378bcac7bSAndi Shyti 41478bcac7bSAndi Shyti static ssize_t stmfts_sysfs_chip_version(struct device *dev, 41578bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 41678bcac7bSAndi Shyti { 41778bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 41878bcac7bSAndi Shyti 41978bcac7bSAndi Shyti return sprintf(buf, "%u\n", sdata->chip_ver); 42078bcac7bSAndi Shyti } 42178bcac7bSAndi Shyti 42278bcac7bSAndi Shyti static ssize_t stmfts_sysfs_fw_ver(struct device *dev, 42378bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 42478bcac7bSAndi Shyti { 42578bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 42678bcac7bSAndi Shyti 42778bcac7bSAndi Shyti return sprintf(buf, "%u\n", sdata->fw_ver); 42878bcac7bSAndi Shyti } 42978bcac7bSAndi Shyti 43078bcac7bSAndi Shyti static ssize_t stmfts_sysfs_config_id(struct device *dev, 43178bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 43278bcac7bSAndi Shyti { 43378bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 43478bcac7bSAndi Shyti 43578bcac7bSAndi Shyti return sprintf(buf, "%#x\n", sdata->config_id); 43678bcac7bSAndi Shyti } 43778bcac7bSAndi Shyti 43878bcac7bSAndi Shyti static ssize_t stmfts_sysfs_config_version(struct device *dev, 43978bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 44078bcac7bSAndi Shyti { 44178bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 44278bcac7bSAndi Shyti 44378bcac7bSAndi Shyti return sprintf(buf, "%u\n", sdata->config_ver); 44478bcac7bSAndi Shyti } 44578bcac7bSAndi Shyti 44678bcac7bSAndi Shyti static ssize_t stmfts_sysfs_read_status(struct device *dev, 44778bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 44878bcac7bSAndi Shyti { 44978bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 45078bcac7bSAndi Shyti u8 status[4]; 45178bcac7bSAndi Shyti int err; 45278bcac7bSAndi Shyti 45378bcac7bSAndi Shyti err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_STATUS, 45478bcac7bSAndi Shyti sizeof(status), status); 45578bcac7bSAndi Shyti if (err) 45678bcac7bSAndi Shyti return err; 45778bcac7bSAndi Shyti 45878bcac7bSAndi Shyti return sprintf(buf, "%#02x\n", status[0]); 45978bcac7bSAndi Shyti } 46078bcac7bSAndi Shyti 46178bcac7bSAndi Shyti static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev, 46278bcac7bSAndi Shyti struct device_attribute *attr, char *buf) 46378bcac7bSAndi Shyti { 46478bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 46578bcac7bSAndi Shyti 46678bcac7bSAndi Shyti return sprintf(buf, "%u\n", sdata->hover_enabled); 46778bcac7bSAndi Shyti } 46878bcac7bSAndi Shyti 46978bcac7bSAndi Shyti static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev, 47078bcac7bSAndi Shyti struct device_attribute *attr, 47178bcac7bSAndi Shyti const char *buf, size_t len) 47278bcac7bSAndi Shyti { 47378bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 47478bcac7bSAndi Shyti unsigned long value; 47578bcac7bSAndi Shyti int err = 0; 47678bcac7bSAndi Shyti 47778bcac7bSAndi Shyti if (kstrtoul(buf, 0, &value)) 47878bcac7bSAndi Shyti return -EINVAL; 47978bcac7bSAndi Shyti 48078bcac7bSAndi Shyti mutex_lock(&sdata->mutex); 48178bcac7bSAndi Shyti 482*d04afe14SYueHaibing if (value && sdata->hover_enabled) 48378bcac7bSAndi Shyti goto out; 48478bcac7bSAndi Shyti 48578bcac7bSAndi Shyti if (sdata->running) 48678bcac7bSAndi Shyti err = i2c_smbus_write_byte(sdata->client, 48778bcac7bSAndi Shyti value ? STMFTS_SS_HOVER_SENSE_ON : 48878bcac7bSAndi Shyti STMFTS_SS_HOVER_SENSE_OFF); 48978bcac7bSAndi Shyti 49078bcac7bSAndi Shyti if (!err) 49178bcac7bSAndi Shyti sdata->hover_enabled = !!value; 49278bcac7bSAndi Shyti 49378bcac7bSAndi Shyti out: 49478bcac7bSAndi Shyti mutex_unlock(&sdata->mutex); 49578bcac7bSAndi Shyti 49678bcac7bSAndi Shyti return len; 49778bcac7bSAndi Shyti } 49878bcac7bSAndi Shyti 49978bcac7bSAndi Shyti static DEVICE_ATTR(chip_id, 0444, stmfts_sysfs_chip_id, NULL); 50078bcac7bSAndi Shyti static DEVICE_ATTR(chip_version, 0444, stmfts_sysfs_chip_version, NULL); 50178bcac7bSAndi Shyti static DEVICE_ATTR(fw_ver, 0444, stmfts_sysfs_fw_ver, NULL); 50278bcac7bSAndi Shyti static DEVICE_ATTR(config_id, 0444, stmfts_sysfs_config_id, NULL); 50378bcac7bSAndi Shyti static DEVICE_ATTR(config_version, 0444, stmfts_sysfs_config_version, NULL); 50478bcac7bSAndi Shyti static DEVICE_ATTR(status, 0444, stmfts_sysfs_read_status, NULL); 50578bcac7bSAndi Shyti static DEVICE_ATTR(hover_enable, 0644, stmfts_sysfs_hover_enable_read, 50678bcac7bSAndi Shyti stmfts_sysfs_hover_enable_write); 50778bcac7bSAndi Shyti 50878bcac7bSAndi Shyti static struct attribute *stmfts_sysfs_attrs[] = { 50978bcac7bSAndi Shyti &dev_attr_chip_id.attr, 51078bcac7bSAndi Shyti &dev_attr_chip_version.attr, 51178bcac7bSAndi Shyti &dev_attr_fw_ver.attr, 51278bcac7bSAndi Shyti &dev_attr_config_id.attr, 51378bcac7bSAndi Shyti &dev_attr_config_version.attr, 51478bcac7bSAndi Shyti &dev_attr_status.attr, 51578bcac7bSAndi Shyti &dev_attr_hover_enable.attr, 51678bcac7bSAndi Shyti NULL 51778bcac7bSAndi Shyti }; 51878bcac7bSAndi Shyti 51978bcac7bSAndi Shyti static struct attribute_group stmfts_attribute_group = { 52078bcac7bSAndi Shyti .attrs = stmfts_sysfs_attrs 52178bcac7bSAndi Shyti }; 52278bcac7bSAndi Shyti 52378bcac7bSAndi Shyti static int stmfts_power_on(struct stmfts_data *sdata) 52478bcac7bSAndi Shyti { 52578bcac7bSAndi Shyti int err; 52678bcac7bSAndi Shyti u8 reg[8]; 52778bcac7bSAndi Shyti 52878bcac7bSAndi Shyti err = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators), 52978bcac7bSAndi Shyti sdata->regulators); 53078bcac7bSAndi Shyti if (err) 53178bcac7bSAndi Shyti return err; 53278bcac7bSAndi Shyti 53378bcac7bSAndi Shyti /* 53478bcac7bSAndi Shyti * The datasheet does not specify the power on time, but considering 53578bcac7bSAndi Shyti * that the reset time is < 10ms, I sleep 20ms to be sure 53678bcac7bSAndi Shyti */ 53778bcac7bSAndi Shyti msleep(20); 53878bcac7bSAndi Shyti 53978bcac7bSAndi Shyti err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_INFO, 54078bcac7bSAndi Shyti sizeof(reg), reg); 54178bcac7bSAndi Shyti if (err < 0) 54278bcac7bSAndi Shyti return err; 54378bcac7bSAndi Shyti if (err != sizeof(reg)) 54478bcac7bSAndi Shyti return -EIO; 54578bcac7bSAndi Shyti 54678bcac7bSAndi Shyti sdata->chip_id = be16_to_cpup((__be16 *)®[6]); 54778bcac7bSAndi Shyti sdata->chip_ver = reg[0]; 54878bcac7bSAndi Shyti sdata->fw_ver = be16_to_cpup((__be16 *)®[2]); 54978bcac7bSAndi Shyti sdata->config_id = reg[4]; 55078bcac7bSAndi Shyti sdata->config_ver = reg[5]; 55178bcac7bSAndi Shyti 55278bcac7bSAndi Shyti enable_irq(sdata->client->irq); 55378bcac7bSAndi Shyti 55478bcac7bSAndi Shyti msleep(50); 55578bcac7bSAndi Shyti 55678bcac7bSAndi Shyti err = stmfts_command(sdata, STMFTS_SYSTEM_RESET); 55778bcac7bSAndi Shyti if (err) 55878bcac7bSAndi Shyti return err; 55978bcac7bSAndi Shyti 56078bcac7bSAndi Shyti err = stmfts_command(sdata, STMFTS_SLEEP_OUT); 56178bcac7bSAndi Shyti if (err) 56278bcac7bSAndi Shyti return err; 56378bcac7bSAndi Shyti 56478bcac7bSAndi Shyti /* optional tuning */ 56578bcac7bSAndi Shyti err = stmfts_command(sdata, STMFTS_MS_CX_TUNING); 56678bcac7bSAndi Shyti if (err) 56778bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 56878bcac7bSAndi Shyti "failed to perform mutual auto tune: %d\n", err); 56978bcac7bSAndi Shyti 57078bcac7bSAndi Shyti /* optional tuning */ 57178bcac7bSAndi Shyti err = stmfts_command(sdata, STMFTS_SS_CX_TUNING); 57278bcac7bSAndi Shyti if (err) 57378bcac7bSAndi Shyti dev_warn(&sdata->client->dev, 57478bcac7bSAndi Shyti "failed to perform self auto tune: %d\n", err); 57578bcac7bSAndi Shyti 57678bcac7bSAndi Shyti err = stmfts_command(sdata, STMFTS_FULL_FORCE_CALIBRATION); 57778bcac7bSAndi Shyti if (err) 57878bcac7bSAndi Shyti return err; 57978bcac7bSAndi Shyti 58078bcac7bSAndi Shyti /* 58178bcac7bSAndi Shyti * At this point no one is using the touchscreen 58278bcac7bSAndi Shyti * and I don't really care about the return value 58378bcac7bSAndi Shyti */ 58478bcac7bSAndi Shyti (void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN); 58578bcac7bSAndi Shyti 58678bcac7bSAndi Shyti return 0; 58778bcac7bSAndi Shyti } 58878bcac7bSAndi Shyti 58978bcac7bSAndi Shyti static void stmfts_power_off(void *data) 59078bcac7bSAndi Shyti { 59178bcac7bSAndi Shyti struct stmfts_data *sdata = data; 59278bcac7bSAndi Shyti 59378bcac7bSAndi Shyti disable_irq(sdata->client->irq); 59478bcac7bSAndi Shyti regulator_bulk_disable(ARRAY_SIZE(sdata->regulators), 59578bcac7bSAndi Shyti sdata->regulators); 59678bcac7bSAndi Shyti } 59778bcac7bSAndi Shyti 59878bcac7bSAndi Shyti /* This function is void because I don't want to prevent using the touch key 59978bcac7bSAndi Shyti * only because the LEDs don't get registered 60078bcac7bSAndi Shyti */ 60178bcac7bSAndi Shyti static int stmfts_enable_led(struct stmfts_data *sdata) 60278bcac7bSAndi Shyti { 60378bcac7bSAndi Shyti int err; 60478bcac7bSAndi Shyti 60578bcac7bSAndi Shyti /* get the regulator for powering the leds on */ 60678bcac7bSAndi Shyti sdata->ledvdd = devm_regulator_get(&sdata->client->dev, "ledvdd"); 60778bcac7bSAndi Shyti if (IS_ERR(sdata->ledvdd)) 60878bcac7bSAndi Shyti return PTR_ERR(sdata->ledvdd); 60978bcac7bSAndi Shyti 61078bcac7bSAndi Shyti sdata->led_cdev.name = STMFTS_DEV_NAME; 61178bcac7bSAndi Shyti sdata->led_cdev.max_brightness = LED_ON; 61278bcac7bSAndi Shyti sdata->led_cdev.brightness = LED_OFF; 613937c4e55SDmitry Torokhov sdata->led_cdev.brightness_set_blocking = stmfts_brightness_set; 61478bcac7bSAndi Shyti sdata->led_cdev.brightness_get = stmfts_brightness_get; 61578bcac7bSAndi Shyti 61678bcac7bSAndi Shyti err = devm_led_classdev_register(&sdata->client->dev, &sdata->led_cdev); 61778bcac7bSAndi Shyti if (err) { 61878bcac7bSAndi Shyti devm_regulator_put(sdata->ledvdd); 61978bcac7bSAndi Shyti return err; 62078bcac7bSAndi Shyti } 62178bcac7bSAndi Shyti 62278bcac7bSAndi Shyti return 0; 62378bcac7bSAndi Shyti } 62478bcac7bSAndi Shyti 62578bcac7bSAndi Shyti static int stmfts_probe(struct i2c_client *client, 62678bcac7bSAndi Shyti const struct i2c_device_id *id) 62778bcac7bSAndi Shyti { 62878bcac7bSAndi Shyti int err; 62978bcac7bSAndi Shyti struct stmfts_data *sdata; 63078bcac7bSAndi Shyti 63178bcac7bSAndi Shyti if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | 63278bcac7bSAndi Shyti I2C_FUNC_SMBUS_BYTE_DATA | 63378bcac7bSAndi Shyti I2C_FUNC_SMBUS_I2C_BLOCK)) 63478bcac7bSAndi Shyti return -ENODEV; 63578bcac7bSAndi Shyti 63678bcac7bSAndi Shyti sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL); 63778bcac7bSAndi Shyti if (!sdata) 63878bcac7bSAndi Shyti return -ENOMEM; 63978bcac7bSAndi Shyti 64078bcac7bSAndi Shyti i2c_set_clientdata(client, sdata); 64178bcac7bSAndi Shyti 64278bcac7bSAndi Shyti sdata->client = client; 64378bcac7bSAndi Shyti mutex_init(&sdata->mutex); 64478bcac7bSAndi Shyti init_completion(&sdata->cmd_done); 64578bcac7bSAndi Shyti 64678bcac7bSAndi Shyti sdata->regulators[STMFTS_REGULATOR_VDD].supply = "vdd"; 64778bcac7bSAndi Shyti sdata->regulators[STMFTS_REGULATOR_AVDD].supply = "avdd"; 64878bcac7bSAndi Shyti err = devm_regulator_bulk_get(&client->dev, 64978bcac7bSAndi Shyti ARRAY_SIZE(sdata->regulators), 65078bcac7bSAndi Shyti sdata->regulators); 65178bcac7bSAndi Shyti if (err) 65278bcac7bSAndi Shyti return err; 65378bcac7bSAndi Shyti 65478bcac7bSAndi Shyti sdata->input = devm_input_allocate_device(&client->dev); 65578bcac7bSAndi Shyti if (!sdata->input) 65678bcac7bSAndi Shyti return -ENOMEM; 65778bcac7bSAndi Shyti 65878bcac7bSAndi Shyti sdata->input->name = STMFTS_DEV_NAME; 65978bcac7bSAndi Shyti sdata->input->id.bustype = BUS_I2C; 66078bcac7bSAndi Shyti sdata->input->open = stmfts_input_open; 66178bcac7bSAndi Shyti sdata->input->close = stmfts_input_close; 66278bcac7bSAndi Shyti 663c9bfb2f0SChanwoo Choi input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_X); 664c9bfb2f0SChanwoo Choi input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_Y); 66578bcac7bSAndi Shyti touchscreen_parse_properties(sdata->input, true, &sdata->prop); 66678bcac7bSAndi Shyti 66778bcac7bSAndi Shyti input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); 66878bcac7bSAndi Shyti input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0); 66978bcac7bSAndi Shyti input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0); 67078bcac7bSAndi Shyti input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0); 67178bcac7bSAndi Shyti input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0); 67278bcac7bSAndi Shyti 67378bcac7bSAndi Shyti sdata->use_key = device_property_read_bool(&client->dev, 67478bcac7bSAndi Shyti "touch-key-connected"); 67578bcac7bSAndi Shyti if (sdata->use_key) { 67678bcac7bSAndi Shyti input_set_capability(sdata->input, EV_KEY, KEY_MENU); 67778bcac7bSAndi Shyti input_set_capability(sdata->input, EV_KEY, KEY_BACK); 67878bcac7bSAndi Shyti } 67978bcac7bSAndi Shyti 68078bcac7bSAndi Shyti err = input_mt_init_slots(sdata->input, 68178bcac7bSAndi Shyti STMFTS_MAX_FINGERS, INPUT_MT_DIRECT); 68278bcac7bSAndi Shyti if (err) 68378bcac7bSAndi Shyti return err; 68478bcac7bSAndi Shyti 68578bcac7bSAndi Shyti input_set_drvdata(sdata->input, sdata); 68678bcac7bSAndi Shyti 687cba04cdfSAndi Shyti /* 688cba04cdfSAndi Shyti * stmfts_power_on expects interrupt to be disabled, but 689cba04cdfSAndi Shyti * at this point the device is still off and I do not trust 690cba04cdfSAndi Shyti * the status of the irq line that can generate some spurious 691cba04cdfSAndi Shyti * interrupts. To be on the safe side it's better to not enable 692cba04cdfSAndi Shyti * the interrupts during their request. 693cba04cdfSAndi Shyti */ 694cba04cdfSAndi Shyti irq_set_status_flags(client->irq, IRQ_NOAUTOEN); 69578bcac7bSAndi Shyti err = devm_request_threaded_irq(&client->dev, client->irq, 69678bcac7bSAndi Shyti NULL, stmfts_irq_handler, 69778bcac7bSAndi Shyti IRQF_ONESHOT, 69878bcac7bSAndi Shyti "stmfts_irq", sdata); 69978bcac7bSAndi Shyti if (err) 70078bcac7bSAndi Shyti return err; 70178bcac7bSAndi Shyti 70278bcac7bSAndi Shyti dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n"); 70378bcac7bSAndi Shyti 70478bcac7bSAndi Shyti err = stmfts_power_on(sdata); 70578bcac7bSAndi Shyti if (err) 70678bcac7bSAndi Shyti return err; 70778bcac7bSAndi Shyti 70878bcac7bSAndi Shyti err = devm_add_action_or_reset(&client->dev, stmfts_power_off, sdata); 70978bcac7bSAndi Shyti if (err) 71078bcac7bSAndi Shyti return err; 71178bcac7bSAndi Shyti 71278bcac7bSAndi Shyti err = input_register_device(sdata->input); 71378bcac7bSAndi Shyti if (err) 71478bcac7bSAndi Shyti return err; 71578bcac7bSAndi Shyti 71678bcac7bSAndi Shyti if (sdata->use_key) { 71778bcac7bSAndi Shyti err = stmfts_enable_led(sdata); 71878bcac7bSAndi Shyti if (err) { 71978bcac7bSAndi Shyti /* 72078bcac7bSAndi Shyti * Even if the LEDs have failed to be initialized and 72178bcac7bSAndi Shyti * used in the driver, I can still use the device even 72278bcac7bSAndi Shyti * without LEDs. The ledvdd regulator pointer will be 72378bcac7bSAndi Shyti * used as a flag. 72478bcac7bSAndi Shyti */ 72578bcac7bSAndi Shyti dev_warn(&client->dev, "unable to use touchkey leds\n"); 72678bcac7bSAndi Shyti sdata->ledvdd = NULL; 72778bcac7bSAndi Shyti } 72878bcac7bSAndi Shyti } 72978bcac7bSAndi Shyti 730c2690bd6SAndi Shyti err = devm_device_add_group(&client->dev, &stmfts_attribute_group); 73178bcac7bSAndi Shyti if (err) 73278bcac7bSAndi Shyti return err; 73378bcac7bSAndi Shyti 73478bcac7bSAndi Shyti pm_runtime_enable(&client->dev); 7351d960003SMarek Szyprowski device_enable_async_suspend(&client->dev); 73678bcac7bSAndi Shyti 73778bcac7bSAndi Shyti return 0; 73878bcac7bSAndi Shyti } 73978bcac7bSAndi Shyti 74078bcac7bSAndi Shyti static int stmfts_remove(struct i2c_client *client) 74178bcac7bSAndi Shyti { 74278bcac7bSAndi Shyti pm_runtime_disable(&client->dev); 74378bcac7bSAndi Shyti 74478bcac7bSAndi Shyti return 0; 74578bcac7bSAndi Shyti } 74678bcac7bSAndi Shyti 747d4c9354bSArnd Bergmann static int __maybe_unused stmfts_runtime_suspend(struct device *dev) 74878bcac7bSAndi Shyti { 74978bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 75078bcac7bSAndi Shyti int ret; 75178bcac7bSAndi Shyti 75278bcac7bSAndi Shyti ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN); 75378bcac7bSAndi Shyti if (ret) 75478bcac7bSAndi Shyti dev_warn(dev, "failed to suspend device: %d\n", ret); 75578bcac7bSAndi Shyti 75678bcac7bSAndi Shyti return ret; 75778bcac7bSAndi Shyti } 75878bcac7bSAndi Shyti 759d4c9354bSArnd Bergmann static int __maybe_unused stmfts_runtime_resume(struct device *dev) 76078bcac7bSAndi Shyti { 76178bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 76278bcac7bSAndi Shyti int ret; 76378bcac7bSAndi Shyti 76478bcac7bSAndi Shyti ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT); 76578bcac7bSAndi Shyti if (ret) 76678bcac7bSAndi Shyti dev_err(dev, "failed to resume device: %d\n", ret); 76778bcac7bSAndi Shyti 76878bcac7bSAndi Shyti return ret; 76978bcac7bSAndi Shyti } 77078bcac7bSAndi Shyti 77178bcac7bSAndi Shyti static int __maybe_unused stmfts_suspend(struct device *dev) 77278bcac7bSAndi Shyti { 77378bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 77478bcac7bSAndi Shyti 77578bcac7bSAndi Shyti stmfts_power_off(sdata); 77678bcac7bSAndi Shyti 77778bcac7bSAndi Shyti return 0; 77878bcac7bSAndi Shyti } 77978bcac7bSAndi Shyti 78078bcac7bSAndi Shyti static int __maybe_unused stmfts_resume(struct device *dev) 78178bcac7bSAndi Shyti { 78278bcac7bSAndi Shyti struct stmfts_data *sdata = dev_get_drvdata(dev); 78378bcac7bSAndi Shyti 78478bcac7bSAndi Shyti return stmfts_power_on(sdata); 78578bcac7bSAndi Shyti } 78678bcac7bSAndi Shyti 78778bcac7bSAndi Shyti static const struct dev_pm_ops stmfts_pm_ops = { 78878bcac7bSAndi Shyti SET_SYSTEM_SLEEP_PM_OPS(stmfts_suspend, stmfts_resume) 78978bcac7bSAndi Shyti SET_RUNTIME_PM_OPS(stmfts_runtime_suspend, stmfts_runtime_resume, NULL) 79078bcac7bSAndi Shyti }; 79178bcac7bSAndi Shyti 79278bcac7bSAndi Shyti #ifdef CONFIG_OF 79378bcac7bSAndi Shyti static const struct of_device_id stmfts_of_match[] = { 79478bcac7bSAndi Shyti { .compatible = "st,stmfts", }, 79578bcac7bSAndi Shyti { }, 79678bcac7bSAndi Shyti }; 79778bcac7bSAndi Shyti MODULE_DEVICE_TABLE(of, stmfts_of_match); 79878bcac7bSAndi Shyti #endif 79978bcac7bSAndi Shyti 80078bcac7bSAndi Shyti static const struct i2c_device_id stmfts_id[] = { 80178bcac7bSAndi Shyti { "stmfts", 0 }, 80278bcac7bSAndi Shyti { }, 80378bcac7bSAndi Shyti }; 80478bcac7bSAndi Shyti MODULE_DEVICE_TABLE(i2c, stmfts_id); 80578bcac7bSAndi Shyti 80678bcac7bSAndi Shyti static struct i2c_driver stmfts_driver = { 80778bcac7bSAndi Shyti .driver = { 80878bcac7bSAndi Shyti .name = STMFTS_DEV_NAME, 80978bcac7bSAndi Shyti .of_match_table = of_match_ptr(stmfts_of_match), 81078bcac7bSAndi Shyti .pm = &stmfts_pm_ops, 8111d960003SMarek Szyprowski .probe_type = PROBE_PREFER_ASYNCHRONOUS, 81278bcac7bSAndi Shyti }, 81378bcac7bSAndi Shyti .probe = stmfts_probe, 81478bcac7bSAndi Shyti .remove = stmfts_remove, 81578bcac7bSAndi Shyti .id_table = stmfts_id, 81678bcac7bSAndi Shyti }; 81778bcac7bSAndi Shyti 81878bcac7bSAndi Shyti module_i2c_driver(stmfts_driver); 81978bcac7bSAndi Shyti 82078bcac7bSAndi Shyti MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>"); 82178bcac7bSAndi Shyti MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen"); 82278bcac7bSAndi Shyti MODULE_LICENSE("GPL v2"); 823