summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-02 06:42:37 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-02 06:42:36 -0700
commit412270ed6e742f05d91abf895e09c9dd7e8f63c2 (patch)
tree53c5a7a04af4cac5760ca84eacad7f43c6c81ea3
parent7341630e3531834d81d53df2c5b3f60790e20d91 (diff)
parent13543441089c92d2402d8c1dfe388c5059fcb1eb (diff)
Merge "input: it7258_ts_i2c: add low power mode support in suspend state"
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt12
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c951
2 files changed, 687 insertions, 276 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..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 <linux/of_gpio.h>
#include <linux/fb.h>
#include <linux/debugfs.h>
+#include <linux/input/mt.h>
+#include <linux/string.h>
#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)
+/*
+ * this code to get versions from the chip via i2c transactions, and save
+ * them in driver data structure.
+ */
+static void IT7260_get_chip_versions(struct device *dev)
{
- bool success = false;
+ 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;
- /* enter fw upload mode */
- if (!IT7260_chipFirmwareUpgradeModeEnterExit(true))
- return false;
+ ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver,
+ 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");
- /* 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;
+ 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");
- /* 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;
+ 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;
}
- success = true;
+ /*
+ * 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:
- return IT7260_chipFirmwareUpgradeModeEnterExit(false) &&
- IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F) &&
- success;
-}
+ release_firmware(cfg);
+ return ret;
+}
-/*
- * both buffers should be VERSION_LENGTH in size,
- * but only a part of them is significant
- */
-static bool IT7260_chipGetVersions(uint8_t *ver_fw, uint8_t *ver_cfg,
- bool log_it)
+static int IT7260_fw_upload(struct device *dev, bool force)
{
- /*
- * 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};
- bool ret = true;
+ 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 structure is so that we definitely do all the calls, but still
- * return a status in case anyone cares
+ * 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.
*/
- 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;
+ 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");
- 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]);
+ 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(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;
}
-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;
+ if (gl_ts->suspended) {
+ dev_err(dev, "Device is suspended, can't flash fw!!!\n");
+ return -EBUSY;
+ }
- 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);
+ 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, 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 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;
+ }
- 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");
+ 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 {
- dev_info(dev, "firmware/config upgrade not needed\n");
+ gl_ts->fw_upgrade_result = true;
}
+ gl_ts->fw_cfg_uploading = false;
}
+ mutex_unlock(&gl_ts->fw_cfg_mutex);
- if (fw_len)
- release_firmware(fw);
+ return count;
+}
- if (cfg_len)
- release_firmware(cfg);
+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 sysfsUpgradeShow(struct device *dev,
+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);
-
- if (pressure >= FD_PRESSURE_LIGHT) {
- if (!gl_ts->had_finger_down)
- gl_ts->had_finger_down = true;
-
- IT7260_readFingerData(&x, &y, &pressure, point_data.fd);
-
- 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);
-
-
- } 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);
+ for (finger = 0; finger < gl_ts->pdata->num_of_fingers; finger++) {
+ finger_status = point_data.flags & (0x01 << finger);
+
+ input_mt_slot(input_dev, finger);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+ finger_status != 0);
+
+ 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);
+
+ pressure = point_data.fd[finger].pressure & FD_PRESSURE_BITS;
+
+ 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");
- 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;
}
- /* 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;