From 97f29fe6f36c555a166b77ffc4d1be54e69964ca Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Sun, 17 May 2015 20:01:20 +0530 Subject: [PATCH 1/5] input: touchscreen: add protocol B support for ITE tech driver Add multi-touch protocol B support for ITE tech touch screen driver. Change-Id: I9ed40ccedab71a3800b97fc7825741855bceaa29 Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/it7258_ts_i2c.c | 106 ++++++++++------------ 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c index 011980ce2024..99fc54a0bf4b 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -26,6 +26,7 @@ #include #include #include +#include #define MAX_BUFFER_SIZE 144 #define DEVICE_NAME "IT7260" @@ -98,18 +99,14 @@ #define PD_FLAGS_DATA_TYPE_BITS 0xF0 /* other types (like chip-detected gestures) exist but we do not care */ #define PD_FLAGS_DATA_TYPE_TOUCH 0x00 -/* set if pen touched, clear if finger(s) */ -#define PD_FLAGS_NOT_PEN 0x08 /* a bit for each finger data that is valid (from lsb to msb) */ #define PD_FLAGS_HAVE_FINGERS 0x07 +/* number of finger supported */ +#define PD_FINGERS_SUPPORTED 3 #define PD_PALM_FLAG_BIT 0x01 #define FD_PRESSURE_BITS 0x0F #define FD_PRESSURE_NONE 0x00 -#define FD_PRESSURE_HOVER 0x01 #define FD_PRESSURE_LIGHT 0x02 -#define FD_PRESSURE_NORMAL 0x04 -#define FD_PRESSURE_HIGH 0x08 -#define FD_PRESSURE_HEAVY 0x0F #define IT_VTG_MIN_UV 1800000 #define IT_VTG_MAX_UV 1800000 @@ -166,12 +163,6 @@ static int IT7260_ts_suspend(struct device *dev); static struct IT7260_ts_data *gl_ts; -/* Function declarations */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -static int IT7260_ts_resume(struct device *dev); -static int IT7260_ts_suspend(struct device *dev); - static int IT7260_debug_suspend_set(void *_data, u64 val) { if (val) @@ -706,35 +697,26 @@ EXPORT_SYMBOL(IT7260_sendCalibrationCmd); static void IT7260_ts_release_all(void) { + int finger; + + for (finger = 0; finger < PD_FINGERS_SUPPORTED; finger++) { + input_mt_slot(gl_ts->input_dev, finger); + input_mt_report_slot_state(gl_ts->input_dev, + MT_TOOL_FINGER, 0); + } + input_report_key(gl_ts->input_dev, BTN_TOUCH, 0); - input_mt_sync(gl_ts->input_dev); input_sync(gl_ts->input_dev); } -static void IT7260_readFingerData(uint16_t *xP, uint16_t *yP, - uint8_t *pressureP, const struct FingerData *fd) -{ - uint16_t x = fd->xLo; - uint16_t y = fd->yLo; - - x += ((uint16_t)(fd->hi & 0x0F)) << 8; - y += ((uint16_t)(fd->hi & 0xF0)) << 4; - - if (xP) - *xP = x; - if (yP) - *yP = y; - if (pressureP) - *pressureP = fd->pressure & FD_PRESSURE_BITS; -} - static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid) { struct PointData point_data; - uint8_t dev_status; + struct input_dev *input_dev = gl_ts->input_dev; + u8 dev_status, finger, touch_count = 0, finger_status; + u8 pressure = FD_PRESSURE_NONE; + u16 x, y; bool palm_detected; - uint8_t pressure = FD_PRESSURE_NONE; - uint16_t x, y; /* * This code adds the touch-to-wake functionality to the ITE tech @@ -747,10 +729,10 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid) if (gl_ts->device_needs_wakeup) { pm_stay_awake(&gl_ts->client->dev); gl_ts->device_needs_wakeup = false; - input_report_key(gl_ts->input_dev, KEY_WAKEUP, 1); - input_sync(gl_ts->input_dev); - input_report_key(gl_ts->input_dev, KEY_WAKEUP, 0); - input_sync(gl_ts->input_dev); + input_report_key(input_dev, KEY_WAKEUP, 1); + input_sync(input_dev); + input_report_key(input_dev, KEY_WAKEUP, 0); + input_sync(input_dev); schedule_work(&gl_ts->work_pm_relax); } @@ -774,38 +756,43 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid) palm_detected = point_data.palm & PD_PALM_FLAG_BIT; if (palm_detected && gl_ts->pdata->palm_detect_en) { - input_report_key(gl_ts->input_dev, + input_report_key(input_dev, gl_ts->pdata->palm_detect_keycode, 1); - input_sync(gl_ts->input_dev); - input_report_key(gl_ts->input_dev, + input_sync(input_dev); + input_report_key(input_dev, gl_ts->pdata->palm_detect_keycode, 0); - input_sync(gl_ts->input_dev); + input_sync(input_dev); } - if ((point_data.flags & PD_FLAGS_HAVE_FINGERS) & 1) - IT7260_readFingerData(&x, &y, &pressure, point_data.fd); + for (finger = 0; finger < PD_FINGERS_SUPPORTED; finger++) { + finger_status = point_data.flags & (0x01 << finger); - if (pressure >= FD_PRESSURE_LIGHT) { - if (!gl_ts->had_finger_down) - gl_ts->had_finger_down = true; + input_mt_slot(input_dev, finger); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, + finger_status != 0); - IT7260_readFingerData(&x, &y, &pressure, point_data.fd); + x = point_data.fd[finger].xLo + + (((u16)(point_data.fd[finger].hi & 0x0F)) << 8); + y = point_data.fd[finger].yLo + + (((u16)(point_data.fd[finger].hi & 0xF0)) << 4); - input_report_key(gl_ts->input_dev, BTN_TOUCH, 1); - input_report_abs(gl_ts->input_dev, ABS_MT_POSITION_X, x); - input_report_abs(gl_ts->input_dev, ABS_MT_POSITION_Y, y); - input_mt_sync(gl_ts->input_dev); - input_sync(gl_ts->input_dev); + pressure = point_data.fd[finger].pressure & FD_PRESSURE_BITS; - - } else if (gl_ts->had_finger_down) { - gl_ts->had_finger_down = false; - - input_report_key(gl_ts->input_dev, BTN_TOUCH, 0); - input_mt_sync(gl_ts->input_dev); - input_sync(gl_ts->input_dev); + if (finger_status) { + if (pressure >= FD_PRESSURE_LIGHT) { + input_report_key(input_dev, BTN_TOUCH, 1); + input_report_abs(input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(input_dev, + ABS_MT_POSITION_Y, y); + touch_count++; + } + } } + input_report_key(input_dev, BTN_TOUCH, touch_count > 0); + input_sync(input_dev); + return IRQ_HANDLED; } @@ -1015,6 +1002,7 @@ static int IT7260_ts_probe(struct i2c_client *client, input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_Y, 0, SCREEN_Y_RESOLUTION, 0, 0); input_set_drvdata(gl_ts->input_dev, gl_ts); + input_mt_init_slots(gl_ts->input_dev, PD_FINGERS_SUPPORTED, 0); if (pdata->wakeup) { set_bit(KEY_WAKEUP, gl_ts->input_dev->keybit); From 1f51fe6ebee704c7cbe9343aae87403fd6bd50ea Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 14 May 2015 19:39:38 +0530 Subject: [PATCH 2/5] input: touchscreen: add auto fw upgrade for ITE tech driver Add auto firmware and config upgrade functionality for ITE tech touchscreen driver. Add sysfs support for manual fw and cfg upgrade functionality. Also clean the sysfs function names. Change-Id: I8912545589cb763c1deb70bebb081e920af69ad2 Signed-off-by: Shantanu Jain --- .../input/touchscreen/it7258_ts_i2c.txt | 4 + drivers/input/touchscreen/it7258_ts_i2c.c | 571 +++++++++++++----- 2 files changed, 410 insertions(+), 165 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt index 0b57ba0b62a0..c95ccad4a841 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt @@ -24,6 +24,8 @@ Optional properties: - ite,wakeup : boolean, use this to support touch-to-wake feature. - ite,palm-detect-en : boolean, use this to send palm-detect-keycode when palm is detected. + - ite,fw-name : Specify firmware file name in /etc/firmware + - ite,cfg-name : Specify config file name in /etc/firmware Required properties palm-detect-en feature: - ite,palm-detect-keycode : The keycode that is required to be sent when @@ -43,5 +45,7 @@ Example: ite,wakeup; ite,palm-detect-en; ite,palm-detect-keycode = <142>; + ite,fw-name = "ite7260_fw.bin"; + ite,cfg-name = "ite7260_cfg.bin"; }; }; diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c index 99fc54a0bf4b..c3dd88c08d7e 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -27,12 +27,24 @@ #include #include #include +#include #define MAX_BUFFER_SIZE 144 #define DEVICE_NAME "IT7260" #define SCREEN_X_RESOLUTION 320 #define SCREEN_Y_RESOLUTION 320 #define DEBUGFS_DIR_NAME "ts_debug" +#define FW_NAME "it7260_fw.bin" +#define CFG_NAME "it7260_cfg.bin" +#define VER_BUFFER_SIZE 4 +#define IT_FW_CHECK(x, y) \ + (((x)[0] < (y)->data[8]) || ((x)[1] < (y)->data[9]) || \ + ((x)[2] < (y)->data[10]) || ((x)[3] < (y)->data[11])) +#define IT_CFG_CHECK(x, y) \ + (((x)[0] < (y)->data[(y)->size - 8]) || \ + ((x)[1] < (y)->data[(y)->size - 7]) || \ + ((x)[2] < (y)->data[(y)->size - 6]) || \ + ((x)[3] < (y)->data[(y)->size - 5])) /* all commands writes go to this idx */ #define BUF_COMMAND 0x20 @@ -55,8 +67,8 @@ #define CMD_IDENT_CHIP 0x00 /* VERSION_LENGTH bytes of data in response */ #define CMD_READ_VERSIONS 0x01 -#define VER_FIRMWARE 0x00 -#define VER_CONFIG 0x06 +#define SUB_CMD_READ_FIRMWARE_VERSION 0x00 +#define SUB_CMD_READ_CONFIG_VERSION 0x06 #define VERSION_LENGTH 10 /* subcommand is zero, next byte is power mode */ #define CMD_PWR_CTL 0x04 @@ -70,8 +82,8 @@ /* needs to be followed by 4 bytes of zeroes */ #define CMD_CALIBRATE 0x13 #define CMD_FIRMWARE_UPGRADE 0x60 -#define FIRMWARE_MODE_ENTER 0x00 -#define FIRMWARE_MODE_EXIT 0x80 +#define SUB_CMD_ENTER_FW_UPGRADE_MODE 0x00 +#define SUB_CMD_EXIT_FW_UPGRADE_MODE 0x80 /* address for FW read/write */ #define CMD_SET_START_OFFSET 0x61 /* subcommand is number of bytes to write */ @@ -135,6 +147,8 @@ struct IT7260_ts_platform_data { bool wakeup; bool palm_detect_en; u16 palm_detect_keycode; + const char *fw_name; + const char *cfg_name; }; struct IT7260_ts_data { @@ -145,10 +159,17 @@ struct IT7260_ts_data { struct regulator *avdd; bool device_needs_wakeup; bool suspended; - struct work_struct work_pm_relax; bool fw_upgrade_result; + bool cfg_upgrade_result; + bool fw_cfg_uploading; + struct work_struct work_pm_relax; bool calibration_success; bool had_finger_down; + char fw_name[MAX_BUFFER_SIZE]; + char cfg_name[MAX_BUFFER_SIZE]; + struct mutex fw_cfg_mutex; + u8 fw_ver[VER_BUFFER_SIZE]; + u8 cfg_ver[VER_BUFFER_SIZE]; #ifdef CONFIG_FB struct notifier_block fb_notif; #endif @@ -269,7 +290,7 @@ static bool IT7260_i2cWrite(uint8_t buf_index, const uint8_t *buffer, return IT7260_i2cWriteNoReadyCheck(buf_index, buffer, buf_len); } -static bool IT7260_chipFirmwareReinitialize(uint8_t command) +static bool IT7260_firmware_reinitialize(u8 command) { uint8_t cmd[] = {command}; uint8_t rsp[2]; @@ -284,13 +305,14 @@ static bool IT7260_chipFirmwareReinitialize(uint8_t command) return !rsp[0] && !rsp[1]; } -static bool IT7260_chipFirmwareUpgradeModeEnterExit(bool enter) +static bool IT7260_enter_exit_fw_ugrade_mode(bool enter) { uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2', '6', '0', 0x55, 0xAA}; uint8_t resp[2]; - cmd[1] = enter ? FIRMWARE_MODE_ENTER : FIRMWARE_MODE_EXIT; + cmd[1] = enter ? SUB_CMD_ENTER_FW_UPGRADE_MODE : + SUB_CMD_EXIT_FW_UPGRADE_MODE; if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd))) return false; @@ -321,7 +343,7 @@ static bool IT7260_chipSetStartOffset(uint16_t offset) /* write fw_length bytes from fw_data at chip offset wr_start_offset */ -static bool IT7260_chipFlashWriteAndVerify(unsigned int fw_length, +static bool IT7260_fw_flash_write_verify(unsigned int fw_length, const uint8_t *fw_data, uint16_t wr_start_offset) { uint32_t cur_data_off; @@ -384,71 +406,171 @@ static bool IT7260_chipFlashWriteAndVerify(unsigned int fw_length, return true; } -static bool IT7260_chipFirmwareUpload(uint32_t fw_len, const uint8_t *fw_data, - uint32_t cfg_len, const uint8_t *cfg_data) -{ - bool success = false; - - /* enter fw upload mode */ - if (!IT7260_chipFirmwareUpgradeModeEnterExit(true)) - return false; - - /* flash the firmware if requested */ - if (fw_len && fw_data && !IT7260_chipFlashWriteAndVerify(fw_len, - fw_data, 0)) { - dev_err(&gl_ts->client->dev, "failed to upload touch firmware\n"); - goto out; - } - - /* flash config data if requested */ - if (cfg_len && cfg_data && !IT7260_chipFlashWriteAndVerify(cfg_len, - cfg_data, CHIP_FLASH_SIZE - cfg_len)) { - dev_err(&gl_ts->client->dev, "failed to upload touch cfg data\n"); - goto out; - } - - success = true; - -out: - return IT7260_chipFirmwareUpgradeModeEnterExit(false) && - IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F) && - success; -} - - /* - * both buffers should be VERSION_LENGTH in size, - * but only a part of them is significant + * this code to get versions from the chip via i2c transactions, and save + * them in driver data structure. */ -static bool IT7260_chipGetVersions(uint8_t *ver_fw, uint8_t *ver_cfg, - bool log_it) +static void IT7260_get_chip_versions(struct device *dev) { - /* - * this code to get versions is reproduced as was written, but it does - * not make sense. Something here *PROBABLY IS* wrong - */ - static const uint8_t cmd_read_fw_ver[] = {CMD_READ_VERSIONS, - VER_FIRMWARE}; - static const uint8_t cmd_read_cfg_ver[] = {CMD_READ_VERSIONS, - VER_CONFIG}; + static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS, + SUB_CMD_READ_FIRMWARE_VERSION}; + static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS, + SUB_CMD_READ_CONFIG_VERSION}; + u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH]; bool ret = true; - /* - * this structure is so that we definitely do all the calls, but still - * return a status in case anyone cares - */ ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver, - sizeof(cmd_read_fw_ver)) && ret; - ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH) && ret; - ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver, - sizeof(cmd_read_cfg_ver)) && ret; - ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH) && ret; + sizeof(cmd_read_fw_ver)); + if (ret) { + ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH); + if (ret) + memcpy(gl_ts->fw_ver, ver_fw + (5 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + } + if (!ret) + dev_err(dev, "failed to read fw version from chip\n"); - if (log_it) - dev_info(&gl_ts->client->dev, - "current versions: fw@{%X,%X,%X,%X}, cfg@{%X,%X,%X,%X}\n", - ver_fw[5], ver_fw[6], ver_fw[7], ver_fw[8], - ver_cfg[1], ver_cfg[2], ver_cfg[3], ver_cfg[4]); + ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver, + sizeof(cmd_read_cfg_ver)); + if (ret) { + ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH) + && ret; + if (ret) + memcpy(gl_ts->cfg_ver, ver_cfg + (1 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + } + if (!ret) + dev_err(dev, "failed to read cfg version from chip\n"); + + dev_info(dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n", + gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2], + gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1], + gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]); +} + +static int IT7260_cfg_upload(struct device *dev, bool force) +{ + const struct firmware *cfg = NULL; + int ret; + bool success, cfg_upgrade = false; + + ret = request_firmware(&cfg, gl_ts->cfg_name, dev); + if (ret) { + dev_err(dev, "failed to get config data %s for it7260 %d\n", + gl_ts->cfg_name, ret); + return ret; + } + + /* + * This compares the cfg version number from chip and the cfg + * data file. IT flashes only when version of cfg data file is + * greater than that of chip or if it is set for force cfg upgrade. + */ + if (force) + cfg_upgrade = true; + else if (IT_CFG_CHECK(gl_ts->cfg_ver, cfg)) + cfg_upgrade = true; + + if (!cfg_upgrade) { + dev_err(dev, "CFG upgrade no required ...\n"); + ret = -EFAULT; + goto out; + } else { + dev_info(dev, "Config upgrading...\n"); + + disable_irq(gl_ts->client->irq); + /* enter cfg upload mode */ + success = IT7260_enter_exit_fw_ugrade_mode(true); + if (!success) { + dev_err(dev, "Can't enter cfg upgrade mode\n"); + ret = -EIO; + goto out; + } + /* flash config data if requested */ + success = IT7260_fw_flash_write_verify(cfg->size, cfg->data, + CHIP_FLASH_SIZE - cfg->size); + if (!success) { + dev_err(dev, "failed to upgrade touch cfg data\n"); + IT7260_enter_exit_fw_ugrade_mode(false); + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F); + ret = -EIO; + goto out; + } else { + memcpy(gl_ts->cfg_ver, cfg->data + + (cfg->size - 8 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + dev_info(dev, "CFG upgrade is success. New cfg ver: %X.%X.%X.%X\n", + gl_ts->cfg_ver[0], gl_ts->cfg_ver[1], + gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]); + + } + enable_irq(gl_ts->client->irq); + } + +out: + release_firmware(cfg); + + return ret; +} + +static int IT7260_fw_upload(struct device *dev, bool force) +{ + const struct firmware *fw = NULL; + int ret; + bool success, fw_upgrade = false; + + ret = request_firmware(&fw, gl_ts->fw_name, dev); + if (ret) { + dev_err(dev, "failed to get firmware %s for it7260 %d\n", + gl_ts->fw_name, ret); + return ret; + } + + /* + * This compares the fw version number from chip and the fw data + * file. It flashes only when version of fw data file is greater + * than that of chip or it it is set for force fw upgrade. + */ + if (force) + fw_upgrade = true; + else if (IT_FW_CHECK(gl_ts->fw_ver, fw)) + fw_upgrade = true; + + if (!fw_upgrade) { + dev_err(dev, "FW upgrade not required ...\n"); + ret = -EFAULT; + goto out; + } else { + dev_info(dev, "Firmware upgrading...\n"); + + disable_irq(gl_ts->client->irq); + /* enter fw upload mode */ + success = IT7260_enter_exit_fw_ugrade_mode(true); + if (!success) { + dev_err(dev, "Can't enter fw upgrade mode\n"); + ret = -EIO; + goto out; + } + /* flash the firmware if requested */ + success = IT7260_fw_flash_write_verify(fw->size, fw->data, 0); + if (!success) { + dev_err(dev, "failed to upgrade touch firmware\n"); + IT7260_enter_exit_fw_ugrade_mode(false); + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F); + ret = -EIO; + goto out; + } else { + memcpy(gl_ts->fw_ver, fw->data + (8 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + dev_info(dev, "FW upgrade is success. New fw ver: %X.%X.%X.%X\n", + gl_ts->fw_ver[0], gl_ts->fw_ver[1], + gl_ts->fw_ver[2], gl_ts->fw_ver[3]); + } + enable_irq(gl_ts->client->irq); + } + +out: + release_firmware(fw); return ret; } @@ -468,75 +590,91 @@ static int IT7260_ts_chipLowPowerMode(bool low) return 0; } -static ssize_t sysfsUpgradeStore(struct device *dev, +static ssize_t sysfs_fw_upgrade_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - const struct firmware *fw, *cfg; - uint8_t ver_fw[10], ver_cfg[10]; - unsigned fw_len = 0, cfg_len = 0; - bool success; int mode = 0, ret; - ret = request_firmware(&fw, "it7260.fw", dev); - if (ret) - dev_dbg(dev, "failed to get firmware for it7260 %d\n", ret); - else - fw_len = fw->size; - - ret = request_firmware(&cfg, "it7260.cfg", dev); - if (ret) - dev_dbg(dev, "failed to get config data for it7260 %d\n", ret); - else - cfg_len = cfg->size; - - ret = kstrtoint(buf, 10, &mode); - - IT7260_chipGetVersions(ver_fw, ver_cfg, true); - - gl_ts->fw_upgrade_result = false; - if (fw_len && cfg_len) { - if ((mode > 0) && ((ver_fw[5] < fw->data[8] || - ver_fw[6] < fw->data[9] || - ver_fw[7] < fw->data[10] || - ver_fw[8] < fw->data[11]) || - (ver_cfg[1] < cfg->data[cfg_len - 8] || - ver_cfg[2] < cfg->data[cfg_len - 7] || - ver_cfg[3] < cfg->data[cfg_len - 6] || - ver_cfg[4] < cfg->data[cfg_len - 5]))) { - dev_info(dev, "firmware/config will be upgraded\n"); - disable_irq(gl_ts->client->irq); - /* upgrade the fw and cfg */ - success = IT7260_chipFirmwareUpload(fw_len, fw->data, - cfg_len, cfg->data); - enable_irq(gl_ts->client->irq); - - gl_ts->fw_upgrade_result = success; - dev_info(dev, "fw/cfg upload %s\n", - success ? "success" : "failed"); - } else { - dev_info(dev, "firmware/config upgrade not needed\n"); - } + if (gl_ts->suspended) { + dev_err(dev, "Device is suspended, can't flash fw!!!\n"); + return -EBUSY; } - if (fw_len) - release_firmware(fw); + ret = kstrtoint(buf, 10, &mode); + if (!ret) { + dev_err(dev, "failed to read input for sysfs\n"); + return -EINVAL; + } - if (cfg_len) - release_firmware(cfg); + mutex_lock(&gl_ts->fw_cfg_mutex); + if (mode == 1) { + gl_ts->fw_cfg_uploading = true; + ret = IT7260_fw_upload(dev, false); + if (ret) { + dev_err(dev, "Failed to flash fw: %d", ret); + gl_ts->fw_upgrade_result = false; + } else { + gl_ts->fw_upgrade_result = true; + } + gl_ts->fw_cfg_uploading = false; + } + mutex_unlock(&gl_ts->fw_cfg_mutex); return count; } -static ssize_t sysfsUpgradeShow(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t sysfs_cfg_upgrade_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { - return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result); + int mode = 0, ret; + + if (gl_ts->suspended) { + dev_err(dev, "Device is suspended, can't flash cfg!!!\n"); + return -EBUSY; + } + + ret = kstrtoint(buf, 10, &mode); + if (!ret) { + dev_err(dev, "failed to read input for sysfs\n"); + return -EINVAL; + } + + mutex_lock(&gl_ts->fw_cfg_mutex); + if (mode == 1) { + gl_ts->fw_cfg_uploading = true; + ret = IT7260_cfg_upload(dev, false); + if (ret) { + dev_err(dev, "Failed to flash cfg: %d", ret); + gl_ts->cfg_upgrade_result = false; + } else { + gl_ts->cfg_upgrade_result = true; + } + gl_ts->fw_cfg_uploading = false; + } + mutex_unlock(&gl_ts->fw_cfg_mutex); + + return count; } -static ssize_t sysfsCalibrationShow(struct device *dev, +static ssize_t sysfs_fw_upgrade_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->calibration_success); + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->fw_upgrade_result); +} + +static ssize_t sysfs_cfg_upgrade_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->cfg_upgrade_result); +} + +static ssize_t sysfs_calibration_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->calibration_success); } static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on) @@ -547,7 +685,7 @@ static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on) sizeof(cmd_calibrate)); } -static ssize_t sysfsCalibrationStore(struct device *dev, +static ssize_t sysfs_calibration_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { uint8_t resp; @@ -560,20 +698,20 @@ static ssize_t sysfsCalibrationStore(struct device *dev, /* * previous logic that was here never called - * IT7260_chipFirmwareReinitialize() due to checking a + * IT7260_firmware_reinitialize() due to checking a * guaranteed-not-null value against null. We now * call it. Hopefully this is OK */ if (!resp) - dev_dbg(dev, "IT7260_chipFirmwareReinitialize -> %s\n", - IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F) + dev_dbg(dev, "IT7260_firmware_reinitialize-> %s\n", + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F) ? "success" : "fail"); } return count; } -` -static ssize_t sysfsPointShow(struct device *dev, + +static ssize_t sysfs_point_show(struct device *dev, struct device_attribute *attr, char *buf) { uint8_t point_data[sizeof(struct PointData)]; @@ -582,37 +720,35 @@ static ssize_t sysfsPointShow(struct device *dev, readSuccess = IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, point_data, sizeof(point_data)); - ret = snprintf(buf, MAX_BUFFER_SIZE, - "point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]=\n", - readSuccess, point_data[0], point_data[1], point_data[2], - point_data[3], point_data[4], point_data[5], point_data[6], - point_data[7], point_data[8], point_data[9], point_data[10], - point_data[11], point_data[12], point_data[13]); + if (readSuccess) { + ret = scnprintf(buf, MAX_BUFFER_SIZE, + "point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]\n", + readSuccess, point_data[0], point_data[1], + point_data[2], point_data[3], point_data[4], + point_data[5], point_data[6], point_data[7], + point_data[8], point_data[9], point_data[10], + point_data[11], point_data[12], point_data[13]); + } else { + ret = scnprintf(buf, MAX_BUFFER_SIZE, + "failed to read point data\n"); + } dev_dbg(dev, "%s", buf); return ret; } -static ssize_t sysfsPointStore(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return count; -} - -static ssize_t sysfsVersionShow(struct device *dev, +static ssize_t sysfs_version_show(struct device *dev, struct device_attribute *attr, char *buf) { - uint8_t ver_fw[10], ver_cfg[10]; - - IT7260_chipGetVersions(ver_fw, ver_cfg, false); - return snprintf(buf, MAX_BUFFER_SIZE, - "fw{%x,%x,%x,%x} # cfg{%x,%x,%x,%x}\n", - ver_fw[5], ver_fw[6], ver_fw[7], ver_fw[8], - ver_cfg[1], ver_cfg[2], ver_cfg[3], ver_cfg[4]); + return scnprintf(buf, MAX_BUFFER_SIZE, + "fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n", + gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2], + gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1], + gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]); } -static ssize_t sysfsSleepShow(struct device *dev, +static ssize_t sysfs_sleep_show(struct device *dev, struct device_attribute *attr, char *buf) { /* @@ -624,7 +760,7 @@ static ssize_t sysfsSleepShow(struct device *dev, return 1; } -static ssize_t sysfsSleepStore(struct device *dev, +static ssize_t sysfs_sleep_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int go_to_sleep, ret; @@ -654,23 +790,95 @@ static ssize_t sysfsSleepStore(struct device *dev, return count; } +static ssize_t sysfs_cfg_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + char *strptr; + + if (count >= MAX_BUFFER_SIZE) { + dev_err(dev, "Input over %d chars long\n", MAX_BUFFER_SIZE); + return -EINVAL; + } + + strptr = strnstr(buf, ".bin", count); + if (!strptr) { + dev_err(dev, "Input is invalid cfg file\n"); + return -EINVAL; + } + + strlcpy(gl_ts->cfg_name, buf, count); + + return count; +} + +static ssize_t sysfs_cfg_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (strnlen(gl_ts->cfg_name, MAX_BUFFER_SIZE) > 0) + return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n", + gl_ts->cfg_name); + else + return scnprintf(buf, MAX_BUFFER_SIZE, + "No config file name given\n"); +} + +static ssize_t sysfs_fw_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + char *strptr; + + if (count >= MAX_BUFFER_SIZE) { + dev_err(dev, "Input over %d chars long\n", MAX_BUFFER_SIZE); + return -EINVAL; + } + + strptr = strnstr(buf, ".bin", count); + if (!strptr) { + dev_err(dev, "Input is invalid fw file\n"); + return -EINVAL; + } + + strlcpy(gl_ts->fw_name, buf, count); + return count; +} + +static ssize_t sysfs_fw_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (strnlen(gl_ts->fw_name, MAX_BUFFER_SIZE) > 0) + return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n", + gl_ts->fw_name); + else + return scnprintf(buf, MAX_BUFFER_SIZE, + "No firmware file name given\n"); +} + static DEVICE_ATTR(version, S_IRUGO | S_IWUSR, - sysfsVersionShow, NULL); + sysfs_version_show, NULL); static DEVICE_ATTR(sleep, S_IRUGO | S_IWUSR, - sysfsSleepShow, sysfsSleepStore); -static DEVICE_ATTR(calibration, S_IRUGO|S_IWUSR|S_IWGRP, - sysfsCalibrationShow, sysfsCalibrationStore); -static DEVICE_ATTR(upgrade, S_IRUGO|S_IWUSR|S_IWGRP, - sysfsUpgradeShow, sysfsUpgradeStore); -static DEVICE_ATTR(point, S_IRUGO|S_IWUSR|S_IWGRP, - sysfsPointShow, sysfsPointStore); + sysfs_sleep_show, sysfs_sleep_store); +static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR, + sysfs_calibration_show, sysfs_calibration_store); +static DEVICE_ATTR(fw_update, S_IRUGO | S_IWUSR, + sysfs_fw_upgrade_show, sysfs_fw_upgrade_store); +static DEVICE_ATTR(cfg_update, S_IRUGO | S_IWUSR, + sysfs_cfg_upgrade_show, sysfs_cfg_upgrade_store); +static DEVICE_ATTR(point, S_IRUGO | S_IWUSR, + sysfs_point_show, NULL); +static DEVICE_ATTR(fw_name, S_IRUGO | S_IWUSR, + sysfs_fw_name_show, sysfs_fw_name_store); +static DEVICE_ATTR(cfg_name, S_IRUGO | S_IWUSR, + sysfs_cfg_name_show, sysfs_cfg_name_store); static struct attribute *it7260_attributes[] = { &dev_attr_version.attr, &dev_attr_sleep.attr, &dev_attr_calibration.attr, - &dev_attr_upgrade.attr, + &dev_attr_fw_update.attr, + &dev_attr_cfg_update.attr, &dev_attr_point.attr, + &dev_attr_fw_name.attr, + &dev_attr_cfg_name.attr, NULL }; @@ -686,7 +894,7 @@ static void IT7260_chipExternalCalibration(bool autoTuneEnabled) IT7260_chipSendCalibrationCmd(autoTuneEnabled)); IT7260_waitDeviceReady(true, true); IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp)); - IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_C); + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_C); } void IT7260_sendCalibrationCmd(void) @@ -975,11 +1183,32 @@ static int IT7260_ts_probe(struct i2c_client *client, } } + ret = of_property_read_string(client->dev.of_node, + "ite,fw-name", &pdata->fw_name); + if (ret && (ret != -EINVAL)) { + dev_err(&client->dev, "Unable to read fw file name %d\n", ret); + return ret; + } + + ret = of_property_read_string(client->dev.of_node, + "ite,cfg-name", &pdata->cfg_name); + if (ret && (ret != -EINVAL)) { + dev_err(&client->dev, "Unable to read cfg file name %d\n", ret); + return ret; + } + + snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s", + (pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME); + snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s", + (pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME); + if (!IT7260_chipIdentify()) { dev_err(&client->dev, "Failed to identify chip!!!"); goto err_identification_fail; } + IT7260_get_chip_versions(&client->dev); + gl_ts->input_dev = input_allocate_device(); if (!gl_ts->input_dev) { dev_err(&client->dev, "failed to allocate input device\n"); @@ -987,6 +1216,9 @@ static int IT7260_ts_probe(struct i2c_client *client, goto err_input_alloc; } + /* Initialize mutex for fw and cfg upgrade */ + mutex_init(&gl_ts->fw_cfg_mutex); + gl_ts->input_dev->name = DEVICE_NAME; gl_ts->input_dev->phys = "I2C"; gl_ts->input_dev->id.bustype = BUS_I2C; @@ -1035,7 +1267,7 @@ static int IT7260_ts_probe(struct i2c_client *client, ret = fb_register_client(&gl_ts->fb_notif); if (ret) - dev_err(&client->dev, "Unable to register fb_notifier: %d\n", + dev_err(&client->dev, "Unable to register fb_notifier %d\n", ret); #endif @@ -1162,9 +1394,11 @@ static int IT7260_ts_resume(struct device *dev) return 0; } - if (device_may_wakeup(dev) && (gl_ts->device_needs_wakeup)) { - gl_ts->device_needs_wakeup = false; - disable_irq_wake(gl_ts->client->irq); + if (device_may_wakeup(dev)) { + if (gl_ts->device_needs_wakeup) { + gl_ts->device_needs_wakeup = false; + disable_irq_wake(gl_ts->client->irq); + } return 0; } @@ -1178,14 +1412,21 @@ static int IT7260_ts_resume(struct device *dev) static int IT7260_ts_suspend(struct device *dev) { + if (gl_ts->fw_cfg_uploading) { + dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n"); + return -EBUSY; + } + if (gl_ts->suspended) { dev_info(dev, "Already in suspend state\n"); return 0; } - if (device_may_wakeup(dev) && (!gl_ts->device_needs_wakeup)) { - gl_ts->device_needs_wakeup = true; - enable_irq_wake(gl_ts->client->irq); + if (device_may_wakeup(dev)) { + if (!gl_ts->device_needs_wakeup) { + gl_ts->device_needs_wakeup = true; + enable_irq_wake(gl_ts->client->irq); + } return 0; } From a499096f0d909560455ec2420391d974b117a2c5 Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 28 May 2015 21:47:00 +0530 Subject: [PATCH 3/5] input: it7258_ts_i2c: add force fw and cfg update functionality Add force firmware and config update functionality to ITE Tech touchscreen driver. Change-Id: I63720092f445700b7ae66e10950d87a4654060aa Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/it7258_ts_i2c.c | 86 +++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c index c3dd88c08d7e..2b366b8d282b 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -670,6 +670,84 @@ static ssize_t sysfs_cfg_upgrade_show(struct device *dev, gl_ts->cfg_upgrade_result); } +static ssize_t sysfs_force_fw_upgrade_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int mode = 0, ret; + + if (gl_ts->suspended) { + dev_err(dev, "Device is suspended, can't flash fw!!!\n"); + return -EBUSY; + } + + ret = kstrtoint(buf, 10, &mode); + if (!ret) { + dev_err(dev, "failed to read input for sysfs\n"); + return -EINVAL; + } + + mutex_lock(&gl_ts->fw_cfg_mutex); + if (mode == 1) { + gl_ts->fw_cfg_uploading = true; + ret = IT7260_fw_upload(dev, true); + if (ret) { + dev_err(dev, "Failed to force flash fw: %d", ret); + gl_ts->fw_upgrade_result = false; + } else { + gl_ts->fw_upgrade_result = true; + } + gl_ts->fw_cfg_uploading = false; + } + mutex_unlock(&gl_ts->fw_cfg_mutex); + + return count; +} + +static ssize_t sysfs_force_cfg_upgrade_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int mode = 0, ret; + + if (gl_ts->suspended) { + dev_err(dev, "Device is suspended, can't flash cfg!!!\n"); + return -EBUSY; + } + + ret = kstrtoint(buf, 10, &mode); + if (!ret) { + dev_err(dev, "failed to read input for sysfs\n"); + return -EINVAL; + } + + mutex_lock(&gl_ts->fw_cfg_mutex); + if (mode == 1) { + gl_ts->fw_cfg_uploading = true; + ret = IT7260_cfg_upload(dev, true); + if (ret) { + dev_err(dev, "Failed to force flash cfg: %d", ret); + gl_ts->cfg_upgrade_result = false; + } else { + gl_ts->cfg_upgrade_result = true; + } + gl_ts->fw_cfg_uploading = false; + } + mutex_unlock(&gl_ts->fw_cfg_mutex); + + return count; +} + +static ssize_t sysfs_force_fw_upgrade_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result); +} + +static ssize_t sysfs_force_cfg_upgrade_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->cfg_upgrade_result); +} + static ssize_t sysfs_calibration_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -869,6 +947,12 @@ static DEVICE_ATTR(fw_name, S_IRUGO | S_IWUSR, sysfs_fw_name_show, sysfs_fw_name_store); static DEVICE_ATTR(cfg_name, S_IRUGO | S_IWUSR, sysfs_cfg_name_show, sysfs_cfg_name_store); +static DEVICE_ATTR(force_fw_update, S_IRUGO | S_IWUSR, + sysfs_force_fw_upgrade_show, + sysfs_force_fw_upgrade_store); +static DEVICE_ATTR(force_cfg_update, S_IRUGO | S_IWUSR, + sysfs_force_cfg_upgrade_show, + sysfs_force_cfg_upgrade_store); static struct attribute *it7260_attributes[] = { &dev_attr_version.attr, @@ -879,6 +963,8 @@ static struct attribute *it7260_attributes[] = { &dev_attr_point.attr, &dev_attr_fw_name.attr, &dev_attr_cfg_name.attr, + &dev_attr_force_fw_update.attr, + &dev_attr_force_cfg_update.attr, NULL }; From 284922b73a3eaee351bcc3ac433f9da49a41ebdc Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Mon, 18 May 2015 18:59:19 +0530 Subject: [PATCH 4/5] input: it7258_ts_i2c: add dt parsing support Add DT parsing support to ITE tech touchscreen driver. Change-Id: I4b6b9867dc0d74c02d165aae670213544fcda1bc Signed-off-by: Shantanu Jain --- .../input/touchscreen/it7258_ts_i2c.txt | 8 + drivers/input/touchscreen/it7258_ts_i2c.c | 197 +++++++++++++----- 2 files changed, 154 insertions(+), 51 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt index c95ccad4a841..b06aca1755b9 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt @@ -26,6 +26,11 @@ Optional properties: palm is detected. - ite,fw-name : Specify firmware file name in /etc/firmware - ite,cfg-name : Specify config file name in /etc/firmware + - ite,panel-coords : touch panel min x, min y, max x and + max y resolution + - ite,display-coords : display min x, min y, max x and + max y resolution + - ite,num-fingers : number of fingers supported by the touch controller Required properties palm-detect-en feature: - ite,palm-detect-keycode : The keycode that is required to be sent when @@ -47,5 +52,8 @@ Example: ite,palm-detect-keycode = <142>; ite,fw-name = "ite7260_fw.bin"; ite,cfg-name = "ite7260_cfg.bin"; + ite,panel-coords = <0 0 320 320>; + ite,display-coords = <0 0 320 320>; + ite,num-fingers = <2>; }; }; diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c index 2b366b8d282b..85bf0827d18d 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -45,6 +45,7 @@ ((x)[1] < (y)->data[(y)->size - 7]) || \ ((x)[2] < (y)->data[(y)->size - 6]) || \ ((x)[3] < (y)->data[(y)->size - 5])) +#define IT7260_COORDS_ARR_SIZE 4 /* all commands writes go to this idx */ #define BUF_COMMAND 0x20 @@ -113,8 +114,6 @@ #define PD_FLAGS_DATA_TYPE_TOUCH 0x00 /* a bit for each finger data that is valid (from lsb to msb) */ #define PD_FLAGS_HAVE_FINGERS 0x07 -/* number of finger supported */ -#define PD_FINGERS_SUPPORTED 3 #define PD_PALM_FLAG_BIT 0x01 #define FD_PRESSURE_BITS 0x0F #define FD_PRESSURE_NONE 0x00 @@ -139,7 +138,6 @@ struct PointData { } __packed; struct IT7260_ts_platform_data { - u32 irqflags; u32 irq_gpio; u32 irq_gpio_flags; u32 reset_gpio; @@ -149,6 +147,15 @@ struct IT7260_ts_platform_data { u16 palm_detect_keycode; const char *fw_name; const char *cfg_name; + unsigned int panel_minx; + unsigned int panel_miny; + unsigned int panel_maxx; + unsigned int panel_maxy; + unsigned int disp_minx; + unsigned int disp_miny; + unsigned int disp_maxx; + unsigned int disp_maxy; + unsigned num_of_fingers; }; struct IT7260_ts_data { @@ -993,7 +1000,7 @@ static void IT7260_ts_release_all(void) { int finger; - for (finger = 0; finger < PD_FINGERS_SUPPORTED; finger++) { + for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) { input_mt_slot(gl_ts->input_dev, finger); input_mt_report_slot_state(gl_ts->input_dev, MT_TOOL_FINGER, 0); @@ -1058,7 +1065,7 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid) input_sync(input_dev); } - for (finger = 0; finger < PD_FINGERS_SUPPORTED; finger++) { + for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) { finger_status = point_data.flags & (0x01 << finger); input_mt_slot(input_dev, finger); @@ -1136,6 +1143,130 @@ static bool IT7260_chipIdentify(void) return true; } +#if CONFIG_OF +static int IT7260_get_dt_coords(struct device *dev, char *name, + struct IT7260_ts_platform_data *pdata) +{ + u32 coords[IT7260_COORDS_ARR_SIZE]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + coords_size = prop->length / sizeof(u32); + if (coords_size != IT7260_COORDS_ARR_SIZE) { + dev_err(dev, "invalid %s\n", name); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read %s\n", name); + return rc; + } + + if (strcmp(name, "ite,panel-coords") == 0) { + pdata->panel_minx = coords[0]; + pdata->panel_miny = coords[1]; + pdata->panel_maxx = coords[2]; + pdata->panel_maxy = coords[3]; + + if (pdata->panel_maxx == 0 || pdata->panel_minx > 0) + rc = -EINVAL; + else if (pdata->panel_maxy == 0 || pdata->panel_miny > 0) + rc = -EINVAL; + + if (rc) { + dev_err(dev, "Invalid panel resolution %d\n", rc); + return rc; + } + } else if (strcmp(name, "ite,display-coords") == 0) { + pdata->disp_minx = coords[0]; + pdata->disp_miny = coords[1]; + pdata->disp_maxx = coords[2]; + pdata->disp_maxy = coords[3]; + } else { + dev_err(dev, "unsupported property %s\n", name); + return -EINVAL; + } + + return 0; +} + +static int IT7260_parse_dt(struct device *dev, + struct IT7260_ts_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + u32 temp_val; + int rc; + + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, + "ite,reset-gpio", 0, &pdata->reset_gpio_flags); + pdata->irq_gpio = of_get_named_gpio_flags(np, + "ite,irq-gpio", 0, &pdata->irq_gpio_flags); + + rc = of_property_read_u32(np, "ite,num-fingers", &temp_val); + if (!rc) + pdata->num_of_fingers = temp_val; + else if (rc != -EINVAL) { + dev_err(dev, "Unable to read reset delay\n"); + return rc; + } + + pdata->wakeup = of_property_read_bool(np, "ite,wakeup"); + pdata->palm_detect_en = of_property_read_bool(np, "ite,palm-detect-en"); + if (pdata->palm_detect_en) { + rc = of_property_read_u32(np, "ite,palm-detect-keycode", + &temp_val); + if (!rc) { + pdata->palm_detect_keycode = temp_val; + } else { + dev_err(dev, "Unable to read palm-detect-keycode\n"); + return rc; + } + } + + rc = of_property_read_string(np, "ite,fw-name", &pdata->fw_name); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw image name %d\n", rc); + return rc; + } + + rc = of_property_read_string(np, "ite,cfg-name", &pdata->cfg_name); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read cfg image name %d\n", rc); + return rc; + } + + snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s", + (pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME); + snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s", + (pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME); + + rc = IT7260_get_dt_coords(dev, "ite,display-coords", pdata); + if (rc && (rc != -EINVAL)) + return rc; + + rc = IT7260_get_dt_coords(dev, "ite,panel-coords", pdata); + if (rc && (rc != -EINVAL)) + return rc; + + return 0; +} +#else +static inline int IT7260_ts_parse_dt(struct device *dev, + struct IT7260_ts_platform_data *pdata) +{ + return 0; +} +#endif + static int IT7260_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1143,7 +1274,6 @@ static int IT7260_ts_probe(struct i2c_client *client, struct IT7260_ts_platform_data *pdata; uint8_t rsp[2]; int ret = -1; - u32 temp_val; struct dentry *temp; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { @@ -1165,6 +1295,10 @@ static int IT7260_ts_probe(struct i2c_client *client, pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; + + ret = IT7260_parse_dt(&client->dev, pdata); + if (ret) + return ret; } else { pdata = client->dev.platform_data; } @@ -1223,9 +1357,6 @@ static int IT7260_ts_probe(struct i2c_client *client, } /* reset gpio info */ - pdata->reset_gpio = of_get_named_gpio_flags(client->dev.of_node, - "ite,reset-gpio", 0, - &pdata->reset_gpio_flags); if (gpio_is_valid(pdata->reset_gpio)) { if (gpio_request(pdata->reset_gpio, "ite_reset_gpio")) { dev_err(&client->dev, @@ -1244,8 +1375,6 @@ static int IT7260_ts_probe(struct i2c_client *client, } /* irq gpio info */ - pdata->irq_gpio = of_get_named_gpio_flags(client->dev.of_node, - "ite,irq-gpio", 0, &pdata->irq_gpio_flags); if (gpio_is_valid(pdata->irq_gpio)) { dev_dbg(&gl_ts->client->dev, "IRQ GPIO %d, IRQ # %d\n", pdata->irq_gpio, gpio_to_irq(pdata->irq_gpio)); @@ -1253,41 +1382,6 @@ static int IT7260_ts_probe(struct i2c_client *client, return pdata->irq_gpio; } - pdata->wakeup = of_property_read_bool(client->dev.of_node, - "ite,wakeup"); - pdata->palm_detect_en = of_property_read_bool(client->dev.of_node, - "ite,palm-detect-en"); - if (pdata->palm_detect_en) { - ret = of_property_read_u32(client->dev.of_node, - "ite,palm-detect-keycode", &temp_val); - if (!ret) { - pdata->palm_detect_keycode = temp_val; - } else { - dev_err(&client->dev, - "Unable to read palm-detect-keycode\n"); - return ret; - } - } - - ret = of_property_read_string(client->dev.of_node, - "ite,fw-name", &pdata->fw_name); - if (ret && (ret != -EINVAL)) { - dev_err(&client->dev, "Unable to read fw file name %d\n", ret); - return ret; - } - - ret = of_property_read_string(client->dev.of_node, - "ite,cfg-name", &pdata->cfg_name); - if (ret && (ret != -EINVAL)) { - dev_err(&client->dev, "Unable to read cfg file name %d\n", ret); - return ret; - } - - snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s", - (pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME); - snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s", - (pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME); - if (!IT7260_chipIdentify()) { dev_err(&client->dev, "Failed to identify chip!!!"); goto err_identification_fail; @@ -1315,12 +1409,13 @@ static int IT7260_ts_probe(struct i2c_client *client, set_bit(EV_ABS, gl_ts->input_dev->evbit); set_bit(INPUT_PROP_DIRECT, gl_ts->input_dev->propbit); set_bit(BTN_TOUCH, gl_ts->input_dev->keybit); - input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_X, 0, - SCREEN_X_RESOLUTION, 0, 0); - input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_Y, 0, - SCREEN_Y_RESOLUTION, 0, 0); + input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_X, + gl_ts->pdata->disp_minx, gl_ts->pdata->disp_maxx, 0, 0); + input_set_abs_params(gl_ts->input_dev, ABS_MT_POSITION_Y, + gl_ts->pdata->disp_miny, gl_ts->pdata->disp_maxy, 0, 0); + input_mt_init_slots(gl_ts->input_dev, gl_ts->pdata->num_of_fingers, 0); + input_set_drvdata(gl_ts->input_dev, gl_ts); - input_mt_init_slots(gl_ts->input_dev, PD_FINGERS_SUPPORTED, 0); if (pdata->wakeup) { set_bit(KEY_WAKEUP, gl_ts->input_dev->keybit); From 13543441089c92d2402d8c1dfe388c5059fcb1eb Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Thu, 18 Jun 2015 13:29:07 +0530 Subject: [PATCH 5/5] input: it7258_ts_i2c: add low power mode support in suspend state Add low power idle mode support in suspend state for ITE tech touchscreen driver. Also, execute the touch to wake feature code only when device moves from idle state to active state. Change-Id: Ia989d8130bbded4ae5acab0b9c3122998acb2056 Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/it7258_ts_i2c.c | 75 ++++++++++------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c index 85bf0827d18d..82bb32422f9e 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -73,10 +73,13 @@ #define VERSION_LENGTH 10 /* subcommand is zero, next byte is power mode */ #define CMD_PWR_CTL 0x04 +/* active mode */ +#define PWR_CTL_ACTIVE_MODE 0x00 /* idle mode */ #define PWR_CTL_LOW_POWER_MODE 0x01 /* sleep mode */ #define PWR_CTL_SLEEP_MODE 0x02 +#define WAIT_CHANGE_MODE 20 /* command is not documented in the datasheet v1.0.0.7 */ #define CMD_UNKNOWN_7 0x07 #define CMD_FIRMWARE_REINIT_C 0x0C @@ -582,18 +585,18 @@ out: return ret; } -static int IT7260_ts_chipLowPowerMode(bool low) +static int IT7260_ts_chipLowPowerMode(const u8 sleep_type) { - static const uint8_t cmd_sleep[] = {CMD_PWR_CTL, - 0x00, PWR_CTL_SLEEP_MODE}; + const uint8_t cmd_sleep[] = {CMD_PWR_CTL, 0x00, sleep_type}; uint8_t dummy; - if (low) + if (sleep_type) IT7260_i2cWriteNoReadyCheck(BUF_COMMAND, cmd_sleep, sizeof(cmd_sleep)); else IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dummy, sizeof(dummy)); + msleep(WAIT_CHANGE_MODE); return 0; } @@ -863,10 +866,10 @@ static ssize_t sysfs_sleep_store(struct device *dev, go_to_sleep ? "sleep" : "wake"); else if (go_to_sleep) { disable_irq(gl_ts->client->irq); - IT7260_ts_chipLowPowerMode(true); + IT7260_ts_chipLowPowerMode(PWR_CTL_SLEEP_MODE); dev_dbg(dev, "touch is going to sleep...\n"); } else { - IT7260_ts_chipLowPowerMode(false); + IT7260_ts_chipLowPowerMode(PWR_CTL_ACTIVE_MODE); enable_irq(gl_ts->client->irq); dev_dbg(dev, "touch is going to wake!\n"); } @@ -1019,24 +1022,6 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid) u16 x, y; bool palm_detected; - /* - * This code adds the touch-to-wake functionality to the ITE tech - * driver. When the device is in suspend, driver sends the - * KEY_WAKEUP event to wake the device. The pm_stay_awake() call - * tells the pm core to stay awake until the CPU cores up already. The - * schedule_work() call schedule a work that tells the pm core to relax - * once the CPU cores are up. - */ - if (gl_ts->device_needs_wakeup) { - pm_stay_awake(&gl_ts->client->dev); - gl_ts->device_needs_wakeup = false; - input_report_key(input_dev, KEY_WAKEUP, 1); - input_sync(input_dev); - input_report_key(input_dev, KEY_WAKEUP, 0); - input_sync(input_dev); - schedule_work(&gl_ts->work_pm_relax); - } - /* verify there is point data to read & it is readable and valid */ IT7260_i2cReadNoReadyCheck(BUF_QUERY, &dev_status, sizeof(dev_status)); if (!((dev_status & PT_INFO_BITS) & PT_INFO_YES)) @@ -1047,12 +1032,29 @@ static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid) "failed to read point data buffer\n"); return IRQ_HANDLED; } + + /* Check if controller moves from idle to active state */ if ((point_data.flags & PD_FLAGS_DATA_TYPE_BITS) != PD_FLAGS_DATA_TYPE_TOUCH) { - dev_err(&gl_ts->client->dev, - "dropping non-point data of type 0x%02X\n", - point_data.flags); - return IRQ_HANDLED; + /* + * This code adds the touch-to-wake functionality to the ITE + * tech driver. When user puts a finger on touch controller in + * idle state, the controller moves to active state and driver + * sends the KEY_WAKEUP event to wake the device. The + * pm_stay_awake() call tells the pm core to stay awake until + * the CPU cores are up already. The schedule_work() call + * schedule a work that tells the pm core to relax once the CPU + * cores are up. + */ + if (gl_ts->device_needs_wakeup) { + pm_stay_awake(&gl_ts->client->dev); + input_report_key(input_dev, KEY_WAKEUP, 1); + input_sync(input_dev); + input_report_key(input_dev, KEY_WAKEUP, 0); + input_sync(input_dev); + schedule_work(&gl_ts->work_pm_relax); + return IRQ_HANDLED; + } } palm_detected = point_data.palm & PD_PALM_FLAG_BIT; @@ -1570,11 +1572,6 @@ static int fb_notifier_callback(struct notifier_block *self, #ifdef CONFIG_PM static int IT7260_ts_resume(struct device *dev) { - if (!gl_ts->suspended) { - dev_info(dev, "Already in resume state\n"); - return 0; - } - if (device_may_wakeup(dev)) { if (gl_ts->device_needs_wakeup) { gl_ts->device_needs_wakeup = false; @@ -1583,9 +1580,6 @@ static int IT7260_ts_resume(struct device *dev) return 0; } - /* put the device in active power mode */ - IT7260_ts_chipLowPowerMode(false); - enable_irq(gl_ts->client->irq); gl_ts->suspended = false; return 0; @@ -1598,10 +1592,8 @@ static int IT7260_ts_suspend(struct device *dev) return -EBUSY; } - if (gl_ts->suspended) { - dev_info(dev, "Already in suspend state\n"); - return 0; - } + /* put the device in low power idle mode */ + IT7260_ts_chipLowPowerMode(PWR_CTL_LOW_POWER_MODE); if (device_may_wakeup(dev)) { if (!gl_ts->device_needs_wakeup) { @@ -1613,9 +1605,6 @@ static int IT7260_ts_suspend(struct device *dev) disable_irq(gl_ts->client->irq); - /* put the device in low power mode */ - IT7260_ts_chipLowPowerMode(true); - IT7260_ts_release_all(); gl_ts->suspended = true;