[PATCH] Input - elan_i2c: support multi ic type and iap format

From: duson
Date: Sat Jun 06 2015 - 15:40:19 EST


In order to support multi ic type for i2c/smbus protocol, add get ic type
command and check fw vaild page count and signature address function.

Signed-off by: Duson Lin <dusonlin@xxxxxxxxxx>
---
drivers/input/mouse/elan_i2c.h | 5 ++--
drivers/input/mouse/elan_i2c_core.c | 44 ++++++++++++++++++++++++++++++----
drivers/input/mouse/elan_i2c_i2c.c | 5 +++-
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 6d5f8a4..ff622a1 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 fd5068b..81e7bc9 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) <dusonlin@xxxxxxxxxx>
- * 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,28 @@ 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 +246,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 +260,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 +352,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 +488,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 a0acbbf..549cdfb 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,9 +272,11 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version)
}

*version = val[0];
+ *ic_type = val[1];
return 0;
}

+
static int elan_i2c_get_product_id(struct i2c_client *client, u8 *id)
{
int error;
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index 30ab80d..c28caef 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;
}--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/