Эх сурвалжийг харах

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 <dusonlin@emc.com.tw>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Duson Lin 10 жил өмнө
parent
commit
12018ac3d6

+ 2 - 3
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);
 

+ 40 - 5
drivers/input/mouse/elan_i2c_core.c

@@ -4,7 +4,7 @@
  * Copyright (c) 2013 ELAN Microelectronics Corp.
  *
  * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
- * 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,

+ 3 - 1
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;
 }
 

+ 4 - 2
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;
 }