These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / input / mouse / elan_i2c_core.c
index fd5068b..2f58985 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 2013 ELAN Microelectronics Corp.
  *
  * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
- * Version: 1.5.7
+ * Version: 1.6.0
  *
  * Based on cyapa driver:
  * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
@@ -40,7 +40,8 @@
 #include "elan_i2c.h"
 
 #define DRIVER_NAME            "elan_i2c"
-#define ELAN_DRIVER_VERSION    "1.5.7"
+#define ELAN_DRIVER_VERSION    "1.6.1"
+#define ELAN_VENDOR_ID         0x04f3
 #define ETP_MAX_PRESSURE       255
 #define ETP_FWIDTH_REDUCE      90
 #define ETP_FINGER_WIDTH       15
@@ -76,13 +77,16 @@ struct elan_tp_data {
        unsigned int            x_res;
        unsigned int            y_res;
 
-       u                     product_id;
+       u16                     product_id;
        u8                      fw_version;
        u8                      sm_version;
        u8                      iap_version;
        u16                     fw_checksum;
        int                     pressure_adjustment;
        u8                      mode;
+       u8                      ic_type;
+       u16                     fw_validpage_count;
+       u16                     fw_signature_address;
 
        bool                    irq_wake;
 
@@ -91,6 +95,42 @@ struct elan_tp_data {
        bool                    baseline_ready;
 };
 
+static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count,
+                          u16 *signature_address)
+{
+       switch (iap_version) {
+       case 0x00:
+       case 0x06:
+       case 0x08:
+               *validpage_count = 512;
+               break;
+       case 0x03:
+       case 0x07:
+       case 0x09:
+       case 0x0A:
+       case 0x0B:
+       case 0x0C:
+               *validpage_count = 768;
+               break;
+       case 0x0D:
+               *validpage_count = 896;
+               break;
+       case 0x0E:
+               *validpage_count = 640;
+               break;
+       default:
+               /* unknown ic type clear value */
+               *validpage_count = 0;
+               *signature_address = 0;
+               return -ENXIO;
+       }
+
+       *signature_address =
+               (*validpage_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 +261,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 +275,13 @@ static int elan_query_device_info(struct elan_tp_data *data)
        if (error)
                return error;
 
+       error = elan_get_fwinfo(data->iap_version, &data->fw_validpage_count,
+                               &data->fw_signature_address);
+       if (error)
+               dev_warn(&data->client->dev,
+                        "unexpected iap version %#04x (ic type: %#04x), firmware update will not work\n",
+                        data->iap_version, data->ic_type);
+
        return 0;
 }
 
@@ -318,7 +366,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_validpage_count; i++) {
                u16 checksum = 0;
                const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE];
 
@@ -403,7 +451,8 @@ static ssize_t elan_sysfs_read_product_id(struct device *dev,
        struct i2c_client *client = to_i2c_client(dev);
        struct elan_tp_data *data = i2c_get_clientdata(client);
 
-       return sprintf(buf, "%d.0\n", data->product_id);
+       return sprintf(buf, ETP_PRODUCT_ID_FORMAT_STRING "\n",
+                      data->product_id);
 }
 
 static ssize_t elan_sysfs_read_fw_ver(struct device *dev,
@@ -442,19 +491,31 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
 {
        struct elan_tp_data *data = dev_get_drvdata(dev);
        const struct firmware *fw;
+       char *fw_name;
        int error;
        const u8 *fw_signature;
        static const u8 signature[] = {0xAA, 0x55, 0xCC, 0x33, 0xFF, 0xFF};
 
-       error = request_firmware(&fw, ETP_FW_NAME, dev);
+       if (data->fw_validpage_count == 0)
+               return -EINVAL;
+
+       /* Look for a firmware with the product id appended. */
+       fw_name = kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id);
+       if (!fw_name) {
+               dev_err(dev, "failed to allocate memory for firmware name\n");
+               return -ENOMEM;
+       }
+
+       dev_info(dev, "requesting fw '%s'\n", fw_name);
+       error = request_firmware(&fw, fw_name, dev);
+       kfree(fw_name);
        if (error) {
-               dev_err(dev, "cannot load firmware %s: %d\n",
-                       ETP_FW_NAME, error);
+               dev_err(dev, "failed to request firmware: %d\n", error);
                return error;
        }
 
        /* 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,
@@ -726,7 +787,7 @@ static const struct attribute_group *elan_sysfs_groups[] = {
  */
 static void elan_report_contact(struct elan_tp_data *data,
                                int contact_num, bool contact_valid,
-                               bool hover_event, u8 *finger_data)
+                               u8 *finger_data)
 {
        struct input_dev *input = data->input;
        unsigned int pos_x, pos_y;
@@ -770,9 +831,7 @@ static void elan_report_contact(struct elan_tp_data *data,
                input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
                input_report_abs(input, ABS_MT_POSITION_X, pos_x);
                input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y);
-               input_report_abs(input, ABS_MT_DISTANCE, hover_event);
-               input_report_abs(input, ABS_MT_PRESSURE,
-                                hover_event ? 0 : scaled_pressure);
+               input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure);
                input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
                input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
                input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
@@ -794,14 +853,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
        hover_event = hover_info & 0x40;
        for (i = 0; i < ETP_MAX_FINGERS; i++) {
                contact_valid = tp_info & (1U << (3 + i));
-               elan_report_contact(data, i, contact_valid, hover_event,
-                                   finger_data);
+               elan_report_contact(data, i, contact_valid, finger_data);
 
                if (contact_valid)
                        finger_data += ETP_FINGER_DATA_LEN;
        }
 
        input_report_key(input, BTN_LEFT, tp_info & 0x01);
+       input_report_abs(input, ABS_DISTANCE, hover_event != 0);
        input_mt_report_pointer_emulation(input, true);
        input_sync(input);
 }
@@ -856,6 +915,8 @@ static int elan_setup_input_device(struct elan_tp_data *data)
 
        input->name = "Elan Touchpad";
        input->id.bustype = BUS_I2C;
+       input->id.vendor = ELAN_VENDOR_ID;
+       input->id.product = data->product_id;
        input_set_drvdata(input, data);
 
        error = input_mt_init_slots(input, ETP_MAX_FINGERS,
@@ -877,6 +938,7 @@ static int elan_setup_input_device(struct elan_tp_data *data)
        input_abs_set_res(input, ABS_Y, data->y_res);
        input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0);
        input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0);
+       input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0);
 
        /* And MT parameters */
        input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0);
@@ -889,7 +951,6 @@ static int elan_setup_input_device(struct elan_tp_data *data)
                             ETP_FINGER_WIDTH * max_width, 0, 0);
        input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0,
                             ETP_FINGER_WIDTH * min_width, 0, 0);
-       input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0);
 
        data->input = input;
 
@@ -1122,6 +1183,9 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0000", 0 },
+       { "ELAN0100", 0 },
+       { "ELAN0600", 0 },
+       { "ELAN1000", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, elan_acpi_id);
@@ -1138,10 +1202,10 @@ MODULE_DEVICE_TABLE(of, elan_of_match);
 static struct i2c_driver elan_driver = {
        .driver = {
                .name   = DRIVER_NAME,
-               .owner  = THIS_MODULE,
                .pm     = &elan_pm_ops,
                .acpi_match_table = ACPI_PTR(elan_acpi_id),
                .of_match_table = of_match_ptr(elan_of_match),
+               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
        },
        .probe          = elan_probe,
        .id_table       = elan_id,