From 12018ac3d679d6a3c6c738ac805797fe4dd43912 Mon Sep 17 00:00:00 2001 From: Duson Lin Date: Mon, 8 Jun 2015 16:39:35 -0700 Subject: [PATCH] Input: elan_i2c - add support for multi IC type and iap format In order to support multiple IC types for i2c/smbus protocol, add get ic type command and use this data when checking firmware page count and signature address. Signed-off-by: Duson Lin Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 5 ++-- drivers/input/mouse/elan_i2c_core.c | 45 ++++++++++++++++++++++++---- drivers/input/mouse/elan_i2c_i2c.c | 4 ++- drivers/input/mouse/elan_i2c_smbus.c | 6 ++-- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index 6d5f8a4c1748..ff622a1b0c2c 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -33,9 +33,7 @@ #define ETP_FW_IAP_PAGE_ERR (1 << 5) #define ETP_FW_IAP_INTF_ERR (1 << 4) #define ETP_FW_PAGE_SIZE 64 -#define ETP_FW_VAILDPAGE_COUNT 768 #define ETP_FW_SIGNATURE_SIZE 6 -#define ETP_FW_SIGNATURE_ADDRESS 0xBFFA struct i2c_client; struct completion; @@ -58,7 +56,8 @@ struct elan_transport_ops { bool max_baseliune, u8 *value); int (*get_version)(struct i2c_client *client, bool iap, u8 *version); - int (*get_sm_version)(struct i2c_client *client, u8 *version); + int (*get_sm_version)(struct i2c_client *client, + u8* ic_type, u8 *version); int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); int (*get_product_id)(struct i2c_client *client, u8 *id); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index fd5068b2542d..b4cfd18cdaca 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -4,7 +4,7 @@ * Copyright (c) 2013 ELAN Microelectronics Corp. * * Author: 林政維 (Duson Lin) - * Version: 1.5.7 + * Version: 1.5.8 * * Based on cyapa driver: * copyright (c) 2011-2012 Cypress Semiconductor, Inc. @@ -40,7 +40,7 @@ #include "elan_i2c.h" #define DRIVER_NAME "elan_i2c" -#define ELAN_DRIVER_VERSION "1.5.7" +#define ELAN_DRIVER_VERSION "1.5.8" #define ETP_MAX_PRESSURE 255 #define ETP_FWIDTH_REDUCE 90 #define ETP_FINGER_WIDTH 15 @@ -83,6 +83,9 @@ struct elan_tp_data { u16 fw_checksum; int pressure_adjustment; u8 mode; + u8 ic_type; + u16 fw_vaildpage_count; + u16 fw_signature_address; bool irq_wake; @@ -91,6 +94,29 @@ struct elan_tp_data { bool baseline_ready; }; +static int elan_get_fwinfo(u8 ic_type, u16 *vaildpage_count, + u16 *signature_address) +{ + switch(ic_type) { + case 0x09: + *vaildpage_count = 768; + break; + case 0x0D: + *vaildpage_count = 896; + break; + default: + /* unknown ic type clear value */ + *vaildpage_count = 0; + *signature_address = 0; + return -ENXIO; + } + + *signature_address = + (*vaildpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; + + return 0; +} + static int elan_enable_power(struct elan_tp_data *data) { int repeat = ETP_RETRY_COUNT; @@ -221,7 +247,8 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = data->ops->get_sm_version(data->client, &data->sm_version); + error = data->ops->get_sm_version(data->client, &data->ic_type, + &data->sm_version); if (error) return error; @@ -234,6 +261,14 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; + error = elan_get_fwinfo(data->ic_type, &data->fw_vaildpage_count, + &data->fw_signature_address); + if (error) { + dev_err(&data->client->dev, + "unknown ic type %d\n", data->ic_type); + return error; + } + return 0; } @@ -318,7 +353,7 @@ static int __elan_update_firmware(struct elan_tp_data *data, iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]); boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE; - for (i = boot_page_count; i < ETP_FW_VAILDPAGE_COUNT; i++) { + for (i = boot_page_count; i < data->fw_vaildpage_count; i++) { u16 checksum = 0; const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE]; @@ -454,7 +489,7 @@ static ssize_t elan_sysfs_update_fw(struct device *dev, } /* Firmware file must match signature data */ - fw_signature = &fw->data[ETP_FW_SIGNATURE_ADDRESS]; + fw_signature = &fw->data[data->fw_signature_address]; if (memcmp(fw_signature, signature, sizeof(signature)) != 0) { dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n", (int)sizeof(signature), signature, diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index a0acbbf83bfd..683c840c9dd7 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -259,7 +259,8 @@ static int elan_i2c_get_version(struct i2c_client *client, return 0; } -static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version) +static int elan_i2c_get_sm_version(struct i2c_client *client, + u8 *ic_type, u8 *version) { int error; u8 val[3]; @@ -271,6 +272,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version) } *version = val[0]; + *ic_type = val[1]; return 0; } diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index 30ab80dbcdd6..ff36a366b2aa 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -165,7 +165,8 @@ static int elan_smbus_get_version(struct i2c_client *client, return 0; } -static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version) +static int elan_smbus_get_sm_version(struct i2c_client *client, + u8 *ic_type, u8 *version) { int error; u8 val[3]; @@ -177,7 +178,8 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version) return error; } - *version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */ + *version = val[0]; + *ic_type = val[1]; return 0; } -- 2.20.1