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 <shjain@codeaurora.org>
This commit is contained in:
parent
97f29fe6f3
commit
1f51fe6ebe
2 changed files with 410 additions and 165 deletions
|
@ -24,6 +24,8 @@ Optional properties:
|
||||||
- ite,wakeup : boolean, use this to support touch-to-wake feature.
|
- ite,wakeup : boolean, use this to support touch-to-wake feature.
|
||||||
- ite,palm-detect-en : boolean, use this to send palm-detect-keycode when
|
- ite,palm-detect-en : boolean, use this to send palm-detect-keycode when
|
||||||
palm is detected.
|
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:
|
Required properties palm-detect-en feature:
|
||||||
- ite,palm-detect-keycode : The keycode that is required to be sent when
|
- ite,palm-detect-keycode : The keycode that is required to be sent when
|
||||||
|
@ -43,5 +45,7 @@ Example:
|
||||||
ite,wakeup;
|
ite,wakeup;
|
||||||
ite,palm-detect-en;
|
ite,palm-detect-en;
|
||||||
ite,palm-detect-keycode = <142>;
|
ite,palm-detect-keycode = <142>;
|
||||||
|
ite,fw-name = "ite7260_fw.bin";
|
||||||
|
ite,cfg-name = "ite7260_cfg.bin";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,12 +27,24 @@
|
||||||
#include <linux/fb.h>
|
#include <linux/fb.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/input/mt.h>
|
#include <linux/input/mt.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
|
||||||
#define MAX_BUFFER_SIZE 144
|
#define MAX_BUFFER_SIZE 144
|
||||||
#define DEVICE_NAME "IT7260"
|
#define DEVICE_NAME "IT7260"
|
||||||
#define SCREEN_X_RESOLUTION 320
|
#define SCREEN_X_RESOLUTION 320
|
||||||
#define SCREEN_Y_RESOLUTION 320
|
#define SCREEN_Y_RESOLUTION 320
|
||||||
#define DEBUGFS_DIR_NAME "ts_debug"
|
#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 */
|
/* all commands writes go to this idx */
|
||||||
#define BUF_COMMAND 0x20
|
#define BUF_COMMAND 0x20
|
||||||
|
@ -55,8 +67,8 @@
|
||||||
#define CMD_IDENT_CHIP 0x00
|
#define CMD_IDENT_CHIP 0x00
|
||||||
/* VERSION_LENGTH bytes of data in response */
|
/* VERSION_LENGTH bytes of data in response */
|
||||||
#define CMD_READ_VERSIONS 0x01
|
#define CMD_READ_VERSIONS 0x01
|
||||||
#define VER_FIRMWARE 0x00
|
#define SUB_CMD_READ_FIRMWARE_VERSION 0x00
|
||||||
#define VER_CONFIG 0x06
|
#define SUB_CMD_READ_CONFIG_VERSION 0x06
|
||||||
#define VERSION_LENGTH 10
|
#define VERSION_LENGTH 10
|
||||||
/* subcommand is zero, next byte is power mode */
|
/* subcommand is zero, next byte is power mode */
|
||||||
#define CMD_PWR_CTL 0x04
|
#define CMD_PWR_CTL 0x04
|
||||||
|
@ -70,8 +82,8 @@
|
||||||
/* needs to be followed by 4 bytes of zeroes */
|
/* needs to be followed by 4 bytes of zeroes */
|
||||||
#define CMD_CALIBRATE 0x13
|
#define CMD_CALIBRATE 0x13
|
||||||
#define CMD_FIRMWARE_UPGRADE 0x60
|
#define CMD_FIRMWARE_UPGRADE 0x60
|
||||||
#define FIRMWARE_MODE_ENTER 0x00
|
#define SUB_CMD_ENTER_FW_UPGRADE_MODE 0x00
|
||||||
#define FIRMWARE_MODE_EXIT 0x80
|
#define SUB_CMD_EXIT_FW_UPGRADE_MODE 0x80
|
||||||
/* address for FW read/write */
|
/* address for FW read/write */
|
||||||
#define CMD_SET_START_OFFSET 0x61
|
#define CMD_SET_START_OFFSET 0x61
|
||||||
/* subcommand is number of bytes to write */
|
/* subcommand is number of bytes to write */
|
||||||
|
@ -135,6 +147,8 @@ struct IT7260_ts_platform_data {
|
||||||
bool wakeup;
|
bool wakeup;
|
||||||
bool palm_detect_en;
|
bool palm_detect_en;
|
||||||
u16 palm_detect_keycode;
|
u16 palm_detect_keycode;
|
||||||
|
const char *fw_name;
|
||||||
|
const char *cfg_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IT7260_ts_data {
|
struct IT7260_ts_data {
|
||||||
|
@ -145,10 +159,17 @@ struct IT7260_ts_data {
|
||||||
struct regulator *avdd;
|
struct regulator *avdd;
|
||||||
bool device_needs_wakeup;
|
bool device_needs_wakeup;
|
||||||
bool suspended;
|
bool suspended;
|
||||||
struct work_struct work_pm_relax;
|
|
||||||
bool fw_upgrade_result;
|
bool fw_upgrade_result;
|
||||||
|
bool cfg_upgrade_result;
|
||||||
|
bool fw_cfg_uploading;
|
||||||
|
struct work_struct work_pm_relax;
|
||||||
bool calibration_success;
|
bool calibration_success;
|
||||||
bool had_finger_down;
|
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
|
#ifdef CONFIG_FB
|
||||||
struct notifier_block fb_notif;
|
struct notifier_block fb_notif;
|
||||||
#endif
|
#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);
|
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 cmd[] = {command};
|
||||||
uint8_t rsp[2];
|
uint8_t rsp[2];
|
||||||
|
@ -284,13 +305,14 @@ static bool IT7260_chipFirmwareReinitialize(uint8_t command)
|
||||||
return !rsp[0] && !rsp[1];
|
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',
|
uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2',
|
||||||
'6', '0', 0x55, 0xAA};
|
'6', '0', 0x55, 0xAA};
|
||||||
uint8_t resp[2];
|
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)))
|
if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd)))
|
||||||
return false;
|
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 */
|
/* 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)
|
const uint8_t *fw_data, uint16_t wr_start_offset)
|
||||||
{
|
{
|
||||||
uint32_t cur_data_off;
|
uint32_t cur_data_off;
|
||||||
|
@ -384,71 +406,171 @@ static bool IT7260_chipFlashWriteAndVerify(unsigned int fw_length,
|
||||||
return true;
|
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,
|
* this code to get versions from the chip via i2c transactions, and save
|
||||||
* but only a part of them is significant
|
* them in driver data structure.
|
||||||
*/
|
*/
|
||||||
static bool IT7260_chipGetVersions(uint8_t *ver_fw, uint8_t *ver_cfg,
|
static void IT7260_get_chip_versions(struct device *dev)
|
||||||
bool log_it)
|
|
||||||
{
|
{
|
||||||
/*
|
static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS,
|
||||||
* this code to get versions is reproduced as was written, but it does
|
SUB_CMD_READ_FIRMWARE_VERSION};
|
||||||
* not make sense. Something here *PROBABLY IS* wrong
|
static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS,
|
||||||
*/
|
SUB_CMD_READ_CONFIG_VERSION};
|
||||||
static const uint8_t cmd_read_fw_ver[] = {CMD_READ_VERSIONS,
|
u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH];
|
||||||
VER_FIRMWARE};
|
|
||||||
static const uint8_t cmd_read_cfg_ver[] = {CMD_READ_VERSIONS,
|
|
||||||
VER_CONFIG};
|
|
||||||
bool ret = true;
|
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,
|
ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver,
|
||||||
sizeof(cmd_read_fw_ver)) && ret;
|
sizeof(cmd_read_fw_ver));
|
||||||
ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH) && ret;
|
if (ret) {
|
||||||
ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver,
|
ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH);
|
||||||
sizeof(cmd_read_cfg_ver)) && ret;
|
if (ret)
|
||||||
ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH) && 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)
|
ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver,
|
||||||
dev_info(&gl_ts->client->dev,
|
sizeof(cmd_read_cfg_ver));
|
||||||
"current versions: fw@{%X,%X,%X,%X}, cfg@{%X,%X,%X,%X}\n",
|
if (ret) {
|
||||||
ver_fw[5], ver_fw[6], ver_fw[7], ver_fw[8],
|
ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH)
|
||||||
ver_cfg[1], ver_cfg[2], ver_cfg[3], ver_cfg[4]);
|
&& 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -468,75 +590,91 @@ static int IT7260_ts_chipLowPowerMode(bool low)
|
||||||
return 0;
|
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)
|
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;
|
int mode = 0, ret;
|
||||||
|
|
||||||
ret = request_firmware(&fw, "it7260.fw", dev);
|
if (gl_ts->suspended) {
|
||||||
if (ret)
|
dev_err(dev, "Device is suspended, can't flash fw!!!\n");
|
||||||
dev_dbg(dev, "failed to get firmware for it7260 %d\n", ret);
|
return -EBUSY;
|
||||||
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);
|
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);
|
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;
|
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 {
|
} 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);
|
|
||||||
|
|
||||||
if (cfg_len)
|
|
||||||
release_firmware(cfg);
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t sysfsUpgradeShow(struct device *dev,
|
static ssize_t sysfs_cfg_upgrade_store(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t sysfsCalibrationShow(struct device *dev,
|
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)
|
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)
|
static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on)
|
||||||
|
@ -547,7 +685,7 @@ static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on)
|
||||||
sizeof(cmd_calibrate));
|
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)
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
uint8_t resp;
|
uint8_t resp;
|
||||||
|
@ -560,20 +698,20 @@ static ssize_t sysfsCalibrationStore(struct device *dev,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* previous logic that was here never called
|
* 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
|
* guaranteed-not-null value against null. We now
|
||||||
* call it. Hopefully this is OK
|
* call it. Hopefully this is OK
|
||||||
*/
|
*/
|
||||||
if (!resp)
|
if (!resp)
|
||||||
dev_dbg(dev, "IT7260_chipFirmwareReinitialize -> %s\n",
|
dev_dbg(dev, "IT7260_firmware_reinitialize-> %s\n",
|
||||||
IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F)
|
IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F)
|
||||||
? "success" : "fail");
|
? "success" : "fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
`
|
|
||||||
static ssize_t sysfsPointShow(struct device *dev,
|
static ssize_t sysfs_point_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
uint8_t point_data[sizeof(struct PointData)];
|
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,
|
readSuccess = IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, point_data,
|
||||||
sizeof(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);
|
dev_dbg(dev, "%s", buf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t sysfsPointStore(struct device *dev,
|
static ssize_t sysfs_version_show(struct device *dev,
|
||||||
struct device_attribute *attr, const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t sysfsVersionShow(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
uint8_t ver_fw[10], ver_cfg[10];
|
return scnprintf(buf, MAX_BUFFER_SIZE,
|
||||||
|
"fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n",
|
||||||
IT7260_chipGetVersions(ver_fw, ver_cfg, false);
|
gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2],
|
||||||
return snprintf(buf, MAX_BUFFER_SIZE,
|
gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1],
|
||||||
"fw{%x,%x,%x,%x} # cfg{%x,%x,%x,%x}\n",
|
gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]);
|
||||||
ver_fw[5], ver_fw[6], ver_fw[7], ver_fw[8],
|
|
||||||
ver_cfg[1], ver_cfg[2], ver_cfg[3], ver_cfg[4]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t sysfsSleepShow(struct device *dev,
|
static ssize_t sysfs_sleep_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -624,7 +760,7 @@ static ssize_t sysfsSleepShow(struct device *dev,
|
||||||
return 1;
|
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)
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
int go_to_sleep, ret;
|
int go_to_sleep, ret;
|
||||||
|
@ -654,23 +790,95 @@ static ssize_t sysfsSleepStore(struct device *dev,
|
||||||
return count;
|
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,
|
static DEVICE_ATTR(version, S_IRUGO | S_IWUSR,
|
||||||
sysfsVersionShow, NULL);
|
sysfs_version_show, NULL);
|
||||||
static DEVICE_ATTR(sleep, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(sleep, S_IRUGO | S_IWUSR,
|
||||||
sysfsSleepShow, sysfsSleepStore);
|
sysfs_sleep_show, sysfs_sleep_store);
|
||||||
static DEVICE_ATTR(calibration, S_IRUGO|S_IWUSR|S_IWGRP,
|
static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR,
|
||||||
sysfsCalibrationShow, sysfsCalibrationStore);
|
sysfs_calibration_show, sysfs_calibration_store);
|
||||||
static DEVICE_ATTR(upgrade, S_IRUGO|S_IWUSR|S_IWGRP,
|
static DEVICE_ATTR(fw_update, S_IRUGO | S_IWUSR,
|
||||||
sysfsUpgradeShow, sysfsUpgradeStore);
|
sysfs_fw_upgrade_show, sysfs_fw_upgrade_store);
|
||||||
static DEVICE_ATTR(point, S_IRUGO|S_IWUSR|S_IWGRP,
|
static DEVICE_ATTR(cfg_update, S_IRUGO | S_IWUSR,
|
||||||
sysfsPointShow, sysfsPointStore);
|
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[] = {
|
static struct attribute *it7260_attributes[] = {
|
||||||
&dev_attr_version.attr,
|
&dev_attr_version.attr,
|
||||||
&dev_attr_sleep.attr,
|
&dev_attr_sleep.attr,
|
||||||
&dev_attr_calibration.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_point.attr,
|
||||||
|
&dev_attr_fw_name.attr,
|
||||||
|
&dev_attr_cfg_name.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -686,7 +894,7 @@ static void IT7260_chipExternalCalibration(bool autoTuneEnabled)
|
||||||
IT7260_chipSendCalibrationCmd(autoTuneEnabled));
|
IT7260_chipSendCalibrationCmd(autoTuneEnabled));
|
||||||
IT7260_waitDeviceReady(true, true);
|
IT7260_waitDeviceReady(true, true);
|
||||||
IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp));
|
IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp));
|
||||||
IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_C);
|
IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_C);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT7260_sendCalibrationCmd(void)
|
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()) {
|
if (!IT7260_chipIdentify()) {
|
||||||
dev_err(&client->dev, "Failed to identify chip!!!");
|
dev_err(&client->dev, "Failed to identify chip!!!");
|
||||||
goto err_identification_fail;
|
goto err_identification_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IT7260_get_chip_versions(&client->dev);
|
||||||
|
|
||||||
gl_ts->input_dev = input_allocate_device();
|
gl_ts->input_dev = input_allocate_device();
|
||||||
if (!gl_ts->input_dev) {
|
if (!gl_ts->input_dev) {
|
||||||
dev_err(&client->dev, "failed to allocate input device\n");
|
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;
|
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->name = DEVICE_NAME;
|
||||||
gl_ts->input_dev->phys = "I2C";
|
gl_ts->input_dev->phys = "I2C";
|
||||||
gl_ts->input_dev->id.bustype = BUS_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);
|
ret = fb_register_client(&gl_ts->fb_notif);
|
||||||
if (ret)
|
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);
|
ret);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1162,9 +1394,11 @@ static int IT7260_ts_resume(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_may_wakeup(dev) && (gl_ts->device_needs_wakeup)) {
|
if (device_may_wakeup(dev)) {
|
||||||
|
if (gl_ts->device_needs_wakeup) {
|
||||||
gl_ts->device_needs_wakeup = false;
|
gl_ts->device_needs_wakeup = false;
|
||||||
disable_irq_wake(gl_ts->client->irq);
|
disable_irq_wake(gl_ts->client->irq);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,14 +1412,21 @@ static int IT7260_ts_resume(struct device *dev)
|
||||||
|
|
||||||
static int IT7260_ts_suspend(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) {
|
if (gl_ts->suspended) {
|
||||||
dev_info(dev, "Already in suspend state\n");
|
dev_info(dev, "Already in suspend state\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_may_wakeup(dev) && (!gl_ts->device_needs_wakeup)) {
|
if (device_may_wakeup(dev)) {
|
||||||
|
if (!gl_ts->device_needs_wakeup) {
|
||||||
gl_ts->device_needs_wakeup = true;
|
gl_ts->device_needs_wakeup = true;
|
||||||
enable_irq_wake(gl_ts->client->irq);
|
enable_irq_wake(gl_ts->client->irq);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue