diff --git a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt index 0b57ba0b62a0..b06aca1755b9 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt @@ -24,6 +24,13 @@ 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 + - 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 @@ -43,5 +50,10 @@ Example: ite,wakeup; ite,palm-detect-en; 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 011980ce2024..82bb32422f9e 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -26,12 +26,26 @@ #include #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])) +#define IT7260_COORDS_ARR_SIZE 4 /* all commands writes go to this idx */ #define BUF_COMMAND 0x20 @@ -54,23 +68,26 @@ #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 +/* 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 /* 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 */ @@ -98,18 +115,12 @@ #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 #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 @@ -130,7 +141,6 @@ struct PointData { } __packed; struct IT7260_ts_platform_data { - u32 irqflags; u32 irq_gpio; u32 irq_gpio_flags; u32 reset_gpio; @@ -138,6 +148,17 @@ struct IT7260_ts_platform_data { bool wakeup; bool palm_detect_en; 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 { @@ -148,10 +169,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 @@ -166,12 +194,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) @@ -278,7 +300,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]; @@ -293,13 +315,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; @@ -330,7 +353,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; @@ -393,159 +416,353 @@ 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_ts_chipLowPowerMode(bool low) +static int IT7260_fw_upload(struct device *dev, bool force) { - static const uint8_t cmd_sleep[] = {CMD_PWR_CTL, - 0x00, PWR_CTL_SLEEP_MODE}; + 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; +} + +static int IT7260_ts_chipLowPowerMode(const u8 sleep_type) +{ + 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; } -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, +static ssize_t sysfs_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, 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 sysfs_fw_upgrade_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + 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_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 sysfsCalibrationShow(struct device *dev, +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->calibration_success); + 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) +{ + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->calibration_success); } static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on) @@ -556,7 +773,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; @@ -569,20 +786,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)]; @@ -591,37 +808,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) { /* @@ -633,7 +848,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; @@ -651,10 +866,10 @@ static ssize_t sysfsSleepStore(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"); } @@ -663,23 +878,103 @@ 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 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, &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, + &dev_attr_force_fw_update.attr, + &dev_attr_force_cfg_update.attr, NULL }; @@ -695,7 +990,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) @@ -706,53 +1001,26 @@ EXPORT_SYMBOL(IT7260_sendCalibrationCmd); static void IT7260_ts_release_all(void) { + int 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); + } + 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 - * 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(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); - 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)); @@ -764,48 +1032,70 @@ 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; 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 < gl_ts->pdata->num_of_fingers; 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; } @@ -855,6 +1145,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) { @@ -862,7 +1276,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)) { @@ -884,6 +1297,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; } @@ -942,9 +1359,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, @@ -963,8 +1377,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)); @@ -972,27 +1384,13 @@ 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; - } - } - 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"); @@ -1000,6 +1398,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; @@ -1010,10 +1411,12 @@ 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); if (pdata->wakeup) { @@ -1047,7 +1450,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 @@ -1169,20 +1572,14 @@ 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"); + 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; } - if (device_may_wakeup(dev) && (gl_ts->device_needs_wakeup)) { - gl_ts->device_needs_wakeup = false; - disable_irq_wake(gl_ts->client->irq); - 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; @@ -1190,22 +1587,24 @@ static int IT7260_ts_resume(struct device *dev) static int IT7260_ts_suspend(struct device *dev) { - if (gl_ts->suspended) { - dev_info(dev, "Already in suspend state\n"); - return 0; + if (gl_ts->fw_cfg_uploading) { + dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n"); + return -EBUSY; } - if (device_may_wakeup(dev) && (!gl_ts->device_needs_wakeup)) { - gl_ts->device_needs_wakeup = true; - enable_irq_wake(gl_ts->client->irq); + /* 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) { + gl_ts->device_needs_wakeup = true; + enable_irq_wake(gl_ts->client->irq); + } return 0; } 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;