Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12018ac3 authored by Duson Lin's avatar Duson Lin Committed by Dmitry Torokhov
Browse files

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: default avatarDuson Lin <dusonlin@emc.com.tw>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 85919a00
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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;
}