diff options
author | Mohan Pallaka <mpallaka@codeaurora.org> | 2013-08-28 13:44:36 +0530 |
---|---|---|
committer | Abinaya P <abinayap@codeaurora.org> | 2016-08-17 16:59:15 +0530 |
commit | bf71f01cc715734d951d9841bb7fa7d229f2903c (patch) | |
tree | e9d7c4d785f89b3d74a3dae24550d5195eeaea96 | |
parent | 72436be454654749d7c64676543ae6e7a579b042 (diff) |
input: ft5x06_ts: Upgrade firmware based on version
Upgrade firmware on the controller only when a new
version of firmware is available.
This patch is propagated from msm-3.18 kernel
'commit 88d102ef081f ("input: ft5x06_ts: Upgrade
firmware based on version")'
Change-Id: I4cf75b3c5efb90f151da09ed73b1ba62b9b5bb1c
Signed-off-by: Mohan Pallaka <mpallaka@codeaurora.org>
-rw-r--r-- | Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/ft5x06_ts.c | 114 | ||||
-rw-r--r-- | include/linux/input/ft5x06_ts.h | 1 |
3 files changed, 90 insertions, 27 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt index b5e12a1951dd..735deb7b3cb5 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt @@ -45,6 +45,8 @@ Optional properties: - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade - focaltech,fw-auto-cal : specify whether calibration is needed after firmware upgrade + - focaltech,fw-vkey-support : specify if virtual keys are supported through firmware + Example: i2c@f9923000{ focaltech@38{ diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c index 794ba264abdf..5ed6473ea715 100644 --- a/drivers/input/touchscreen/ft5x06_ts.c +++ b/drivers/input/touchscreen/ft5x06_ts.c @@ -41,7 +41,7 @@ #define FT_SUSPEND_LEVEL 1 #endif -#define FT_DRIVER_VERSION 0x01 +#define FT_DRIVER_VERSION 0x02 #define FT_META_REGS 3 #define FT_ONE_TCH_LEN 6 @@ -69,6 +69,9 @@ #define FT_REG_THGROUP 0x80 #define FT_REG_ECC 0xCC #define FT_REG_RESET_FW 0x07 +#define FT_REG_FW_MAJ_VER 0xB1 +#define FT_REG_FW_MIN_VER 0xB2 +#define FT_REG_FW_SUB_MIN_VER 0xB3 /* power register bits */ #define FT_PMODE_ACTIVE 0x00 @@ -107,7 +110,12 @@ #define FT_FW_MIN_SIZE 8 #define FT_FW_MAX_SIZE 32768 -#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2]) + +/* Firmware file is not supporting minor and sub minor so use 0 */ +#define FT_FW_FILE_MAJ_VER(x) ((x)->data[(x)->size - 2]) +#define FT_FW_FILE_MIN_VER(x) 0 +#define FT_FW_FILE_SUB_MIN_VER(x) 0 + #define FT_FW_CHECK(x) \ (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \ && (((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \ @@ -134,7 +142,8 @@ #define FT_INFO_MAX_LEN 512 -#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_name, fw_ver) \ +#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \ + fw_name, fw_maj, fw_min, fw_sub_min) \ snprintf(buf, FT_INFO_MAX_LEN, \ "controller\t= focaltech\n" \ "model\t\t= 0x%x\n" \ @@ -142,10 +151,12 @@ "max_touches\t= %d\n" \ "drv_ver\t\t= 0x%x\n" \ "group_id\t= 0x%x\n" \ + "fw_vkey_support\t= %s\n" \ "fw_name\t\t= %s\n" \ - "fw_ver\t\t= 0x%x\n", id, name, \ + "fw_ver\t\t= %d.%d.%d\n", id, name, \ max_tch, FT_DRIVER_VERSION, group_id, \ - fw_name, fw_ver) + fw_vkey_support, fw_name, fw_maj, fw_min, \ + fw_sub_min) #define FT_DEBUG_DIR_NAME "ts_debug" @@ -164,6 +175,7 @@ struct ft5x06_ts_data { char *ts_info; u8 *tch_data; u32 tch_data_len; + u8 fw_ver[3]; #if defined(CONFIG_FB) struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) @@ -246,6 +258,31 @@ static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val) return ft5x06_i2c_read(client, &addr, 1, val, 1); } +static void ft5x06_update_fw_ver(struct ft5x06_ts_data *data) +{ + struct i2c_client *client = data->client; + u8 reg_addr; + int err; + + reg_addr = FT_REG_FW_MAJ_VER; + err = ft5x06_i2c_read(client, ®_addr, 1, &data->fw_ver[0], 1); + if (err < 0) + dev_err(&client->dev, "fw major version read failed"); + + reg_addr = FT_REG_FW_MIN_VER; + err = ft5x06_i2c_read(client, ®_addr, 1, &data->fw_ver[1], 1); + if (err < 0) + dev_err(&client->dev, "fw minor version read failed"); + + reg_addr = FT_REG_FW_SUB_MIN_VER; + err = ft5x06_i2c_read(client, ®_addr, 1, &data->fw_ver[2], 1); + if (err < 0) + dev_err(&client->dev, "fw sub minor version read failed"); + + dev_info(&client->dev, "Firmware version = %d.%d.%d\n", + data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); +} + static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id) { struct ft5x06_ts_data *data = dev_id; @@ -297,8 +334,10 @@ static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id) input_report_abs(ip_dev, ABS_MT_POSITION_X, x); input_report_abs(ip_dev, ABS_MT_POSITION_Y, y); input_report_abs(ip_dev, ABS_MT_PRESSURE, pressure); - } else + } else { input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0); + input_report_abs(ip_dev, ABS_MT_PRESSURE, 0); + } } if (update_input) { @@ -746,7 +785,8 @@ static int ft5x06_fw_upgrade(struct device *dev, bool force) struct ft5x06_ts_data *data = dev_get_drvdata(dev); const struct firmware *fw = NULL; int rc; - u8 val = 0; + u8 fw_file_maj, fw_file_min, fw_file_sub_min; + bool fw_upgrade = false; rc = request_firmware(&fw, data->fw_name, dev); if (rc < 0) { @@ -761,27 +801,38 @@ static int ft5x06_fw_upgrade(struct device *dev, bool force) goto rel_fw; } - /* check firmware version */ - rc = ft5x0x_read_reg(data->client, FT_REG_FW_VER, &val); - if (rc < 0) { - dev_err(dev, "Get firmware version failed\n"); - goto rel_fw; - } + fw_file_maj = FT_FW_FILE_MAJ_VER(fw); + fw_file_min = FT_FW_FILE_MIN_VER(fw); + fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw); + + dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj, + fw_file_min, fw_file_sub_min); + + if (force) { + fw_upgrade = true; + } else if (data->fw_ver[0] == fw_file_maj) { + if (data->fw_ver[1] < fw_file_min) + fw_upgrade = true; + else if (data->fw_ver[2] < fw_file_sub_min) + fw_upgrade = true; + else + dev_info(dev, "No need to upgrade\n"); + } else + dev_info(dev, "Firmware versions do not match\n"); - if (val == FT_FW_FILE_VER(fw) && !force) { - dev_err(dev, "No need to update (0x%x)\n", val); + if (!fw_upgrade) { + dev_info(dev, "Exiting fw upgrade...\n"); rc = -EFAULT; goto rel_fw; } - dev_info(dev, "upgrade to fw ver 0x%x from 0x%x\n", - FT_FW_FILE_VER(fw), val); - /* start firmware upgrade */ if (FT_FW_CHECK(fw)) { rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size); if (rc < 0) - dev_err(dev, "update failed (%d)\n", rc); + dev_err(dev, "update failed (%d). try later...\n", rc); else if (data->pdata->info.auto_cal) ft5x06_auto_cal(data->client); } else { @@ -789,9 +840,13 @@ static int ft5x06_fw_upgrade(struct device *dev, bool force) rc = -EIO; } + ft5x06_update_fw_ver(data); + FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, data->pdata->num_max_touches, data->pdata->group_id, - data->pdata->fw_name, FT_FW_FILE_VER(fw)); + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); rel_fw: release_firmware(fw); return rc; @@ -820,6 +875,11 @@ static ssize_t ft5x06_update_fw_store(struct device *dev, if (rc != 0) return rc; + if (data->suspended) { + dev_info(dev, "In suspend state, try again later...\n"); + return size; + } + mutex_lock(&data->input_dev->mutex); if (!data->loading_fw && val) { data->loading_fw = true; @@ -1186,6 +1246,9 @@ static int ft5x06_parse_dt(struct device *dev, pdata->info.auto_cal = of_property_read_bool(np, "focaltech,fw-auto-cal"); + pdata->fw_vkey_support = of_property_read_bool(np, + "focaltech,fw-vkey-support"); + rc = of_property_read_u32(np, "focaltech,family-id", &temp_val); if (!rc) pdata->family_id = temp_val; @@ -1472,16 +1535,13 @@ static int ft5x06_ts_probe(struct i2c_client *client, dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4); - reg_addr = FT_REG_FW_VER; - err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1); - if (err < 0) - dev_err(&client->dev, "version read failed"); - - dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value); + ft5x06_update_fw_ver(data); FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, data->pdata->num_max_touches, data->pdata->group_id, - data->pdata->fw_name, reg_value); + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); #if defined(CONFIG_FB) data->fb_notif.notifier_call = fb_notifier_callback; diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h index 89e3143eda77..202ddeec09d6 100644 --- a/include/linux/input/ft5x06_ts.h +++ b/include/linux/input/ft5x06_ts.h @@ -55,6 +55,7 @@ struct ft5x06_ts_platform_data { u32 hard_rst_dly; u32 soft_rst_dly; u32 num_max_touches; + bool fw_vkey_support; bool no_force_update; bool i2c_pull_up; int (*power_init)(bool); |