rmi4: new driver for synaptics touch controller s3202
authorHong Liu <hong.liu@intel.com>
Thu, 22 Dec 2011 19:48:19 +0000 (11:48 -0800)
committerbuildbot <buildbot@intel.com>
Thu, 12 Jan 2012 11:07:52 +0000 (03:07 -0800)
BZ: 19819

Added RMI4 framework and driver from Synaptics that supports s3202
touch controller on CloverTrail Phone platform.

Changes made to the original driver:
1. Fixed all checkpatch & compiling errors and warnings
2. add F1a function support for key reporting, s3202 doesn't have
   F19 for key reporting.

Change-Id: I1fb608a7d7d9668f1779af5f27332b42a5ecc3f9
Signed-off-by: Andriy Naborskyy <andriy.naborskyy@intel.com>
Signed-off-by: Leo Yan <leo.yan@intel.com>
Signed-off-by: Hong Liu <hong.liu@intel.com>
Reviewed-on: http://android.intel.com:8080/31120
Reviewed-by: Mai, Leonard <leonard.mai@intel.com>
Reviewed-by: Du, Alek <alek.du@intel.com>
Tested-by: Wang, Zhifeng <zhifeng.wang@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
33 files changed:
arch/x86/platform/mrst/mrst.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/rmi/Kconfig [new file with mode: 0644]
drivers/input/touchscreen/rmi/Makefile [new file with mode: 0644]
drivers/input/touchscreen/rmi/README [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_bus.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_bus.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_dev.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_dev.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_drvr.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f01.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f01.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f05.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f05.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f11.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f11.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f19.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f19.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f34.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f34.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f54.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_f54.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_function.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_function.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_i2c.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_sensor.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_sensor.h [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_spi.c [new file with mode: 0644]
drivers/input/touchscreen/rmi/rmi_spi.h [new file with mode: 0644]
include/linux/rmi_i2c.h [new file with mode: 0644]
include/linux/rmi_platformdata.h [new file with mode: 0644]

index 53eaaf9..2894c6c 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/atmel_mxt224.h>
+#include <linux/rmi_i2c.h>
 
 #include <linux/atomisp_platform.h>
 #include <media/v4l2-subdev.h>
@@ -1000,7 +1001,7 @@ void max17042_i2c_reset_workaround(void)
        gpio_set_value(I2C_1_GPIO_PIN, 0);
        udelay(10);
        lnw_gpio_set_alt(I2C_1_GPIO_PIN, LNW_ALT_1);
-#undef I2C_1_GPIO_PIN 27
+#undef I2C_1_GPIO_PIN
 }
 EXPORT_SYMBOL(max17042_i2c_reset_workaround);
 
@@ -1572,6 +1573,60 @@ void *atmel_mxt224_platform_data_init(void *info)
        return &mxt_pdata;
 }
 
+static struct rmi_f11_functiondata synaptics_f11_data = {
+       .swap_axes = true,
+};
+
+static unsigned char synaptic_keys[31] = {1, 2, 3, 4,};
+                       /* {KEY_BACK,KEY_MENU,KEY_HOME,KEY_SEARCH,} */
+
+static struct rmi_button_map synaptics_button_map = {
+       .nbuttons = 31,
+       .map = synaptic_keys,
+};
+static struct rmi_f19_functiondata  synaptics_f19_data = {
+       .button_map = &synaptics_button_map,
+};
+
+#define RMI_F11_INDEX 0x11
+#define RMI_F19_INDEX 0x19
+
+static struct rmi_functiondata synaptics_functiondata[] = {
+       {
+               .function_index = RMI_F11_INDEX,
+               .data = &synaptics_f11_data,
+       },
+       {
+               .function_index = RMI_F19_INDEX,
+               .data = &synaptics_f19_data,
+       },
+};
+
+static struct rmi_functiondata_list synaptics_perfunctiondata = {
+       .count = ARRAY_SIZE(synaptics_functiondata),
+       .functiondata = synaptics_functiondata,
+};
+
+
+static struct rmi_sensordata s3202_sensordata = {
+       .perfunctiondata = &synaptics_perfunctiondata,
+};
+
+void *s3202_platform_data_init(void *info)
+{
+       struct i2c_board_info *i2c_info = info;
+       static struct rmi_i2c_platformdata s3202_platform_data = {
+               .delay_ms = 50,
+               .sensordata = &s3202_sensordata,
+       };
+
+       s3202_platform_data.i2c_address = i2c_info->addr;
+       s3202_sensordata.attn_gpio_number = get_gpio_by_name("ts_int");
+       s3202_sensordata.rst_gpio_number  = get_gpio_by_name("ts_rst");
+
+       return &s3202_platform_data;
+}
+
 static const struct devs_id __initconst device_ids[] = {
        {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
        {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data},
@@ -1605,7 +1660,7 @@ static const struct devs_id __initconst device_ids[] = {
        {"mt9e013", SFI_DEV_TYPE_I2C, 0, &mt9e013_platform_data_init},
        {"mt9m114", SFI_DEV_TYPE_I2C, 0, &mt9m114_platform_data_init},
        {"mxt224", SFI_DEV_TYPE_I2C, 0, &atmel_mxt224_platform_data_init},
-
+       {"synaptics_3202", SFI_DEV_TYPE_I2C, 0, &s3202_platform_data_init},
        {},
 };
 
index 23ef376..98cff54 100644 (file)
@@ -759,5 +759,7 @@ config TOUCHSCREEN_ATMEL_MXT224
        help
                Say Y here if you have a mXT224 touchscreen
                If unsure, say N.
+
+source "drivers/input/touchscreen/rmi/Kconfig"
           
 endif
index 3933daa..980576b 100644 (file)
@@ -63,4 +63,6 @@ obj-$(CONFIG_TOUCHSCREEN_W90X900)     += w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)     += tps6507x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE)  += cyttsp_core.o
 obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C)   += cyttsp_i2c.o
-obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT224) += atmel_mxt224.o
\ No newline at end of file
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT224) += atmel_mxt224.o
+
+obj-y += rmi/
diff --git a/drivers/input/touchscreen/rmi/Kconfig b/drivers/input/touchscreen/rmi/Kconfig
new file mode 100644 (file)
index 0000000..326389e
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Touchscreen driver configuration
+#
+
+config TOUCHSCREEN_SYNAPTICS_RMI4_I2C
+    tristate "Synaptics RMI4 I2C touchscreens"
+    depends on I2C
+    default n
+    help
+        Say Y here if you have a Synaptics RMI4 I2C touchscreen connected to
+        your system. This enables support for Synaptics RMI4 over I2C based
+        touchscreens.
+        If unsure, say N.
+        To compile this driver as a set of modules, choose M here: the
+        modules will be called rmi_core, rmi_app_touchpad, rmi_phys_i2c.
+
+config SYNA_MULTI_TOUCH
+       bool "add multi touch support to RMI4 driver"
+       default y
+       depends on TOUCHSCREEN_SYNAPTICS_RMI4_I2C
+       help
+        This option enables multi-touch capabilities in the input device.
+        Driver will report ABS_MT_* event sequence required by kernel
+        multi-touch protocol.
+
+        If only need single-touch capability, say N.
+
+
+config SYNA_RMI_DEV
+       bool "rmi_dev"
+       depends on TOUCHSCREEN_SYNAPTICS_RMI4_I2C
+       help
+        Enable mutli-touch capabilities in the input device
diff --git a/drivers/input/touchscreen/rmi/Makefile b/drivers/input/touchscreen/rmi/Makefile
new file mode 100644 (file)
index 0000000..221c9ee
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+#ccflags-y += -DDEBUG
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C)   +=  rmi_bus.o rmi_sensor.o rmi_function.o rmi_f01.o rmi_f05.o rmi_f11.o rmi_f19.o rmi_f34.o rmi_f54.o rmi_i2c.o
diff --git a/drivers/input/touchscreen/rmi/README b/drivers/input/touchscreen/rmi/README
new file mode 100644 (file)
index 0000000..b31ef6a
--- /dev/null
@@ -0,0 +1,6 @@
+This is the Synaptics S3200 Touch Controller driver for Intel Clovertrail platform.
+Here are two tips to use the driver:
+1. Since touch screen is on different i2c bus for EV and VV platform, please change
+the I2C_BUS_NUM macro in rmi_i2c.c accordingly when using this driver on these two
+platforms.
+2. Set the COMM_DEBUG macro in rmi_i2c.c to dump more debug information.
diff --git a/drivers/input/touchscreen/rmi/rmi.h b/drivers/input/touchscreen/rmi/rmi.h
new file mode 100644 (file)
index 0000000..7357819
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_H)
+#define _RMI_H
+
+/*  RMI4 Protocol Support
+ */
+
+
+/* Every function on an RMI device is identified by a one byte function number.
+ * The hexadecimal representation of this byte is used in the function name.
+ * For example, the function identified by the byte 0x11 is referred to as
+ * F11 (or sometimes FN11).  In the extremely improbable event that F11 is no
+ * longer identified by 0x11, though, we provide these handy #defines.
+ */
+#define RMI_F01_INDEX 0x01
+#define RMI_F05_INDEX 0x05
+#define RMI_F11_INDEX 0x11
+#define RMI_F19_INDEX 0x19
+#define RMI_F34_INDEX 0x34
+#define RMI_F54_INDEX 0x54
+
+/* This byte has information about the communications protocol.  See the RMI4
+ * specification for details of what exactly is there.
+ */
+#define RMI_PROTOCOL_VERSION_ADDRESS 0xA0FD
+
+/* For each function present on the RMI device, we need to get the RMI4 Function
+ * Descriptor info from the Page Descriptor Table. This will give us the
+ * addresses for Query, Command, Control, Data and the Source Count (number
+ * of sources for this function) and the function id.
+ */
+struct rmi_function_descriptor {
+       unsigned char query_base_addr;
+       unsigned char command_base_addr;
+       unsigned char control_base_addr;
+       unsigned char data_base_addr;
+       unsigned char interrupt_source_count;
+       unsigned char function_number;
+};
+
+/* The product descriptor table starts here, and continues till we get
+ * a function ID of 0x00 or 0xFF.
+ */
+#define RMI_PDT_START_ADDRESS 0x00E9
+
+#define RMI_IS_VALID_FUNCTION_ID(id) (id != 0x00 && id != 0xFF)
+
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_bus.c b/drivers/input/touchscreen/rmi/rmi_bus.c
new file mode 100644 (file)
index 0000000..d74a0c7
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Synaptics Register Mapped Interface (RMI4) - RMI Bus Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ * Implements "rmi" bus per Documentation/driver-model/bus.txt
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+static const char busname[] = "rmi";
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+#include "rmi_drvr.h"
+#include "rmi.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+
+#define PDT_START_SCAN_LOCATION 0x00E9
+#define PDT_END_SCAN_LOCATION 0x0005
+#define PDT_ENTRY_SIZE 0x0006
+
+/* definitions for rmi bus */
+struct device rmi_bus_device;
+
+struct bus_type rmi_bus_type;
+EXPORT_SYMBOL(rmi_bus_type);
+
+/*
+ * This method is called, perhaps multiple times, whenever a new device or
+ * driver is added for this bus. It should return a nonzero value if the given
+ * device can be handled by the given driver. This function must be handled at
+ * the bus level, because that is where the proper logic exists; the core
+ * kernel cannot know how to match devices and drivers for every possible bus
+ * type The match function does a comparison between the hardware ID provided
+ * by the device itself and the IDs supported by the driver.
+ *
+ */
+static int rmi_bus_match(struct device *dev, struct device_driver *driver)
+{
+       dev_dbg(dev, "%s: Matching driver %s against bus %s for rmi bus.\n",
+                __func__, driver->name, dev->bus->name);
+       return !strcmp(dev->bus->name, driver->name);
+}
+
+/* Stub for now.
+ */
+static int rmi_bus_suspend(struct device *dev, pm_message_t state)
+{
+       dev_dbg(dev, "%s: RMI bus suspending.", __func__);
+       return 0;
+}
+
+/* Stub for now.
+ */
+static int rmi_bus_resume(struct device *dev)
+{
+       dev_dbg(dev, "%s: RMI bus resuming.", __func__);
+       return 0;
+}
+
+/*
+ * This method is called, whenever a new device is added for this bus.
+ * It will scan the devices PDT to get the function $01 query, control,
+ * command and data regsiters so that it can create a function $01 (sensor)
+ * device for the new physical device. It also caches the PDT for later use by
+ * other functions that are created for the device. For example, if a function
+ * $11 is found it will need the query, control, command and data register
+ * addresses for that function. The new function could re-scan the PDT but
+ * since it is being done here we can cache it and keep it around.
+ *
+ * TODO: If the device is reset or some action takes place that would invalidate
+ * the PDT - such as a reflash of the firmware - then the device should be
+ * re-added to the bus and the PDT re-scanned and cached.
+ *
+ */
+int rmi_register_sensor(struct rmi_phys_driver *rpd,
+                       struct rmi_sensordata *sensordata)
+{
+       int i;
+       int pdt_entry_count = 0;
+       struct rmi_sensor_device *rmi_sensor_dev = NULL;
+       struct rmi_function_descriptor rmi_fd;
+       int retval;
+       static int index;
+
+       /* Make sure we have a read, write, read_multiple, write_multiple
+          function pointers from whatever physical layer the sensor is on.
+        */
+       if (!rpd->name) {
+               pr_err("%s: Physical driver must specify a name", __func__);
+               return -EINVAL;
+       }
+       if (!rpd->write) {
+               pr_err("%s: Physical driver %s must specify a writer.",
+                      __func__, rpd->name);
+               return -EINVAL;
+       }
+       if (!rpd->read) {
+               pr_err("%s: Physical driver %s must specify a reader.",
+                      __func__, rpd->name);
+               return -EINVAL;
+       }
+       if (!rpd->write_multiple) {
+               pr_err("%s: Physical driver %s must specify a "
+                      "multiple writer.", __func__, rpd->name);
+               return -EINVAL;
+       }
+       if (!rpd->read_multiple) {
+               pr_err("%s: Physical driver %s must specify a "
+                      "multiple reader.", __func__, rpd->name);
+               return -EINVAL;
+       }
+
+       /* Get some information from the device */
+       pr_debug("%s: Identifying sensors by presence of F01...", __func__);
+
+       /* Scan the page descriptor table until we find F01.  If we find that,
+        * we assume that we can reliably talk to this sensor.
+        */
+       for (i = PDT_START_SCAN_LOCATION;
+            i >= PDT_END_SCAN_LOCATION; i -= PDT_ENTRY_SIZE) {
+               retval = rpd->read_multiple(rpd, i, (char *)&rmi_fd,
+                                           sizeof(rmi_fd));
+               if (retval) {
+                       /* failed to read next PDT entry - end PDT
+                          scan - this may result in an incomplete set
+                          of recognized functions - should probably
+                          return an error but the driver may still be
+                          viable for diagnostics and debugging so let's
+                          let it continue. */
+                       pr_err
+                           ("%s: Read Error %d when reading next PDT entry - "
+                            "ending PDT scan.", __func__, retval);
+                       break;
+               }
+
+               if (rmi_fd.function_number == 0x00
+                   || rmi_fd.function_number == 0xff) {
+                       /* A zero or 0xff in the function number
+                          signals the end of the PDT */
+                       pr_debug("%s:   Found End of PDT.", __func__);
+                       break;
+               }
+               pdt_entry_count++;
+               if ((rmi_fd.function_number & 0xff) == 0x01) {
+                       pr_debug("%s: F01 Found - RMI Device Control",
+                                __func__);
+
+                       /* This appears to be a valid device, so create a sensor
+                        * device and sensor driver for it. */
+                       rmi_sensor_dev =
+                           kzalloc(sizeof(*rmi_sensor_dev), GFP_KERNEL);
+                       if (!rmi_sensor_dev) {
+                               pr_err
+                                   ("%s: Error allocating memory for "
+                                    "rmi_sensor_device",
+                                    __func__);
+                               retval = -ENOMEM;
+                               goto exit_fail;
+                       }
+                       rmi_sensor_dev->dev.bus = &rmi_bus_type;
+                       dev_set_drvdata(&rmi_sensor_dev->dev, rmi_sensor_dev);
+
+                       retval =
+                           rmi_sensor_register_device(rmi_sensor_dev, index++);
+                       if (retval < 0) {
+                               pr_err
+                                   ("%s: Error %d registering sensor device.",
+                                    __func__, retval);
+                               goto exit_fail;
+                       }
+
+                       rmi_sensor_dev->driver =
+                           rmi_sensor_create_driver(rmi_sensor_dev, rpd,
+                                                    sensordata);
+                       if (!rmi_sensor_dev->driver) {
+                               pr_err("%s: Failed to create sensor driver.",
+                                      __func__);
+                               goto exit_fail;
+                       }
+
+                       retval =
+                           rmi_sensor_register_driver(rmi_sensor_dev->driver);
+                       if (retval < 0) {
+                               pr_err
+                                   ("%s: Error %d registering sensor driver.",
+                                    __func__, retval);
+                               goto exit_fail;
+                       }
+
+                       /* link the attn fn in the rpd to the sensor attn fn */
+                       rpd->sensor = rmi_sensor_dev->driver;
+                       rpd->set_attn_handler(rpd,
+                                       rmi_sensor_dev->driver->attention);
+
+                       /* All done with this sensor, fall out of scan loop. */
+                       break;
+               } else {
+                       /* Just print out the function found for now */
+                       pr_debug("%s: Found Function %02x - Ignored.\n",
+                                __func__, rmi_fd.function_number & 0xff);
+               }
+       }
+
+       /* If we actually found a sensor, keep it around. */
+       if (rmi_sensor_dev) {
+               pr_debug("%s: Registered sensor drivers.", __func__);
+               retval = 0;
+       } else {
+               pr_err("%s: Failed to find sensor. PDT contained %d entries.",
+                      __func__, pdt_entry_count);
+               retval = -ENODEV;
+               goto exit_fail;
+       }
+
+       return 0;
+
+exit_fail:
+       if (rmi_sensor_dev)
+               rmi_sensor_destroy_driver(rmi_sensor_dev->driver);
+       kfree(rmi_sensor_dev);
+       return retval;
+}
+EXPORT_SYMBOL(rmi_register_sensor);
+
+int rmi_unregister_sensors(struct rmi_phys_driver *rpd)
+{
+       if (rpd->sensor) {
+               pr_warning
+                   ("%s: WARNING: unregister of %s while %s still attached.",
+                    __func__, rpd->name, rpd->sensor->drv.name);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(rmi_unregister_sensors);
+
+static void rmi_bus_dev_release(struct device *dev)
+{
+       pr_debug("rmi bus device release\n");
+}
+
+int rmi_register_bus_device(struct device *rmibusdev)
+{
+       pr_debug("%s: Registering RMI4 bus device.\n", __func__);
+
+       /* Here, we simply fill in some of the embedded device structure
+        * fields (which individual drivers should not need to know about),
+        * and register the device with the driver core. */
+
+       rmibusdev->bus = &rmi_bus_type;
+       rmibusdev->parent = &rmi_bus_device;
+       rmibusdev->release = rmi_bus_dev_release;
+       dev_set_name(rmibusdev, "rmi");
+
+       /* If we wanted to add bus-specific attributes to the device,
+        * we could do so here. */
+
+       return device_register(rmibusdev);
+}
+EXPORT_SYMBOL(rmi_register_bus_device);
+
+void rmi_unregister_bus_device(struct device *rmibusdev)
+{
+       dev_dbg(rmibusdev, "%s: Unregistering bus device.", __func__);
+
+       device_unregister(rmibusdev);
+}
+EXPORT_SYMBOL(rmi_unregister_bus_device);
+
+static int __init rmi_bus_init(void)
+{
+       int status = 0;
+
+       pr_info("%s: RMI Bus Driver Init", __func__);
+
+       /* Register the rmi bus */
+       rmi_bus_type.name = busname;
+       rmi_bus_type.match = rmi_bus_match;
+       rmi_bus_type.suspend = rmi_bus_suspend;
+       rmi_bus_type.resume = rmi_bus_resume;
+       status = bus_register(&rmi_bus_type);
+       if (status < 0) {
+               pr_err("%s: Error %d registering the rmi bus.", __func__,
+                      status);
+               goto err_exit;
+       }
+       pr_debug("%s: successfully registered bus.", __func__);
+
+       return 0;
+err_exit:
+       return status;
+}
+
+static void __exit rmi_bus_exit(void)
+{
+       pr_debug("%s: RMI Bus Driver Exit.", __func__);
+
+       rmi_unregister_bus_device(&rmi_bus_device);
+       bus_unregister(&rmi_bus_type);
+}
+
+/* Utility routine to handle writes to read-only attributes.  Hopefully
+ * this will never happen, but if the user does something stupid, we don't
+ * want to accept it quietly (which is what can happen if you just put NULL
+ * for the attribute's store function).
+ */
+ssize_t rmi_store_error(struct device *dev,
+                       struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       dev_warn(dev,
+               "RMI4 WARNING: Attempt to write %d characters to read-only "
+               "attribute %s.", count, attr->attr.name);
+       return -EPERM;
+}
+
+/* Utility routine to handle reads of write-only attributes.  Hopefully
+ * this will never happen, but if the user does something stupid, we don't
+ * want to accept it quietly (which is what can happen if you just put NULL
+ * for the attribute's show function).
+ */
+ssize_t rmi_show_error(struct device *dev,
+                      struct device_attribute *attr,
+                      char *buf)
+{
+       dev_warn(dev,
+                "RMI4 WARNING: Attempt to read from write-only attribute %s.",
+                attr->attr.name);
+       return -EPERM;
+}
+
+/* Register a sensor driver on the bus.
+ */
+int rmi_bus_register_sensor_driver(struct rmi_sensor_driver *sensor_driver)
+{
+       int retval = 0;
+
+       sensor_driver->drv.bus = &rmi_bus_type;
+       retval = driver_register(&sensor_driver->drv);
+       return retval;
+}
+EXPORT_SYMBOL(rmi_bus_register_sensor_driver);
+
+/* Remove a sensor driver from the bus.
+ */
+void rmi_bus_unregister_sensor_driver(struct rmi_sensor_driver *sensor_driver)
+{
+       driver_unregister(&sensor_driver->drv);
+}
+EXPORT_SYMBOL(rmi_bus_unregister_sensor_driver);
+
+module_init(rmi_bus_init);
+module_exit(rmi_bus_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi/rmi_bus.h b/drivers/input/touchscreen/rmi/rmi_bus.h
new file mode 100644 (file)
index 0000000..780a2f5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *
+ * Synaptics Register Mapped Interface (RMI4) - RMI Bus Module Header.
+ * Copyright (C) 2007 - 2010, Synaptics Incorporated
+ *
+ */
+/*
+ *
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_BUS_H)
+#define _RMI_BUS_H
+
+#include "rmi_sensor.h"
+
+int rmi_bus_register_sensor_driver(struct rmi_sensor_driver *sensor_driver);
+void rmi_bus_unregister_sensor_driver(struct rmi_sensor_driver *sensor_driver);
+
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_dev.c b/drivers/input/touchscreen/rmi/rmi_dev.c
new file mode 100644 (file)
index 0000000..47a4f86
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Synaptics Register Mapped Interface (RMI4) - RMI device Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/syscalls.h>
+
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_function.h"
+#include "rmi_sensor.h"
+#include "rmi_dev.h"
+
+#if defined(CONFIG_SYNA_RMI_DEV)
+
+#define CHAR_DEVICE_NAME "rmi"
+#define CHAR_DEVICE_NAME_SZ 3
+
+#define REG_ADDR_LIMIT 0xFFFF
+
+/*store dynamically allocated major number of char device*/
+static int rmi_char_dev_major_num;
+
+
+/* file operations for RMI char device */
+
+/*
+ * rmi_char_dev_llseek: - use to setup register address
+ *
+ * @filp: file structure for seek
+ * @off: offset
+ *       if whence == SEEK_SET,
+ *       high 16 bits: page address
+ *       low 16 bits: register address
+ *
+ *       if whence == SEEK_CUR,
+ *       offset from current position
+ *
+ *       if whence == SEEK_END,
+ *       offset from END(0xFFFF)
+ *
+ * @whence: SEEK_SET , SEEK_CUR or SEEK_END
+ */
+static loff_t rmi_char_dev_llseek(struct file *filp, loff_t off, int whence)
+{
+       loff_t newpos;
+       struct rmi_char_dev *my_char_dev = filp->private_data;
+
+       if (IS_ERR(my_char_dev)) {
+               pr_debug("%s: pointer of char device is invalid", __func__);
+               return -EBADF;
+       }
+
+       mutex_lock(&(my_char_dev->mutex_file_op));
+
+       switch (whence) {
+       case SEEK_SET:
+               newpos = off;
+               break;
+
+       case SEEK_CUR:
+               newpos = filp->f_pos + off;
+               break;
+
+       case SEEK_END:
+               newpos = REG_ADDR_LIMIT + off;
+               break;
+
+       default:                /* can't happen */
+               newpos = -EINVAL;
+               goto clean_up;
+       }
+
+       if (newpos < 0 || newpos > REG_ADDR_LIMIT) {
+               pr_debug("%s: newpos 0x%04x is invalid.",
+                               __func__, (unsigned int)newpos);
+               newpos = -EINVAL;
+               goto clean_up;
+       }
+
+       filp->f_pos = newpos;
+
+clean_up:
+
+       mutex_unlock(&(my_char_dev->mutex_file_op));
+
+       return newpos;
+}
+
+/*
+ *  rmi_char_dev_read: - use to read data from RMI stream
+ *
+ *  @filp: file structure for read
+ *  @buf: user-level buffer pointer
+ *
+ *  @count: number of byte read
+ *  @f_pos: offset (starting register address)
+ *
+ *     @return number of bytes read into user buffer (buf) if succeeds
+ *          negative number if error occurs.
+ */
+static ssize_t rmi_char_dev_read(struct file *filp, char __user *buf,
+               size_t count, loff_t *f_pos)
+{
+       struct rmi_char_dev *my_char_dev = filp->private_data;
+       ssize_t ret_value  = 0;
+       unsigned char tmpbuf[count+1];
+       struct rmi_phys_driver *rpd;
+
+       /* limit offset to REG_ADDR_LIMIT-1 */
+       if (count > (REG_ADDR_LIMIT - *f_pos))
+               count = REG_ADDR_LIMIT - *f_pos;
+
+       if (count == 0)
+               return 0;
+
+       if (IS_ERR(my_char_dev)) {
+               pr_err("%s: pointer of char device is invalid", __func__);
+               ret_value = -EBADF;
+               return ret_value;
+       }
+
+       mutex_lock(&(my_char_dev->mutex_file_op));
+
+       rpd = my_char_dev->sensor->rpd;
+       /*
+        * just let it go through , because we do not know the register is FIFO
+        * register or not
+        */
+
+       /* return zero upon success */
+       ret_value = rpd->read_multiple(rpd, *f_pos, tmpbuf, count);
+       if (ret_value == 0) {
+               /* we prepare the amount of data requested */
+               ret_value = count;
+               *f_pos += count;
+       } else {
+               ret_value = -EIO;
+               goto clean_up;
+       }
+
+       if (copy_to_user(buf, tmpbuf, count))
+               ret_value = -EFAULT;
+
+clean_up:
+
+       mutex_unlock(&(my_char_dev->mutex_file_op));
+
+       return ret_value;
+}
+
+/*
+ * rmi_char_dev_write: - use to write data into RMI stream
+ *
+ * @filep : file structure for write
+ * @buf: user-level buffer pointer contains data to be written
+ * @count: number of byte be be written
+ * @f_pos: offset (starting register address)
+ *
+ * @return number of bytes written from user buffer (buf) if succeeds
+ *         negative number if error occurs.
+ */
+static ssize_t rmi_char_dev_write(struct file *filp, const char __user *buf,
+               size_t count, loff_t *f_pos)
+{
+       struct rmi_char_dev *my_char_dev = filp->private_data;
+       ssize_t ret_value  = 0;
+       unsigned char tmpbuf[count+1];
+       struct rmi_phys_driver *rpd;
+
+       /* limit offset to REG_ADDR_LIMIT-1 */
+       if (count > (REG_ADDR_LIMIT - *f_pos))
+               count = REG_ADDR_LIMIT - *f_pos;
+
+       if (count == 0)
+               return 0;
+
+       if (IS_ERR(my_char_dev)) {
+               pr_err("%s: pointer of char device is invalid", __func__);
+               ret_value = -EBADF;
+               return ret_value;
+       }
+
+       if (copy_from_user(tmpbuf, buf, count)) {
+               ret_value = -EFAULT;
+               return ret_value;
+       }
+
+       mutex_lock(&(my_char_dev->mutex_file_op));
+
+       rpd = my_char_dev->sensor->rpd;
+       /*
+        * just let it go through , because we do not know the register is FIFO
+        * register or not
+        */
+
+       /* return one upon success */
+
+       ret_value = rpd->write_multiple(rpd, *f_pos, tmpbuf, count);
+
+       if (ret_value == 1) {
+               /* we had written the amount of data requested */
+               ret_value = count;
+               *f_pos += count;
+       } else {
+               ret_value = -EIO;
+       }
+
+       mutex_unlock(&(my_char_dev->mutex_file_op));
+
+       return ret_value;
+}
+
+/*
+ * rmi_char_dev_open: - get a new handle for from RMI stream
+ * @inp : inode struture
+ * @filp: file structure for read/write
+ *
+ * @return 0 if succeeds
+ */
+static int rmi_char_dev_open(struct inode *inp, struct file *filp)
+{
+       /* store the device pointer to file structure */
+       struct rmi_char_dev *my_dev = container_of(inp->i_cdev,
+                       struct rmi_char_dev, main_dev);
+       struct rmi_sensor_driver *sensor = my_dev->sensor;
+       int ret_value = 0;
+
+       filp->private_data = my_dev;
+
+       if (!sensor)
+               return -EACCES;
+
+       mutex_lock(&(my_dev->mutex_file_op));
+       if (my_dev->ref_count < 1)
+               my_dev->ref_count++;
+       else
+               ret_value = -EACCES;
+
+       mutex_unlock(&(my_dev->mutex_file_op));
+
+       return ret_value; /*succeeds*/
+}
+
+/*
+ *  rmi_char_dev_release: - release an existing handle
+ *  @inp: inode structure
+ *  @filp: file structure for read/write
+ *
+ *  @return 0 if succeeds
+ */
+static int rmi_char_dev_release(struct inode *inp, struct file *filp)
+{
+       struct rmi_char_dev *my_dev = container_of(inp->i_cdev,
+                       struct rmi_char_dev, main_dev);
+       struct rmi_sensor_driver *sensor = my_dev->sensor;
+
+       if (!sensor)
+               return -EACCES;
+
+       mutex_lock(&(my_dev->mutex_file_op));
+
+       my_dev->ref_count--;
+       if (my_dev->ref_count < 0)
+               my_dev->ref_count = 0;
+
+       mutex_unlock(&(my_dev->mutex_file_op));
+
+       return 0; /*succeeds*/
+}
+
+static const struct file_operations rmi_char_dev_fops = {
+       .owner =    THIS_MODULE,
+       .llseek =   rmi_char_dev_llseek,
+       .read =     rmi_char_dev_read,
+       .write =    rmi_char_dev_write,
+       .open =     rmi_char_dev_open,
+       .release =  rmi_char_dev_release,
+};
+
+/*
+ * rmi_char_dev_clean_up - release memory or unregister driver
+ * @char_dev: char device structure
+ * @char_device_class: class of the device use to generate one under /dev
+ *
+ */
+static void rmi_char_dev_clean_up(struct rmi_char_dev *char_dev,
+               struct class *char_device_class)
+{
+       dev_t devno = char_dev->main_dev.dev;
+
+       /* Get rid of our char dev entries */
+       if (char_dev) {
+               cdev_del(&char_dev->main_dev);
+               kfree(char_dev);
+       }
+
+       if (char_device_class) {
+               device_destroy(char_device_class, devno);
+               class_unregister(char_device_class);
+               class_destroy(char_device_class);
+       }
+       /* cleanup_module is never called if registering failed */
+       unregister_chrdev_region(devno, 1);
+       pr_debug("%s: rmi_char_dev is removed\n", __func__);
+}
+
+/*
+ * rmi_char_devnode - return device permission
+ *
+ * @dev: char device structure
+ * @mode: file permission
+ *
+ */
+static char *rmi_char_devnode(struct device *dev, mode_t *mode)
+{
+       if (!mode)
+               return NULL;
+       /* rmi** */
+       /**mode = 0666*/
+       *mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+
+       return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev));
+}
+
+/*
+ * rmi_char_dev_register - register char device (called from up-level)
+ *
+ * @physical_driver: pointer to physical_driver of the lower-level stack
+ *                                     (I2C or SPI)
+ * @sensor_dev: sensor device containing this device
+ *
+ * @return: zero if suceeds
+ */
+int rmi_char_dev_register(struct rmi_phys_driver *physical_driver,
+               struct rmi_sensor_device *sensor_dev)
+{
+       struct rmi_char_dev *char_dev;
+       dev_t dev_no;
+       int err;
+       int result;
+       struct device *device_ptr;
+
+       if (rmi_char_dev_major_num) {
+               dev_no = MKDEV(rmi_char_dev_major_num, 0);
+               result = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
+       } else {
+               result = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
+               /* let kernel allocate a major for us */
+               rmi_char_dev_major_num = MAJOR(dev_no);
+               pr_debug("%s Major number of rmi_char_dev: %d\n", __func__,
+                               rmi_char_dev_major_num);
+
+       }
+       if (result < 0)
+               return result;
+
+       /* allocate memory for rmi_char_dev */
+       char_dev = kzalloc(sizeof(struct rmi_char_dev), GFP_KERNEL);
+       if (!char_dev) {
+               pr_err("%s: Error allocating memory. ", __func__);
+               /* unregister the char device region */
+               __unregister_chrdev(rmi_char_dev_major_num, MINOR(dev_no), 1,
+                               CHAR_DEVICE_NAME);
+               return -ENOMEM;
+       }
+       /* initialize mutex */
+       mutex_init(&char_dev->mutex_file_op);
+
+       /* assign device pointer to sensor_device */
+       sensor_dev->char_dev = char_dev;
+
+       /* register char device */
+
+       /* store driver pointer of rmi driver */
+       char_dev->sensor = sensor_dev->driver;
+
+       /* initialize char device */
+       cdev_init(&char_dev->main_dev, &rmi_char_dev_fops);
+
+       err = cdev_add(&char_dev->main_dev, dev_no, 1);
+       /* check if adding device fails */
+       if (err) {
+               pr_err("%s: Error %d adding rmi_char_dev", __func__, err);
+               rmi_char_dev_clean_up(sensor_dev->char_dev,
+                               sensor_dev->rmi_char_device_class);
+               return err;
+       }
+
+       /* create device node */
+       sensor_dev->rmi_char_device_class = class_create(THIS_MODULE,
+                       CHAR_DEVICE_NAME);
+
+       if (IS_ERR(sensor_dev->rmi_char_device_class)) {
+               pr_err("%s: create /dev/rmi failed", __func__);
+               rmi_char_dev_clean_up(sensor_dev->char_dev,
+                               sensor_dev->rmi_char_device_class);
+               return -ENODEV;
+       }
+       /* setup permission */
+       sensor_dev->rmi_char_device_class->devnode = rmi_char_devnode;
+       /* class creation */
+       device_ptr = device_create(
+                                       sensor_dev->rmi_char_device_class,
+                                       NULL, dev_no, NULL,
+                                       CHAR_DEVICE_NAME"%d",
+                                       MINOR(dev_no));
+
+       if (IS_ERR(device_ptr)) {
+               pr_err("%s: create rmi device", __func__);
+               rmi_char_dev_clean_up(sensor_dev->char_dev,
+                               sensor_dev->rmi_char_device_class);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(rmi_char_dev_register);
+
+/*
+ * rmi_char_dev_unregister - unregister char device (called from up-level)
+ *
+ * @physical_driver: pointer to physical_driver of the lower-level stack
+ *                                     (I2C or SPI)
+ * @sensor_dev: sensor device containing this device
+ *
+ */
+void rmi_char_dev_unregister(struct rmi_char_dev *char_dev,
+               struct class *char_device_class)
+{
+       /* clean up */
+       rmi_char_dev_clean_up(char_dev, char_device_class);
+}
+EXPORT_SYMBOL(rmi_char_dev_unregister);
+
+#endif /*CONFIG_SYNA_RMI_DEV*/
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Char Device");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi/rmi_dev.h b/drivers/input/touchscreen/rmi/rmi_dev.h
new file mode 100644 (file)
index 0000000..9a28034
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *
+ * Synaptics Register Mapped Interface (RMI4) - RMI device Module Header.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ *
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#if !defined(_RMI_DEV_H)
+#define _RMI_DEV_H
+
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+
+
+struct rmi_sensor_device;
+
+/*
+ *  rmi_char_dev: a char device to directly control RMI interface
+ */
+
+#define RMI_CHAR_DEV_TMPBUF_SZ 128
+#define RMI_REG_ADDR_PAGE_SELECT 0xFF
+
+struct rmi_char_dev {
+       /* mutex for file operation*/
+       struct mutex mutex_file_op;
+    /* main char dev structure */
+       struct cdev main_dev;
+
+       /* register address for RMI protocol */
+       /* filp->f_pos */
+
+       /* pointer to the corresponding phys driver info for this sensor */
+       /* The senor driver has the pointers to read, write, etc. */
+       struct rmi_sensor_driver *sensor;
+       /* reference count */
+       int ref_count;
+};
+
+int rmi_char_dev_register(struct rmi_phys_driver *physical_driver,
+               struct rmi_sensor_device *sensor_dev);
+void rmi_char_dev_unregister(struct rmi_char_dev *char_dev,
+               struct class *char_device_class);
+
+
+#endif /*_RMI_DEV_H*/
diff --git a/drivers/input/touchscreen/rmi/rmi_drvr.h b/drivers/input/touchscreen/rmi/rmi_drvr.h
new file mode 100644 (file)
index 0000000..20783c9
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) RMI Driver Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_DRVR_H)
+#define _RMI_DRVR_H
+
+#include <linux/rmi_platformdata.h>
+#include "rmi.h"
+
+/*  RMI4 Protocol Support
+ */
+
+struct rmi_phys_driver {
+       char *name;
+       int (*write) (struct rmi_phys_driver *physdrvr, unsigned short address,
+                     char data);
+       int (*read) (struct rmi_phys_driver *physdrvr, unsigned short address,
+                    char *buffer);
+       int (*write_multiple) (struct rmi_phys_driver *physdrvr,
+                              unsigned short address, char *buffer,
+                              int length);
+       int (*read_multiple) (struct rmi_phys_driver *physdrvr,
+                             unsigned short address, char *buffer, int length);
+       void (*attention) (struct rmi_phys_driver *physdrvr);
+       bool polling_required;
+       int irq;
+
+       void (*set_attn_handler) (
+               struct rmi_phys_driver *physdrvr,
+               void (*attention) (struct rmi_phys_driver *physdrvr));
+       int (*enable_device) (struct rmi_phys_driver *physdrvr);
+       void (*disable_device) (struct rmi_phys_driver *physdrvr);
+
+       /* Some quick data relating to the operation of the device. */
+       char *proto_name;
+       unsigned long tx_count;
+       unsigned long tx_bytes;
+       unsigned long tx_errors;
+       unsigned long rx_count;
+       unsigned long rx_bytes;
+       unsigned long rx_errors;
+       unsigned long attn_count;
+
+       struct list_head drivers;
+       struct rmi_sensor_driver *sensor;
+       struct module *module;
+};
+
+int rmi_read(struct rmi_sensor_driver *sensor, unsigned short address,
+            char *dest);
+int rmi_write(struct rmi_sensor_driver *sensor, unsigned short address,
+             unsigned char data);
+int rmi_read_multiple(struct rmi_sensor_driver *sensor, unsigned short address,
+                     char *dest, int length);
+int rmi_write_multiple(struct rmi_sensor_driver *sensor, unsigned short address,
+                      unsigned char *data, int length);
+int rmi_register_sensor(struct rmi_phys_driver *physdrvr,
+                       struct rmi_sensordata *sensordata);
+int rmi_unregister_sensors(struct rmi_phys_driver *physdrvr);
+
+/* Utility routine to set bits in a register. */
+int rmi_set_bits(struct rmi_sensor_driver *sensor, unsigned short address,
+                unsigned char bits);
+/* Utility routine to clear bits in a register. */
+int rmi_clear_bits(struct rmi_sensor_driver *sensor, unsigned short address,
+                  unsigned char bits);
+/* Utility routine to set the value of a bit field in a register. */
+int rmi_set_bit_field(struct rmi_sensor_driver *sensor, unsigned short address,
+                     unsigned char field_mask, unsigned char bits);
+
+/* Utility routine to handle writes to read-only attributes.  Hopefully
+ * this will never happen, but if the user does something stupid, we
+ * don't want to accept it quietly.
+ */
+ssize_t rmi_store_error(struct device *dev,
+                       struct device_attribute *attr,
+                       const char *buf, size_t count);
+
+/* Utility routine to handle reads to write-only attributes.  Hopefully
+ * this will never happen, but if the user does something stupid, we
+ * don't want to accept it quietly.
+ */
+ssize_t rmi_show_error(struct device *dev,
+                      struct device_attribute *attr,
+                      char *buf);
+
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_f01.c b/drivers/input/touchscreen/rmi/rmi_f01.c
new file mode 100644 (file)
index 0000000..56e9e73
--- /dev/null
@@ -0,0 +1,879 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $01 support for sensor
+ * control and configuration.
+ *
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/param.h>
+#include <linux/stat.h>
+#include <linux/rmi_platformdata.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f01.h"
+
+/* Query register field positions. */
+#define F01_MFG_ID_POS 0
+#define F01_PROPERTIES_POS 1
+#define F01_PRODUCT_INFO_POS 2
+#define F01_DATE_CODE_POS 4
+#define F01_TESTER_ID_POS 7
+#define F01_SERIAL_NUMBER_POS 9
+#define F01_PRODUCT_ID_POS 11
+#define F01_DATE_CODE_YEAR 0
+#define F01_DATE_CODE_MONTH 1
+#define F01_DATE_CODE_DAY 2
+
+/* Control register bits. */
+#define F01_CONFIGURED (1 << 7)
+#define NONSTANDARD_REPORT_RATE (1 << 6)
+
+/* Command register bits. */
+#define F01_RESET 1
+#define F01_SHUTDOWN (1 << 1)
+#define F01_INITREFLASH (1 << 7)
+
+/* Data register 0 bits. */
+#define F01_UNCONFIGURED (1 << 7)
+#define F01_FLASH_PROGRAMMING_MODE (1 << 6)
+#define F01_STATUS_MASK 0x0F
+
+/** Context data for each F01 we find.
+ */
+struct f01_instance_data {
+       struct rmi_F01_control *control_registers;
+       struct rmi_F01_data *data_registers;
+       struct rmi_F01_query *query_registers;
+
+       bool nonstandard_report_rate;
+       /* original mode before suspend */
+       unsigned char original_sleepmode;
+       /* original no sleep setting */
+       unsigned char original_nosleep;
+};
+static void set_sensor_sleepmode(struct rmi_function_info *functionInfo,
+                       unsigned char sleepmode, unsigned char nosleep);
+
+static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf);
+
+static ssize_t rmi_fn_01_productid_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf);
+
+static ssize_t rmi_fn_01_datecode_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf);
+
+static ssize_t rmi_fn_01_reportrate_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+
+static ssize_t rmi_fn_01_reportrate_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_reset_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_testerid_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf);
+
+static ssize_t rmi_fn_01_serialnumber_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf);
+
+static ssize_t rmi_fn_01_sleepmode_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_01_sleepmode_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+static ssize_t rmi_fn_01_nosleep_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_01_nosleep_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_initreflash_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_01_initreflash_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+static struct device_attribute attrs[] = {
+       __ATTR(productinfo, 0444,
+              rmi_fn_01_productinfo_show, rmi_store_error),    /* RO attr */
+       __ATTR(productid, 0444,
+              rmi_fn_01_productid_show, rmi_store_error),      /* RO attr */
+       __ATTR(manufacturer, 0444,
+              rmi_fn_01_manufacturer_show, rmi_store_error),   /* RO attr */
+       __ATTR(datecode, 0444,
+              rmi_fn_01_datecode_show, rmi_store_error),       /* RO attr */
+       __ATTR(reportrate, 0666,
+              rmi_fn_01_reportrate_show, rmi_fn_01_reportrate_store),  /* RW */
+       __ATTR(reset, 0222,
+              rmi_show_error, rmi_fn_01_reset_store),  /* WO attr */
+       __ATTR(testerid, 0444,
+              rmi_fn_01_testerid_show, rmi_store_error),       /* RO attr */
+       __ATTR(serialnumber, 0444,
+              rmi_fn_01_serialnumber_show, rmi_store_error),   /* RO attr */
+       __ATTR(sleepmode, (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH),
+              rmi_fn_01_sleepmode_show, rmi_fn_01_sleepmode_store),    /* RW */
+       __ATTR(nosleep, (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH),
+                       rmi_fn_01_nosleep_show, rmi_fn_01_nosleep_store), /*RW*/
+       __ATTR(initreflash, (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH),
+               rmi_fn_01_initreflash_show, rmi_fn_01_initreflash_store) /*RW*/
+};
+
+static int set_report_rate(struct rmi_function_info *function_info,
+                          bool nonstandard)
+{
+       if (nonstandard) {
+               return rmi_set_bits(function_info->sensor,
+                       function_info->function_descriptor.control_base_addr,
+                       NONSTANDARD_REPORT_RATE);
+       } else {
+               return rmi_clear_bits(function_info->sensor,
+                       function_info->function_descriptor.control_base_addr,
+                       NONSTANDARD_REPORT_RATE);
+       }
+}
+
+static void read_query_registers(struct rmi_function_info *rmifninfo)
+{
+       unsigned char query_buffer[21];
+       int retval;
+       struct f01_instance_data *instance_data = rmifninfo->fndata;
+       struct rmi_F01_query *query_registers = instance_data->query_registers;
+
+       /* Read the query info and unpack it. */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                         rmifninfo->function_descriptor.query_base_addr,
+                  query_buffer, ARRAY_SIZE(query_buffer));
+       if (retval) {
+               pr_err("%s : Could not read F01 query registers at "
+                       "0x%02x. Error %d.\n", __func__,
+                       rmifninfo->function_descriptor.query_base_addr,
+                       retval);
+               /* Presumably if the read fails, the buffer should be all
+                * zeros, so we're OK to continue. */
+       }
+       query_registers->mfgid = query_buffer[F01_MFG_ID_POS];
+       query_registers->properties = query_buffer[F01_PROPERTIES_POS];
+       query_registers->prod_info[0] =
+               query_buffer[F01_PRODUCT_INFO_POS] & 0x7F;
+       query_registers->prod_info[1] =
+               query_buffer[F01_PRODUCT_INFO_POS + 1] & 0x7F;
+       query_registers->date_code[F01_DATE_CODE_YEAR] =
+               query_buffer[F01_DATE_CODE_POS] & 0x1F;
+       query_registers->date_code[F01_DATE_CODE_MONTH] =
+               query_buffer[F01_DATE_CODE_POS + 1] & 0x0F;
+       query_registers->date_code[F01_DATE_CODE_DAY] =
+               query_buffer[F01_DATE_CODE_POS + 2] & 0x1F;
+       query_registers->tester_id =
+               (((unsigned short)query_buffer[F01_TESTER_ID_POS] & 0x7F) << 7)
+               | (query_buffer[F01_TESTER_ID_POS + 1] & 0x7F);
+       query_registers->serial_num =
+               (((unsigned short)query_buffer[F01_SERIAL_NUMBER_POS] & 0x7F)
+                       << 7)
+               | (query_buffer[F01_SERIAL_NUMBER_POS + 1] & 0x7F);
+       memcpy(query_registers->prod_id, &query_buffer[F01_PRODUCT_ID_POS],
+               F01_PRODUCT_ID_LENGTH);
+
+       pr_debug("%s: RMI4 Protocol Function $01 Query information\n",
+               __func__);
+       pr_debug("%s: Manufacturer ID: %d %s\n", __func__,
+               query_registers->mfgid,
+               query_registers->mfgid == 1 ? "(Synaptics)" : "");
+       pr_debug("%s: Product Properties: 0x%x\n", __func__,
+               query_registers->properties);
+       pr_debug("%s: Product Info: 0x%x 0x%x\n", __func__,
+               query_registers->prod_info[0], query_registers->prod_info[1]);
+       pr_debug("%s: Date Code: Year : %d Month: %d Day: %d\n", __func__,
+               query_registers->date_code[F01_DATE_CODE_YEAR],
+               query_registers->date_code[F01_DATE_CODE_MONTH],
+               query_registers->date_code[F01_DATE_CODE_DAY]);
+       pr_debug("%s: Tester ID: %d\n", __func__, query_registers->tester_id);
+       pr_debug("%s: Serial Number: 0x%x\n",
+               __func__, query_registers->serial_num);
+       pr_debug("%s: Product ID: %s\n", __func__, query_registers->prod_id);
+}
+
+
+void FN_01_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs)
+{
+       struct f01_instance_data *instance_data = rmifninfo->fndata;
+
+       pr_debug("%s: Read device status.", __func__);
+
+       if (rmi_read
+           (rmifninfo->sensor, rmifninfo->function_descriptor.data_base_addr,
+            &instance_data->data_registers->device_status)) {
+               pr_err("%s : Could not read F01 device status.\n", __func__);
+       }
+       pr_info("%s: read device status register.  Value 0x%02X.", __func__,
+               instance_data->data_registers->device_status);
+
+       if (instance_data->data_registers->device_status & F01_UNCONFIGURED) {
+               pr_info("%s: ++++ Device reset detected.", __func__);
+               /* TODO: Handle device reset appropriately.
+                */
+       }
+}
+EXPORT_SYMBOL(FN_01_inthandler);
+
+/*
+ * This reads in the function $01 source data.
+ *
+ */
+void FN_01_attention(struct rmi_function_info *rmifninfo)
+{
+       struct f01_instance_data *instance_data = rmifninfo->fndata;
+       int retval;
+
+       /* TODO: Compute size to read and number of IRQ registers to processors
+        * dynamically.  See comments in rmi.h. */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                           rmifninfo->function_descriptor.data_base_addr + 1,
+                           instance_data->data_registers->irqs, 1);
+       if (retval) {
+               pr_err("%s: Could not read interrupt status registers "
+                       "at 0x%02x; code=%d.", __func__,
+                       rmifninfo->function_descriptor.data_base_addr + 1,
+                       retval);
+               return;
+       }
+
+       if (instance_data->data_registers->irqs[0] &
+               instance_data->control_registers->interrupt_enable[0]) {
+               /* call down to the sensors irq dispatcher to dispatch
+                * all enabled IRQs */
+               rmifninfo->sensor->dispatchIRQs(rmifninfo->sensor,
+                                               instance_data->data_registers->
+                                               irqs[0]);
+       }
+
+}
+EXPORT_SYMBOL(FN_01_attention);
+
+int FN_01_config(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+       struct f01_instance_data *instance_data = rmifninfo->fndata;
+
+       pr_debug("%s: RMI4 function $01 config\n", __func__);
+
+       /* First thing to do is set the configuration bit.  We'll check this at
+        * the end to determine if the device has reset during the config
+        * process.
+        */
+       retval = rmi_set_bits(rmifninfo->sensor,
+                        rmifninfo->function_descriptor.control_base_addr,
+                        F01_CONFIGURED);
+       if (retval)
+               pr_warning("%s: failed to set configured bit, errno = %d.",
+                          __func__, retval);
+
+       /* At config time, the device is presumably in its default state, so we
+        * only need to write non-default configuration settings.
+        */
+       if (instance_data->nonstandard_report_rate) {
+               retval = set_report_rate(rmifninfo, true);
+               if (!retval)
+                       pr_warning
+                           ("%s: failed to configure report rate, errno = %d.",
+                            __func__, retval);
+       }
+
+       /* TODO: Check for reset! */
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_01_config);
+
+/* Initialize any function $01 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_01_init(struct rmi_function_device *function_device)
+{
+       int retval;
+       int attr_count = 0;
+       struct rmi_f01_functiondata *functiondata =
+           rmi_sensor_get_functiondata(function_device->sensor, RMI_F01_INDEX);
+       struct f01_instance_data *instance_data = function_device->rfi->fndata;
+
+       pr_debug("%s: RMI4 function $01 init\n", __func__);
+
+       if (functiondata)
+               instance_data->nonstandard_report_rate =
+                   functiondata->nonstandard_report_rate;
+
+       pr_debug("%s: Creating sysfs files.", __func__);
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&function_device->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       pr_err("%s: Failed to create sysfs file for %s.",
+                               __func__, attrs[attr_count].attr.name);
+                       retval = -ENODEV;
+                       goto error_exit;
+               }
+       }
+
+       return 0;
+
+error_exit:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&function_device->dev.kobj,
+                                 &attrs[attr_count].attr);
+       /* If you've allocated anything, free it here. */
+       return retval;
+}
+EXPORT_SYMBOL(FN_01_init);
+
+int FN_01_detect(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+       struct f01_instance_data *instance_data = NULL;
+       struct rmi_F01_control *control_registers = NULL;
+       struct rmi_F01_data *data_registers = NULL;
+       struct rmi_F01_query *query_registers = NULL;
+
+       pr_debug("%s: RMI4 function $01 detect\n", __func__);
+
+       /* Set up context data. */
+       if (rmifninfo->fndata) {
+               /* detect routine should only ever be called once
+                * per rmifninfo. */
+               pr_err("%s: WTF?!? F01 instance data is already present!",
+                      __func__);
+               return -EINVAL;
+       }
+       instance_data = kzalloc(sizeof(*instance_data), GFP_KERNEL);
+       if (!instance_data) {
+               pr_err("%s: Error allocating memory for F01 context data.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       rmifninfo->fndata = instance_data;
+
+       query_registers = kzalloc(sizeof(*query_registers), GFP_KERNEL);
+       if (!query_registers) {
+               pr_err("%s: Error allocating memory for F01 query registers.",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       instance_data->query_registers = query_registers;
+       read_query_registers(rmifninfo);
+
+       /* TODO: size of control registers needs to be computed dynamically.
+        * See comment in rmi.h. */
+       control_registers = kzalloc(sizeof(*control_registers), GFP_KERNEL);
+       if (!control_registers) {
+               pr_err
+                   ("%s: Error allocating memory for F01 control registers.\n",
+                    __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       instance_data->control_registers = control_registers;
+       retval =
+           rmi_read_multiple(rmifninfo->sensor,
+                             rmifninfo->function_descriptor.control_base_addr,
+                             (char *)instance_data->control_registers,
+                             sizeof(struct rmi_F01_control));
+       if (retval) {
+               pr_err
+                   ("%s: Could not read F01 control registers at 0x%02x. "
+                    "Error %d.\n", __func__,
+                    rmifninfo->function_descriptor.control_base_addr,
+                    retval);
+       }
+
+       /* TODO: size of data registers needs to be computed dynamically.
+        * See comment in rmi.h. */
+       data_registers = kzalloc(sizeof(*data_registers), GFP_KERNEL);
+       if (!data_registers) {
+               pr_err("%s: Error allocating memory for F01 data registers.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       instance_data->data_registers = data_registers;
+
+       /* initialize original_sleepmode */
+       instance_data->original_sleepmode = RMI_SLEEP_MODE_NORMAL;
+       /* initialize of original_nosleep */
+       instance_data->original_nosleep = RMI_NO_SLEEP_DISABLE;
+
+       return retval;
+
+error_exit:
+       kfree(instance_data);
+       kfree(query_registers);
+       kfree(control_registers);
+       kfree(data_registers);
+       rmifninfo->fndata = NULL;
+       return retval;
+}
+EXPORT_SYMBOL(FN_01_detect);
+
+/**
+ *  suspend handler for F01, this will be invoked in
+ *  suspend routine from sensor
+ */
+int FN_01_suspend(struct rmi_function_info *rmifninfo)
+{
+       struct f01_instance_data *instance = rmifninfo->fndata;
+       /*store original sleep mode */
+       instance->original_sleepmode =
+                       instance->control_registers->
+                       device_control & RMI_F01_SLEEP_MODE_MASK;
+       /*store original no sleep setting */
+       instance->original_nosleep =
+                       (instance->control_registers->
+                               device_control & RMI_F01_NO_SLEEP_MASK) >> 2;
+       /*sleep:1 normal:0 */
+       set_sensor_sleepmode(rmifninfo, RMI_SLEEP_MODE_SENSOR_SLEEP,
+                       RMI_NO_SLEEP_DISABLE);
+       return 0;
+}
+EXPORT_SYMBOL(FN_01_suspend);
+
+/*
+ *  resume handler for F01, this will be invoked in
+ *  resume routine from sensor
+ */
+void FN_01_resume(struct rmi_function_info *rmifninfo)
+{
+       struct f01_instance_data *instance = rmifninfo->fndata;
+       /*sleep:1 normal:0 */
+       set_sensor_sleepmode(rmifninfo, instance->original_sleepmode,
+                       instance->original_nosleep);
+}
+EXPORT_SYMBOL(FN_01_resume);
+
+
+static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers
+                       && instance_data->query_registers->prod_info)
+               return snprintf(buf, PAGE_SIZE, "0x%02X 0x%02X\n",
+                              instance_data->query_registers->prod_info[0],
+                              instance_data->query_registers->prod_info[1]);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static ssize_t rmi_fn_01_productid_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers
+                       && instance_data->query_registers->prod_id)
+               return snprintf(buf, PAGE_SIZE, "%s\n",
+                       instance_data->query_registers->prod_id);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers)
+               return snprintf(buf, PAGE_SIZE, "0x%02X\n",
+                       instance_data->query_registers->mfgid);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static ssize_t rmi_fn_01_datecode_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers
+           && instance_data->query_registers->date_code)
+               return snprintf(buf, PAGE_SIZE, "20%02u-%02u-%02u\n",
+                              instance_data->query_registers->date_code[0],
+                              instance_data->query_registers->date_code[1],
+                              instance_data->query_registers->date_code[2]);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static ssize_t rmi_fn_01_reportrate_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers
+                       && instance_data->query_registers->date_code)
+               return snprintf(buf, PAGE_SIZE, "%d\n",
+                       instance_data->nonstandard_report_rate);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static ssize_t rmi_fn_01_reportrate_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+       unsigned int new_rate;
+       int retval;
+
+       if (sscanf(buf, "%u", &new_rate) != 1)
+               return -EINVAL;
+       if (new_rate < 0 || new_rate > 1)
+               return -EINVAL;
+       instance_data->nonstandard_report_rate = new_rate;
+
+       retval = set_report_rate(fn->rfi, new_rate);
+       if (retval < 0) {
+               pr_err("%s: failed to set report rate bit, error = %d.",
+                      __func__, retval);
+               return retval;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_01_reset_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       unsigned int reset;
+       int retval;
+
+       if (sscanf(buf, "%u", &reset) != 1)
+               return -EINVAL;
+       if (reset < 0 || reset > 1)
+               return -EINVAL;
+
+       /* Per spec, 0 has no effect, so we skip it entirely. */
+       if (reset) {
+               retval = rmi_set_bits(fn->sensor,
+                               fn->rfi->function_descriptor.command_base_addr,
+                               F01_RESET);
+               if (retval < 0) {
+                       dev_err(dev, "%s: failed to issue reset command, "
+                               "error = %d.", __func__, retval);
+                       return retval;
+               }
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_01_serialnumber_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers)
+               return snprintf(buf, PAGE_SIZE, "%u\n",
+                              instance_data->query_registers->serial_num);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+static ssize_t rmi_fn_01_testerid_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+
+       if (instance_data && instance_data->query_registers)
+               return snprintf(buf, PAGE_SIZE, "%u\n",
+                              instance_data->query_registers->tester_id);
+
+       return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+/*
+ *  update content of device control into hardware and sync the status
+ *  @param control_base_address base address for F01 device control
+ *  @param mask mask of the field that will be changed
+ *  @param field_target_value target value for the field
+ */
+static int update_device_control(struct rmi_sensor_driver *sensor,
+                       struct rmi_F01_control *control_register,
+                       unsigned char control_base_address,
+                       unsigned char mask,
+                       unsigned char field_target_value)
+{
+
+       unsigned char control_target_value =
+                       control_register->device_control & (~mask);
+       field_target_value &= mask;
+       control_target_value |= field_target_value;
+       if (control_register->device_control != control_target_value) {
+               /* update device_control*/
+               control_register->device_control = control_target_value;
+               return rmi_set_bit_field(sensor, control_base_address,
+                                       mask, field_target_value);
+       }
+       return 0;
+}
+
+/*
+ *  shows the status bit provided by device_control
+ *  @param mask mask to retrieve the information ex. 0x3 for bit 0 and bit 1
+ *  @param offset the offset of the information ex. 0: bit 0 1: bit 1
+ */
+static ssize_t device_control_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf,
+                               unsigned char mask,
+                               unsigned char offset)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+       unsigned char controlRegister = 0;
+
+       if (!instance_data || !instance_data->control_registers)
+               return snprintf(buf, PAGE_SIZE, "unknown\n");
+
+       controlRegister =
+               (instance_data->control_registers->device_control & mask)
+                       >> offset;
+       return snprintf(buf, PAGE_SIZE, "%u\n", controlRegister);
+}
+
+/*
+ *  store the value into device_control
+ *  @param mask mask to retrieve the information ex. 0x3 for bit 1 and bit 1
+ *  @param offset the offset of the information ex. 0: bit 0 1: bit 1
+ */
+static ssize_t device_control_store(struct device *dev,
+                               struct device_attribute *attr,
+                               unsigned int new_value,
+                               unsigned char mask,
+                               unsigned char offset)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+       unsigned char target_setting;
+       int retval;
+
+       target_setting = (unsigned char) new_value;
+       if (!instance_data || !instance_data->control_registers)
+               return -EINVAL;
+
+       /*update hardware and device_control status*/
+       retval = update_device_control(fn->sensor,
+                       instance_data->control_registers,
+                       fn->rfi->function_descriptor.control_base_addr,
+                       mask, (target_setting<<offset));
+
+       if (retval < 0)
+               dev_err(dev, "%s: failed to write control register, "
+                       "error = %d.", __func__, retval);
+
+       return retval;
+}
+
+/*
+ * show status for sleep 0:normal 1:sleep 2,3: reserved
+ */
+static ssize_t rmi_fn_01_sleepmode_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       return device_control_show(dev, attr, buf,
+                       RMI_F01_SLEEP_MODE_MASK, RMI_F01_SLEEP_MODE_OFFSET);
+}
+
+/*
+ * setup status for sleep mode 0:normal 1:sleep 2,3: reserved
+ */
+static ssize_t rmi_fn_01_sleepmode_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t count)
+{
+       unsigned long new_value;
+       int retval;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || !RMI_IS_VALID_SLEEPMODE(new_value)) {
+               dev_err(dev, "%s: Invalid sleep mode %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       retval = device_control_store(dev, attr, (unsigned int) new_value,
+                       RMI_F01_SLEEP_MODE_MASK, RMI_F01_SLEEP_MODE_OFFSET);
+       if (!retval)
+               retval = count;
+       return retval;
+}
+
+/*
+ * show current setting of no sleep, 0:disable 1:enable
+ */
+static ssize_t rmi_fn_01_nosleep_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       return device_control_show(dev, attr, buf,
+                       RMI_F01_NO_SLEEP_MASK, RMI_F01_NO_SLEEP_OFFSET);
+}
+
+/*
+ * setup no sleep, 0:disable 1:enable
+ */
+static ssize_t rmi_fn_01_nosleep_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       unsigned long new_value;
+       int retval;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid no sleep setting %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       retval = (device_control_store(dev, attr, (int) new_value,
+                       RMI_F01_NO_SLEEP_MASK, RMI_F01_NO_SLEEP_OFFSET));
+       if (!retval)
+               retval = count;
+       return retval;
+}
+
+static ssize_t rmi_fn_01_initreflash_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f01_instance_data *instance_data = fn->rfi->fndata;
+       unsigned char initreflash = 0;
+
+       if (!instance_data || !instance_data->query_registers)
+               return snprintf(buf, PAGE_SIZE, "unknown\n");
+
+       initreflash = (instance_data->query_registers->properties &
+               RMI_F01_INIT_REFLASH_MASK) >> RMI_F01_INIT_REFLASH_OFFSET;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", initreflash);
+}
+
+static ssize_t rmi_fn_01_initreflash_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       unsigned int initreflash;
+       int retval;
+
+       if (sscanf(buf, "%u", &initreflash) != 1)
+               return -EINVAL;
+       if (initreflash < 0 || initreflash > 1)
+               return -EINVAL;
+
+       /* Per spec, 0 has no effect, so we skip it entirely. */
+       if (initreflash) {
+               retval = rmi_set_bits(fn->sensor,
+                               fn->rfi->function_descriptor.command_base_addr,
+                               F01_INITREFLASH);
+               if (retval < 0) {
+                       dev_err(dev, "%s: failed to issue initreflash command, "
+                               "error = %d.", __func__, retval);
+                       return retval;
+               }
+       }
+
+       return count;
+}
+
+/* setup sleep mode via F01. we will store original_mode before sleepmode
+ * and nosleep setting is changed.
+ */
+static void set_sensor_sleepmode(struct rmi_function_info *functionInfo,
+                       unsigned char sleepmode,
+                       unsigned char nosleep)
+{
+       struct f01_instance_data *instance_data =
+                       functionInfo->function_device->rfi->fndata;
+
+       if (instance_data && instance_data->control_registers) {
+               /*update hardware and device_control status*/
+               update_device_control(functionInfo->sensor,
+                       instance_data->control_registers,
+                       functionInfo->function_descriptor.control_base_addr,
+                       (RMI_F01_SLEEP_MODE_MASK | RMI_F01_NO_SLEEP_MASK),
+                       (sleepmode | (nosleep << 2))
+               );
+       }
+}
diff --git a/drivers/input/touchscreen/rmi/rmi_f01.h b/drivers/input/touchscreen/rmi/rmi_f01.h
new file mode 100644 (file)
index 0000000..8db462a
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $01 header.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ * There is only one function $01 for each RMI4 sensor. This will be
+ * the function that is used to set sensor control and configurations
+ * and check the interrupts to find the source function that is interrupting.
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_F01_H)
+#define _RMI_F01_H
+
+/*  This encapsulates the information found using the RMI4 Function $01
+ *  query registers. There is only one Function $01 per device.
+ *
+ *  Assuming appropriate endian-ness, you can populate most of this
+ *  structure by reading query registers starting at the query base address
+ *  that was obtained from RMI4 function 0x01 function descriptor info read
+ *  from the Page Descriptor Table.
+ *
+ *  Specific register information is provided in the comments for each field.
+ *  For further reference, please see the "Synaptics RMI 4 Interfacing
+ *  Guide" document : go to http://www.synaptics.com/developers/manuals - and
+ *  select "Synaptics RMI 4 Interfacting Guide".
+ */
+#define F01_PRODUCT_INFO_LENGTH 2
+#define F01_DATE_CODE_LENGTH 3
+#define F01_PRODUCT_ID_LENGTH 10
+struct rmi_F01_query {
+       /* The manufacturer identification byte. */
+       unsigned char mfgid;
+
+       /* The Product Properties information. */
+       unsigned char properties;
+
+       /* The product info bytes. */
+       unsigned char prod_info[F01_PRODUCT_INFO_LENGTH];
+
+       /* Date Code - Year, Month, Day. */
+       unsigned char date_code[F01_DATE_CODE_LENGTH];
+
+       /* Tester ID (14 bits). */
+       unsigned short tester_id;
+
+       /* Serial Number (14 bits). */
+       unsigned short serial_num;
+
+       /* A null-terminated string that identifies this particular product. */
+       char prod_id[F01_PRODUCT_ID_LENGTH];
+};
+
+/* This encapsulates the F01 Device Control control registers.
+ * TODO: This isn't right.  The number of interrupt enables needs to be
+ * determined dynamically as the sensor is initialized.  Fix this.
+ */
+struct rmi_F01_control {
+       unsigned char device_control;
+       unsigned char interrupt_enable[1];
+};
+
+
+/* This encapsulates the F01 Device Control data registers.
+ * TODO: This isn't right.  The number of irqs needs to be determined
+ * dynamically as the sensor is initialized.  Fix this.
+ */
+struct rmi_F01_data {
+       unsigned char device_status;
+       unsigned char irqs[1];
+};
+
+
+void FN_01_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs);
+int FN_01_config(struct rmi_function_info *rmifninfo);
+int FN_01_init(struct rmi_function_device *function_device);
+int FN_01_detect(struct rmi_function_info *rmifninfo);
+void FN_01_attention(struct rmi_function_info *rmifninfo);
+int FN_01_suspend(struct rmi_function_info *rmifninfo);
+void FN_01_resume(struct rmi_function_info *rmifninfo);
+
+#define RMI_F01_SLEEP_MODE_MASK 0x03
+/* Position of bits in control register. */
+#define RMI_F01_SLEEP_MODE_OFFSET 0
+
+#define RMI_SLEEP_MODE_NORMAL (0x00)
+#define RMI_SLEEP_MODE_SENSOR_SLEEP (0x01)
+#define RMI_SLEEP_MODE_RESERVED0 (0x02)
+#define RMI_SLEEP_MODE_RESERVED1 (0x03)
+
+#define RMI_IS_VALID_SLEEPMODE(mode) \
+       (mode < RMI_SLEEP_MODE_NORMAL || mode > RMI_SLEEP_MODE_RESERVED1)
+
+/* This bit is used to disable current sleep mode. */
+#define RMI_F01_NO_SLEEP_MASK 0x04
+/* Position of bits in control register. */
+#define RMI_F01_NO_SLEEP_OFFSET 2
+
+#define RMI_NO_SLEEP_ENABLE (0x01)
+#define RMI_NO_SLEEP_DISABLE (0x00)
+
+#define RMI_F01_INIT_REFLASH_MASK 0x04
+/* Position of bits in query 1 register (product properties). */
+#define RMI_F01_INIT_REFLASH_OFFSET 2
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_f05.c b/drivers/input/touchscreen/rmi/rmi_f05.c
new file mode 100644 (file)
index 0000000..8f2808a
--- /dev/null
@@ -0,0 +1,127 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/rmi_platformdata.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f05.h"
+
+struct f05_instance_data {
+       int dummy;              /* TODO: Write this */
+};
+
+/*
+ * There is no attention function for F05 - it is left NULL
+ * in the function table so it is not called.
+ *
+ */
+
+/*
+ * This reads in a sample and reports the F05 source data to the
+ * input subsystem. It is used for both polling and interrupt driven
+ * operation. This is called a lot so don't put in any informational
+ * printks since they will slow things way down!
+ *
+ * This is a stub for now, and will be fleshed out when the implementation
+ * is completed.
+ */
+void FN_05_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs)
+{
+}
+EXPORT_SYMBOL(FN_05_inthandler);
+
+/* This is a stub for now, and will be fleshed out when the implementation
+ * is completed.
+ */
+int FN_05_config(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+
+       pr_debug("%s: RMI4 F05 config\n", __func__);
+
+       /* TODO: Perform configuration.  In particular, write any cached control
+        * register values to the device. */
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_05_config);
+
+/* This is a stub for now, and will be fleshed out when the implementation
+ * is completed.
+ */
+int FN_05_init(struct rmi_function_device *function_device)
+{
+       int retval = 0;
+/*
+       struct f05_instance_data *instance_data = function_device->rfi->fndata;
+       struct rmi_f05_functiondata *functiondata =
+           rmi_sensor_get_functiondata(function_device->sensor, RMI_F05_INDEX);
+*/
+
+       pr_debug("%s: RMI4 F05 init\n", __func__);
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_05_init);
+
+
+/*
+ * This is stubbed for now, will be filled out in the future.
+ */
+int FN_05_detect(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+       struct f05_instance_data *instance_data;
+
+       pr_debug("%s: RMI4 F05 detect\n", __func__);
+
+       if (rmifninfo->fndata) {
+               /* detect routine should only ever be called once
+                * per rmifninfo. */
+               pr_err("%s: WTF?!? F05 instance data is already present!",
+                      __func__);
+               return -EINVAL;
+       }
+       instance_data = kzalloc(sizeof(struct f05_instance_data), GFP_KERNEL);
+       if (!instance_data) {
+               pr_err("%s: Error allocating F05 instance data.\n", __func__);
+               return -ENOMEM;
+       }
+       rmifninfo->fndata = instance_data;
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_05_detect);
diff --git a/drivers/input/touchscreen/rmi/rmi_f05.h b/drivers/input/touchscreen/rmi/rmi_f05.h
new file mode 100644 (file)
index 0000000..10e4df4
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 header.
+ * Copyright (c) 2007 - 2010, Synaptics Incorporated
+ *
+ * For every RMI4 function that has a data source - like 2D sensors,
+ * buttons, LEDs, GPIOs, etc. - the user will create a new rmi_function_xx.c
+ * file and add these functions to perform the config(), init(), report()
+ * and detect() functionality. The function pointers are then srored under
+ * the RMI function info and these functions will automatically be called by
+ * the global config(), init(), report() and detect() functions that will
+ * loop through all data sources and call the data sources functions using
+ * these functions pointed to by the function ptrs.
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_F05_H)
+#define _RMI_F05_H
+
+void FN_05_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs);
+int FN_05_config(struct rmi_function_info *rmifninfo);
+int FN_05_init(struct rmi_function_device *function_device);
+int FN_05_detect(struct rmi_function_info *rmifninfo);
+/* No attention function for F05 */
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_f11.c b/drivers/input/touchscreen/rmi/rmi_f11.c
new file mode 100644 (file)
index 0000000..5bdee0b
--- /dev/null
@@ -0,0 +1,1256 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/rmi_platformdata.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f11.h"
+
+
+/*
+ * This will dump a ton of stuff to the console.  Don't turn it on.
+ */
+#define POS_DEBUG              0
+
+/* By default, we'll support two fingers if we can't figure out how many we
+ * really need to handle.
+ */
+#define DEFAULT_NR_OF_FINGERS 2
+
+/*
+ * Bitmasks and offsets for various things.  All of these are fixed in the
+ * spec, and most are used exactly once in the code below.
+ */
+/* Per device queries. */
+#define HAS_QUERY_9_MASK       0x08
+#define HAS_QUERY_11_MASK      0x10
+#define NR_SENSORS_MASK                0x07
+
+#define DEVICE_QUERY_SIZE      1
+
+
+/* Per sensor queries. */
+#define CONFIGURABLE_OFFSET    0
+#define CONFIGURABLE_MASK      0x80
+#define HAS_SENSITIVITY_ADJUST_OFFSET 0
+#define HAS_SENSITIVITY_ADJUST_MASK 0x40
+#define HAS_GESTURES_OFFSET    0
+#define HAS_GESTURES_MASK      0x20
+#define HAS_ABS_OFFSET         0
+#define HAS_ABS_MASK           0x10
+#define HAS_REL_OFFSET         0
+#define HAS_REL_MASK           0x08
+#define NR_FINGERS_OFFSET      0
+#define NR_FINGERS_MASK                0x07
+#define NR_X_ELECTRODES_OFFSET 1
+#define NR_Y_ELECTRODES_OFFSET 2
+#define MAX_ELECTRODES_OFFSET  3
+#define NR_ELECTRODES_MASK     0x7F
+#define ABS_DATA_SIZE_OFFSET   4
+#define ABS_DATA_SIZE_MASK     0x03
+#define HAS_ANCHORED_FINGER_OFFSET 4
+#define HAS_ANCHORED_FINGER_MASK 0x04
+#define HAS_ADJ_HYST_OFFSET    4
+#define HAS_ADJ_HYST_MASK      0x08
+#define HAS_DRIBBLE_OFFSET     4
+#define HAS_DRIBBLE_MASK       0x10
+
+#define HAS_SINGLE_TAP_MASK    0x01
+#define HAS_TAP_AND_HOLD_MASK  0x02
+#define HAS_DOUBLE_TAP_MASK    0x04
+#define HAS_EARLY_TAP_MASK     0x08
+#define HAS_FLICK_MASK         0x10
+#define HAS_PRESS_MASK         0x20
+#define HAS_PINCH_MASK         0x40
+#define ROTATE_FLICK_DATA_BYTES        2
+
+#define HAS_PALM_DETECT_MASK   0x01
+#define HAS_ROTATE_MASK                0x02
+#define HAS_TOUCH_SHAPES_MASK  0x04
+#define TOUCH_SHAPE_BITS_PER_BYTE      8
+#define HAS_SCROLL_ZONES_MASK  0x08
+#define HAS_INDIVIDUAL_SCROLL_ZONES_MASK       0x10
+#define SCROLL_ZONE_DATA_BYTES 2
+#define HAS_MULTIFINGER_SCROLL_MASK            0x20
+#define HAS_MULTIFINGER_SCROLL_EDGE_MOTION_MASK        0x40
+#define HAS_MULTIFINGER_SCROLL_INERTIA_MASK    0x80
+
+#define HAS_PEN_MASK           0x01
+#define HAS_PROXIMITY_MASK     0x02
+#define HAS_PALM_DETECT_SENSITIVITY_MASK       0x04
+#define HAS_SUPPRESS_ON_PALM_DETECT_MASK       0x08
+
+#define NUMBER_OF_TOUCH_SHAPES_MASK    0x1F
+
+#define HAS_Z_TUNING_MASK              0x01
+#define HAS_ALGORITHM_SECTION_MASK     0x02
+
+/* Data registers. */
+#define X_HIGH_BITS_OFFSET             0
+#define Y_HIGH_BITS_OFFSET             1
+#define XY_LOW_BITS_OFFSET             2
+#define XY_HIGH_BITS_SHIFT             4
+#define XY_HIGH_BITS_MASK              0x0FF0
+#define XY_LOW_BITS_MASK               0x0F
+#define X_LOW_BITS_SHIFT               0
+#define Y_LOW_BITS_SHIFT               4
+#define W_XY_OFFSET                    3
+#define W_X_SHIFT                      0
+#define W_Y_SHIFT                      4
+#define W_XY_MASK                      0x0F
+#define Z_OFFSET                       4
+#define REL_X_OFFSET                   0
+#define REL_Y_OFFSET                   1
+
+
+/* The per-sensor query registers will never be larger than this. */
+#define MAX_PER_SENSOR_QUERY_SIZE 11
+
+/* If we can't figure out how many bytes of abs data there are per finger,
+ * we'll use this and hope we get lucky.
+ */
+#define DEFAULT_ABS_BYTES_PER_FINGER 5
+
+/* How many finger status values are packed into a byte?
+ */
+#define FINGER_STATES_PER_BYTE 4
+#define BITS_PER_FINGER_STATE  2
+
+#define REL_BYTES_PER_FINGER 2
+
+struct f11_instance_data {
+       struct rmi_F11_device_query *device_info;
+       struct rmi_F11_sensor_query *sensor_info;
+       struct rmi_F11_control *control_registers;
+       unsigned char finger_data_buffer_size;
+       unsigned char abs_data_offset;
+       unsigned char abs_data_size;
+       unsigned char rel_data_offset;
+       unsigned char gesture_data_offset;
+       unsigned char *finger_data_buffer;
+       /* Last X & Y seen, needed at finger lift.  Was down indicates
+        * at least one finger was here. TODO: Eventually we'll need to
+        * track this info on a per finger basis. */
+       bool wasdown;
+       unsigned int old_X;
+       unsigned int old_Y;
+       /* Transformations to be applied to coordinates before reporting. */
+       bool flip_X;
+       bool flip_Y;
+       int offset_X;
+       int offset_Y;
+       int clip_X_low;
+       int clip_X_high;
+       int clip_Y_low;
+       int clip_Y_high;
+       bool swap_axes;
+       bool rel_report_enabled;
+
+       unsigned int data8_offset;
+       unsigned int data9_offset;
+       unsigned int data10_offset;
+       unsigned int data11_offset;
+       unsigned int data13_offset;
+       unsigned int data14_offset;
+       unsigned int data16_offset;
+};
+
+enum finger_state {
+       F11_NO_FINGER = 0,
+       F11_PRESENT = 1,
+       F11_INACCURATE = 2,
+       F11_RESERVED = 3
+};
+
+#define FINGER_STATE_MASK 0x03
+
+static ssize_t rmi_fn_11_flip_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_flip_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t rmi_fn_11_clip_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_clip_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t rmi_fn_11_offset_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_offset_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count);
+
+static ssize_t rmi_fn_11_swap_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_swap_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t rmi_fn_11_relreport_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_11_relreport_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+static ssize_t rmi_fn_11_maxPos_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static struct device_attribute attrs[] = {
+       __ATTR(flip, 0666,
+              rmi_fn_11_flip_show, rmi_fn_11_flip_store),      /* RW attr */
+       __ATTR(clip, 0666,
+              rmi_fn_11_clip_show, rmi_fn_11_clip_store),      /* RW attr */
+       __ATTR(offset, 0666,
+              rmi_fn_11_offset_show, rmi_fn_11_offset_store),  /* RW attr */
+       __ATTR(swap, 0666,
+              rmi_fn_11_swap_show, rmi_fn_11_swap_store),      /* RW attr */
+       __ATTR(relreport, 0666,
+              rmi_fn_11_relreport_show, rmi_fn_11_relreport_store),    /* RW */
+       __ATTR(maxPos, 0444,
+              rmi_fn_11_maxPos_show, rmi_store_error)  /* R0 attr */
+};
+
+static void handle_absolute_reports(struct rmi_function_info *rmifninfo);
+static void handle_relative_report(struct rmi_function_info *rmifninfo);
+
+/*
+ * Read the device query register and extract interesting data.
+ */
+static int read_device_query(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+       unsigned char device_query;
+
+       retval = rmi_read(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.query_base_addr,
+                       &device_query);
+       if (retval) {
+               pr_err("%s: Could not read F11 device query at 0x%04x\n",
+                      __func__,
+                       rmifninfo->function_descriptor.query_base_addr);
+               return retval;
+       }
+
+       /* Extract device data. */
+       instance_data->device_info->has_query_9 =
+               (device_query & HAS_QUERY_9_MASK) != 0;
+       instance_data->device_info->has_query_11 =
+               (device_query & HAS_QUERY_11_MASK) != 0;
+       instance_data->device_info->number_of_sensors =
+               (device_query & NR_SENSORS_MASK) + 1;
+       pr_debug("%s: F11 device - %d sensors.  Query 9? %d.", __func__,
+               instance_data->device_info->number_of_sensors,
+               instance_data->device_info->has_query_9);
+       if (instance_data->device_info->number_of_sensors > 1)
+               pr_warning("%s: WARNING device has %d sensors, but RMI4 "
+               "driver does not support multiple sensors yet.",
+               __func__,
+               instance_data->device_info->number_of_sensors);
+
+       return retval;
+}
+
+/*
+ * Read and parse the per sensor query information from the specified
+ * address into the specified sensor_info.
+ */
+static int read_per_sensor_query(struct rmi_function_info *rmifninfo,
+                                struct rmi_F11_sensor_query *sensor_info,
+                                unsigned char address)
+{
+       int retval = 0;
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+       unsigned char query_buffer[MAX_PER_SENSOR_QUERY_SIZE];
+       unsigned int nr_fingers;
+       unsigned int query_offset;
+
+       retval = rmi_read_multiple(rmifninfo->sensor, address,
+                                  query_buffer, sizeof(query_buffer));
+       if (retval) {
+               pr_err("%s: Could not read F11 device query at 0x%04x\n",
+                      __func__, address);
+               return retval;
+       }
+
+       /* 2D data sources have only 3 bits for the number of fingers
+        * supported - so the encoding is a bit wierd. */
+       sensor_info->number_of_fingers = DEFAULT_NR_OF_FINGERS;
+       nr_fingers = query_buffer[NR_FINGERS_OFFSET] & NR_FINGERS_MASK;
+       switch (nr_fingers) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+               sensor_info->number_of_fingers = nr_fingers + 1;
+               break;
+       case 5:
+               sensor_info->number_of_fingers = 10;
+               break;
+       default:
+               pr_warning("%s: Invalid F11 nr fingers %d. Assuming %d.",
+                       __func__, nr_fingers, DEFAULT_NR_OF_FINGERS);
+       }
+       pr_debug("%s: Number of fingers: %d.", __func__,
+               sensor_info->number_of_fingers);
+
+       sensor_info->configurable =
+               (query_buffer[CONFIGURABLE_OFFSET] & CONFIGURABLE_MASK) != 0;
+       sensor_info->has_sensitivity_adjust =
+               (query_buffer[HAS_SENSITIVITY_ADJUST_OFFSET] &
+               HAS_SENSITIVITY_ADJUST_MASK) != 0;
+       sensor_info->has_gestures =
+               (query_buffer[HAS_GESTURES_OFFSET] & HAS_GESTURES_MASK) != 0;
+       sensor_info->has_absolute =
+               (query_buffer[HAS_ABS_OFFSET] & HAS_ABS_MASK) != 0;
+       sensor_info->has_relative =
+               (query_buffer[HAS_REL_OFFSET] & HAS_REL_MASK) != 0;
+
+       sensor_info->abs_data_size =
+               query_buffer[ABS_DATA_SIZE_OFFSET] & ABS_DATA_SIZE_MASK;
+       sensor_info->has_anchored_finger =
+               query_buffer[HAS_ANCHORED_FINGER_OFFSET] &
+               HAS_ANCHORED_FINGER_MASK;
+       sensor_info->has_adj_hyst =
+               query_buffer[HAS_ADJ_HYST_OFFSET] & HAS_ADJ_HYST_MASK;
+       sensor_info->has_dribble =
+               query_buffer[HAS_DRIBBLE_OFFSET] & HAS_DRIBBLE_MASK;
+
+       /* From here on, query offsets are determined by the presence or
+        * absence of various features.
+        */
+       query_offset = ABS_DATA_SIZE_OFFSET + 1;
+
+       /* This byte is here if we have relative reporting, but it
+        * doesn't contain anything.
+        */
+       if (sensor_info->has_relative)
+               query_offset++;
+
+       /* The next two bytes are present if we have gestures. */
+       if (sensor_info->has_gestures) {
+               sensor_info->has_pinch =
+                       query_buffer[query_offset] & HAS_PINCH_MASK;
+               sensor_info->has_flick =
+                       query_buffer[query_offset] & HAS_FLICK_MASK;
+               sensor_info->has_tap =
+                       query_buffer[query_offset] & HAS_SINGLE_TAP_MASK;
+               sensor_info->has_tap_and_hold =
+                       query_buffer[query_offset] & HAS_TAP_AND_HOLD_MASK;
+               sensor_info->has_double_tap =
+                       query_buffer[query_offset] & HAS_DOUBLE_TAP_MASK;
+               sensor_info->has_early_tap =
+                       query_buffer[query_offset] & HAS_EARLY_TAP_MASK;
+               sensor_info->has_press =
+                       query_buffer[query_offset] & HAS_PRESS_MASK;
+               query_offset++;
+
+               sensor_info->has_palm_detect =
+                       query_buffer[query_offset] & HAS_PALM_DETECT_MASK;
+               sensor_info->has_rotate =
+                       query_buffer[query_offset] & HAS_ROTATE_MASK;
+               sensor_info->has_touch_shapes =
+                       query_buffer[query_offset] & HAS_TOUCH_SHAPES_MASK;
+               sensor_info->has_scroll_zones =
+                       query_buffer[query_offset] & HAS_SCROLL_ZONES_MASK;
+               sensor_info->has_individual_scroll_zones =
+                       query_buffer[query_offset] &
+                       HAS_INDIVIDUAL_SCROLL_ZONES_MASK;
+               sensor_info->has_multifinger_scroll =
+                       query_buffer[query_offset] &
+                       HAS_MULTIFINGER_SCROLL_MASK;
+               sensor_info->has_multifinger_scroll_edge_motion =
+                       query_buffer[query_offset] &
+                       HAS_MULTIFINGER_SCROLL_EDGE_MOTION_MASK;
+               sensor_info->has_multifinger_scroll_inertia =
+                       query_buffer[query_offset] &
+                       HAS_MULTIFINGER_SCROLL_INERTIA_MASK;
+               query_offset++;
+       }
+
+       if (instance_data->device_info->has_query_9) {
+               sensor_info->has_pen =
+                       query_buffer[query_offset] & HAS_PEN_MASK;
+               sensor_info->has_proximity =
+                       query_buffer[query_offset] & HAS_PROXIMITY_MASK;
+               sensor_info->has_palm_detect_sensitivity =
+                       query_buffer[query_offset] &
+                       HAS_PALM_DETECT_SENSITIVITY_MASK;
+               sensor_info->has_suppress_on_palm_detect =
+                       query_buffer[query_offset] &
+                       HAS_SUPPRESS_ON_PALM_DETECT_MASK;
+               query_offset++;
+       }
+
+       if (sensor_info->has_touch_shapes) {
+               sensor_info->number_of_touch_shapes =
+                       (query_buffer[query_offset] &
+                       NUMBER_OF_TOUCH_SHAPES_MASK) + 1;
+               query_offset++;
+       }
+
+       if (instance_data->device_info->has_query_11) {
+               sensor_info->has_Z_tuning =
+                       query_buffer[query_offset] & HAS_Z_TUNING_MASK;
+               sensor_info->has_algorithm_selection =
+                       query_buffer[query_offset] & HAS_ALGORITHM_SECTION_MASK;
+               query_offset++;
+       }
+
+       return 0;
+}
+
+/* Figure out just how much data we'll need to read. */
+static void compute_finger_data_size(struct rmi_function_info *rmifninfo,
+                                    struct rmi_F11_sensor_query *sensor_info)
+{
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+       unsigned int data_buffer_size = 0;
+
+       /* Finger state comes first in the data registers.
+        */
+       data_buffer_size =  (sensor_info->number_of_fingers +
+               FINGER_STATES_PER_BYTE - 1) / FINGER_STATES_PER_BYTE;
+
+       /* Next comes absolute data.
+        */
+       if (sensor_info->has_absolute) {
+               instance_data->abs_data_offset = data_buffer_size;
+               switch (sensor_info->abs_data_size) {
+               case 0:
+                       instance_data->abs_data_size = 5;
+                       break;
+               default:
+                       instance_data->abs_data_size =
+                               DEFAULT_ABS_BYTES_PER_FINGER;
+                       pr_warning("%s: Unrecognized abs data size %d ignored.",
+                               __func__, sensor_info->abs_data_size);
+               }
+               data_buffer_size += sensor_info->number_of_fingers *
+                       instance_data->abs_data_size;
+       }
+
+       /* Then comes the relative data.  Once again, it's optional.
+        */
+       if (sensor_info->has_relative) {
+               instance_data->rel_data_offset = data_buffer_size;
+               data_buffer_size +=
+                       sensor_info->number_of_fingers * REL_BYTES_PER_FINGER;
+       }
+
+       /* Gesture data is next, and it's very optional and very complicated.
+        */
+       if (sensor_info->has_gestures) {
+               instance_data->gesture_data_offset = data_buffer_size;
+               if (sensor_info->has_pinch ||
+                               sensor_info->has_press ||
+                               sensor_info->has_flick ||
+                               sensor_info->has_early_tap ||
+                               sensor_info->has_double_tap ||
+                               sensor_info->has_tap ||
+                               sensor_info->has_tap_and_hold) {
+                       instance_data->data8_offset = data_buffer_size;
+                       data_buffer_size++;
+                       instance_data->data9_offset = data_buffer_size;
+                       data_buffer_size++;
+               } else if (sensor_info->has_palm_detect ||
+                               sensor_info->has_rotate ||
+                               sensor_info->has_touch_shapes ||
+                               sensor_info->has_scroll_zones ||
+                               sensor_info->has_individual_scroll_zones ||
+                               sensor_info->has_multifinger_scroll ||
+                               sensor_info->has_multifinger_scroll_edge_motion
+                               ||
+                               sensor_info->has_multifinger_scroll_inertia) {
+                       instance_data->data9_offset = data_buffer_size;
+                       data_buffer_size++;
+               }
+               if (sensor_info->has_pinch || sensor_info->has_flick) {
+                       instance_data->data10_offset = data_buffer_size;
+                       data_buffer_size++;
+               }
+               if (sensor_info->has_rotate || sensor_info->has_flick) {
+                       instance_data->data11_offset = data_buffer_size;
+                       data_buffer_size += ROTATE_FLICK_DATA_BYTES;
+               }
+               if (sensor_info->has_touch_shapes) {
+                       instance_data->data13_offset = data_buffer_size;
+                       data_buffer_size +=
+                               (sensor_info->number_of_touch_shapes +
+                               TOUCH_SHAPE_BITS_PER_BYTE - 1) /
+                               TOUCH_SHAPE_BITS_PER_BYTE;
+               }
+               if (sensor_info->has_scroll_zones) {
+                       instance_data->data14_offset = data_buffer_size;
+                       data_buffer_size += SCROLL_ZONE_DATA_BYTES;
+               }
+               if (sensor_info->has_individual_scroll_zones) {
+                       instance_data->data16_offset = data_buffer_size;
+                       data_buffer_size += SCROLL_ZONE_DATA_BYTES;
+               }
+       }
+
+       instance_data->finger_data_buffer_size = data_buffer_size;
+}
+
+/* Reading and parsing the F11 query registers is a big hairy wad.  There's a
+ * lot of stuff that is dependent on the presence or absence of other stuff,
+ * and there's really no tidy way to deal with it.  We can break it down into
+ * a few function calls, but some things (like computing finger data size)
+ * are just not amenable to further break down.
+ */
+static int read_query_registers(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+       unsigned char query_address =
+               rmifninfo->function_descriptor.query_base_addr;
+
+       retval = read_device_query(rmifninfo);
+
+       if (retval)
+               return retval;
+
+       query_address = query_address + DEVICE_QUERY_SIZE;
+
+       retval = read_per_sensor_query(rmifninfo, instance_data->sensor_info,
+                       query_address);
+
+       if (retval)
+               return retval;
+
+       compute_finger_data_size(rmifninfo, instance_data->sensor_info);
+
+       return 0;
+}
+
+static enum finger_state get_finger_state(unsigned char finger,
+                                    unsigned char *buffer)
+{
+       int finger_byte = finger / FINGER_STATES_PER_BYTE;
+       int finger_shift =
+               (finger % FINGER_STATES_PER_BYTE) * BITS_PER_FINGER_STATE;
+       return (buffer[finger_byte] >> finger_shift) & FINGER_STATE_MASK;
+}
+
+/*
+ * This reads in a sample and reports the function $11 source data to the
+ * input subsystem. It is used for both polling and interrupt driven
+ * operation. This is called a lot so don't put in any informational
+ * printks since they will slow things way down!
+ */
+void FN_11_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs)
+{
+       /* number of touch points - fingers down in this case */
+       int finger_down_count = 0;
+       int finger;
+       struct rmi_function_device *function_device =
+                       rmifninfo->function_device;
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+       int retval;
+
+       /* get 2D sensor finger data */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.data_base_addr,
+                       instance_data->finger_data_buffer,
+                       instance_data->finger_data_buffer_size);
+       if (retval) {
+               pr_err("%s: Failed to read finger data registers, code=%d.\n",
+                      __func__, retval);
+               return;
+       }
+
+       /* First we need to count the fingers and generate some events
+        * related to that. */
+       for (finger = 0; finger < instance_data->sensor_info->number_of_fingers;
+            finger++) {
+               enum finger_state finger_status = get_finger_state(finger,
+                               instance_data->finger_data_buffer);
+               if (finger_status == F11_PRESENT
+                   || finger_status == F11_INACCURATE) {
+                       finger_down_count++;
+                       instance_data->wasdown = true;
+               }
+       }
+       input_report_key(function_device->input, BTN_TOUCH, finger_down_count);
+
+       for (finger = 0;
+            finger < (instance_data->sensor_info->number_of_fingers - 1);
+            finger++)
+               input_report_key(function_device->input, BTN_2 + finger,
+                                finger_down_count >= (finger + 2));
+
+       if (instance_data->sensor_info->has_absolute)
+               handle_absolute_reports(rmifninfo);
+
+       if (instance_data->sensor_info->has_relative &&
+                       instance_data->rel_report_enabled)
+               handle_relative_report(rmifninfo);
+
+       input_sync(function_device->input); /* sync after groups of events */
+
+}
+EXPORT_SYMBOL(FN_11_inthandler);
+
+static void handle_absolute_reports(struct rmi_function_info *rmifninfo)
+{
+       int finger;
+       int finger_down_count = 0;
+       struct rmi_function_device *function_device =
+                       rmifninfo->function_device;
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+
+       for (finger = 0; finger < instance_data->sensor_info->number_of_fingers;
+            finger++) {
+               enum finger_state finger_status = get_finger_state(finger,
+                               instance_data->finger_data_buffer);
+               int X = 0, Y = 0, Z = 0, Wy = 0, Wx = 0;
+
+               /* if finger status indicates a finger is present then
+                *   extract the finger data and report it */
+               if (finger_status == F11_PRESENT
+                               || finger_status == F11_INACCURATE) {
+                       int max_X = instance_data->control_registers->
+                               sensor_max_X_pos;
+                       int max_Y = instance_data->control_registers->
+                               sensor_max_Y_pos;
+                       int reg = instance_data->abs_data_offset +
+                               (finger * instance_data->abs_data_size);
+
+                       finger_down_count++;
+
+                       X = ((instance_data->finger_data_buffer[reg +
+                                       X_HIGH_BITS_OFFSET] <<
+                                       XY_HIGH_BITS_SHIFT) & XY_HIGH_BITS_MASK)
+                               | ((instance_data->finger_data_buffer[reg +
+                                       XY_LOW_BITS_OFFSET] >> X_LOW_BITS_SHIFT)
+                               & XY_LOW_BITS_MASK);
+                       Y = ((instance_data->finger_data_buffer[reg +
+                                       Y_HIGH_BITS_OFFSET] <<
+                                       XY_HIGH_BITS_SHIFT) & XY_HIGH_BITS_MASK)
+                               | ((instance_data->finger_data_buffer[reg +
+                                       XY_LOW_BITS_OFFSET] >> Y_LOW_BITS_SHIFT)
+                                       & XY_LOW_BITS_MASK);
+                       /* First thing to do is swap axes if needed. */
+                       if (instance_data->swap_axes) {
+                               int temp = X;
+                               X = Y;
+                               Y = temp;
+                               max_X = instance_data->control_registers->
+                                       sensor_max_Y_pos;
+                               max_Y = instance_data->control_registers->
+                                       sensor_max_X_pos;
+                       }
+                       if (instance_data->flip_X)
+                               X = max(max_X - X, 0);
+                       X = X - instance_data->offset_X;
+                       X = min(max(X, instance_data->clip_X_low),
+                               instance_data->clip_X_high);
+                       if (instance_data->flip_Y)
+                               Y = max(max_Y - Y, 0);
+                       Y = Y - instance_data->offset_Y;
+                       Y = min(max(Y, instance_data->clip_Y_low),
+                               instance_data->clip_Y_high);
+
+                       Wx = (instance_data->finger_data_buffer[reg +
+                               W_XY_OFFSET] >> W_Y_SHIFT) & W_XY_MASK;
+                       Wy = (instance_data->finger_data_buffer[reg +
+                               W_XY_OFFSET] >> W_Y_SHIFT) & W_XY_MASK;
+                       if (instance_data->swap_axes) {
+                               int temp = Wx;
+                               Wx = Wy;
+                               Wy = temp;
+                       }
+
+                       Z = instance_data->finger_data_buffer[reg + Z_OFFSET];
+#if    POS_DEBUG
+                       pr_info("Finger %d - X:%d, Y:%d, Z:%d, Wx:%d, Wy:%d\n",
+                                finger, X, Y, Z, Wx, Wy);
+#endif
+
+                       /* if this is the first finger report normal
+                       * ABS_X, ABS_Y, PRESSURE, TOOL_WIDTH events for
+                       * non-MT apps. Apps that support Multi-touch
+                       * will ignore these events and use the MT
+                       * events. Apps that don't support Multi-touch
+                       * will still function.
+                       */
+                       if (finger_down_count == 1) {
+                               instance_data->old_X = X;
+                               instance_data->old_Y = Y;
+                               input_report_abs(function_device->input,
+                                               ABS_X, X);
+                               input_report_abs(function_device->input,
+                                               ABS_Y, Y);
+                               input_report_abs(function_device->input,
+                                               ABS_PRESSURE, Z);
+                               input_report_abs(function_device->input,
+                                               ABS_TOOL_WIDTH, max(Wx, Wy));
+                       } else {
+                               /* TODO generate non MT events for
+                                       * multifinger situation. */
+                       }
+#if defined(CONFIG_SYNA_MULTI_TOUCH)
+                       /* Report Multi-Touch events for each finger */
+#if defined(ABS_MT_PRESSURE)
+                       /* Finger pressure; not supported in all kernel
+                        * versions. */
+                       input_report_abs(function_device->input,
+                                       ABS_MT_PRESSURE, Z);
+#endif
+                       /* major axis of touch area ellipse */
+                       input_report_abs(function_device->input,
+                                       ABS_MT_TOUCH_MAJOR, max(Wx, Wy));
+                       /* minor axis of touch area ellipse */
+                       input_report_abs(function_device->input,
+                                       ABS_MT_TOUCH_MINOR, min(Wx, Wy));
+                       /* Currently only 2 supported - 1 or 0 */
+                       input_report_abs(function_device->input,
+                                       ABS_MT_ORIENTATION,
+                                       (Wx > Wy ? 1 : 0));
+                       input_report_abs(function_device->input,
+                                       ABS_MT_POSITION_X, X);
+                       input_report_abs(function_device->input,
+                                       ABS_MT_POSITION_Y, Y);
+
+                       /* TODO: Tracking ID needs to be reported but
+                               * not used yet. Could be formed by keeping
+                               * an id per position and assiging a new id
+                               * when finger_status changes for that position.
+                               */
+                       input_report_abs(function_device->input,
+                                       ABS_MT_TRACKING_ID,
+                                       finger + 1);
+
+                       /* MT sync between fingers */
+                       input_mt_sync(function_device->input);
+#endif
+               }
+       }
+
+       /* if we had a finger down before and now we don't have
+       * any send a button up. */
+       if ((finger_down_count == 0) && instance_data->wasdown) {
+               instance_data->wasdown = false;
+
+#if defined(CONFIG_SYNA_MULTI_TOUCH)
+#if defined(ABS_MT_PRESSURE)
+               input_report_abs(function_device->input, ABS_MT_PRESSURE, 0);
+#endif
+               input_report_abs(function_device->input, ABS_MT_TOUCH_MAJOR, 0);
+               input_report_abs(function_device->input, ABS_MT_TOUCH_MINOR, 0);
+               input_report_abs(function_device->input, ABS_MT_POSITION_X,
+                               instance_data->old_X);
+               input_report_abs(function_device->input, ABS_MT_POSITION_Y,
+                               instance_data->old_Y);
+               input_report_abs(function_device->input, ABS_MT_TRACKING_ID, 1);
+               input_mt_sync(function_device->input);
+#endif
+
+               input_report_abs(function_device->input, ABS_X,
+                               instance_data->old_X);
+               input_report_abs(function_device->input, ABS_Y,
+                               instance_data->old_Y);
+               instance_data->old_X = instance_data->old_Y = 0;
+               pr_debug("%s: Finger up.", __func__);
+       }
+}
+
+#define F11_MIN_RELATIVE -128
+#define F11_MAX_RELATIVE 127
+
+/* This function reads in relative data for first finger and
+ * sends it to input system */
+static void handle_relative_report(struct rmi_function_info *rmifninfo)
+{
+       struct f11_instance_data *instance_data = rmifninfo->fndata;
+       struct rmi_function_device *function_device =
+                       rmifninfo->function_device;
+       signed char X, Y;
+       int reg = instance_data->rel_data_offset;
+
+
+       X = instance_data->finger_data_buffer[reg + REL_X_OFFSET];
+       Y = instance_data->finger_data_buffer[reg + REL_Y_OFFSET];
+       if (instance_data->swap_axes) {
+               signed char temp = X;
+               X = Y;
+               Y = temp;
+       }
+       if (instance_data->flip_X)
+               X = -X;
+       if (instance_data->flip_Y)
+               Y = -Y;
+       X = (signed char)min(F11_MAX_RELATIVE,
+                               max(F11_MIN_RELATIVE, (int)X));
+       Y = (signed char)min(F11_MAX_RELATIVE,
+                               max(F11_MIN_RELATIVE, (int)Y));
+
+       input_report_rel(function_device->input, REL_X, X);
+       input_report_rel(function_device->input, REL_Y, Y);
+}
+
+/* This is a stub for now, and will be expanded as this implementation
+ * evolves.
+ */
+int FN_11_config(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+
+       pr_debug("%s: RMI4 function $11 config\n", __func__);
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_11_config);
+
+/* This operation is done in a number of places, so we have a handy routine
+ * for it.
+ */
+static void f11_set_abs_params(struct rmi_function_device *function_device)
+{
+       struct f11_instance_data *instance_data = function_device->rfi->fndata;
+       /* Use the max X and max Y read from the device, or the clip values,
+        * whichever is stricter.
+        */
+       int xMin = instance_data->clip_X_low;
+       int xMax =
+           min((int)instance_data->control_registers->sensor_max_X_pos,
+               instance_data->clip_X_high);
+       int yMin = instance_data->clip_Y_low;
+       int yMax =
+           min((int)instance_data->control_registers->sensor_max_Y_pos,
+               instance_data->clip_Y_high);
+       if (instance_data->swap_axes) {
+               int temp = xMin;
+               xMin = yMin;
+               yMin = temp;
+               temp = xMax;
+               xMax = yMax;
+               yMax = temp;
+       }
+       pr_debug("%s: Set ranges X=[%d..%d] Y=[%d..%d].", __func__, xMin, xMax,
+                yMin, yMax);
+       input_set_abs_params(function_device->input, ABS_X, xMin, xMax, 0, 0);
+       input_set_abs_params(function_device->input, ABS_Y, yMin, yMax, 0, 0);
+       input_set_abs_params(function_device->input, ABS_PRESSURE, 0, 255, 0,
+                            0);
+       input_set_abs_params(function_device->input, ABS_TOOL_WIDTH, 0, 15, 0,
+                            0);
+
+#if defined(CONFIG_SYNA_MULTI_TOUCH)
+#if defined(ABS_MT_PRESSURE)
+       input_set_abs_params(function_device->input, ABS_MT_PRESSURE, 0, 255,
+                            0, 0);
+#endif
+       input_set_abs_params(function_device->input, ABS_MT_TOUCH_MAJOR, 0, 15,
+                            0, 0);
+       input_set_abs_params(function_device->input, ABS_MT_TOUCH_MINOR, 0, 15,
+                            0, 0);
+       input_set_abs_params(function_device->input, ABS_MT_ORIENTATION, 0, 1,
+                            0, 0);
+       input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID, 1, 10,
+                            0, 0);
+       input_set_abs_params(function_device->input, ABS_MT_POSITION_X, xMin,
+                            xMax, 0, 0);
+       input_set_abs_params(function_device->input, ABS_MT_POSITION_Y, yMin,
+                            yMax, 0, 0);
+#endif
+}
+
+/* Initialize any function $11 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_11_init(struct rmi_function_device *function_device)
+{
+       struct f11_instance_data *instance_data = function_device->rfi->fndata;
+       int retval = 0;
+       int attr_count = 0;
+       struct rmi_f11_functiondata *functiondata =
+               rmi_sensor_get_functiondata(function_device->sensor,
+                       RMI_F11_INDEX);
+       pr_debug("%s: RMI4 F11 init", __func__);
+
+       /* TODO: Initialize these through some normal kernel mechanism.
+        */
+       instance_data->flip_X = false;
+       instance_data->flip_Y = false;
+       instance_data->swap_axes = false;
+       instance_data->rel_report_enabled = true;
+       instance_data->offset_X = instance_data->offset_Y = 0;
+       instance_data->clip_X_low = instance_data->clip_Y_low = 0;
+       /* TODO: 65536 should actually be the largest valid RMI4
+        * position coordinate */
+       instance_data->clip_X_high = instance_data->clip_Y_high = 65536;
+
+       /* Load any overrides that were specified via platform data.
+        */
+       if (functiondata) {
+               pr_debug("%s: found F11 per function platformdata.", __func__);
+               instance_data->flip_X = functiondata->flip_X;
+               instance_data->flip_Y = functiondata->flip_Y;
+               instance_data->swap_axes = functiondata->swap_axes;
+               if (functiondata->offset) {
+                       instance_data->offset_X = functiondata->offset->x;
+                       instance_data->offset_Y = functiondata->offset->y;
+               }
+               if (functiondata->clip_X) {
+                       if (functiondata->clip_X->min >=
+                           functiondata->clip_X->max) {
+                               pr_warning
+                                   ("%s: Clip X min (%d) >= X clip max (%d) "
+                                    "- ignored.",
+                                    __func__, functiondata->clip_X->min,
+                                    functiondata->clip_X->max);
+                       } else {
+                               instance_data->clip_X_low =
+                                   functiondata->clip_X->min;
+                               instance_data->clip_X_high =
+                                   functiondata->clip_X->max;
+                       }
+               }
+               if (functiondata->clip_Y) {
+                       if (functiondata->clip_Y->min >=
+                           functiondata->clip_Y->max) {
+                               pr_warning
+                                   ("%s: Clip Y min (%d) >= Y clip max (%d) "
+                                    "- ignored.",
+                                    __func__, functiondata->clip_Y->min,
+                                    functiondata->clip_Y->max);
+                       } else {
+                               instance_data->clip_Y_low =
+                                   functiondata->clip_Y->min;
+                               instance_data->clip_Y_high =
+                                   functiondata->clip_Y->max;
+                       }
+               }
+       }
+
+       /* need to init the input abs params for the 2D */
+       set_bit(EV_ABS, function_device->input->evbit);
+       set_bit(EV_SYN, function_device->input->evbit);
+       set_bit(EV_KEY, function_device->input->evbit);
+       set_bit(BTN_TOUCH, function_device->input->keybit);
+
+
+       f11_set_abs_params(function_device);
+
+       pr_debug("%s: Creating sysfs files.", __func__);
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&function_device->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       pr_err
+                           ("%s: Failed to create sysfs file for %s.",
+                            __func__, attrs[attr_count].attr.name);
+                       retval = -ENODEV;
+                       goto error_exit;
+               }
+       }
+
+       return 0;
+
+error_exit:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&function_device->dev.kobj,
+                                 &attrs[attr_count].attr);
+       /* If you alloc anything, free it here. */
+       return retval;
+}
+EXPORT_SYMBOL(FN_11_init);
+
+int FN_11_detect(struct rmi_function_info *rmifninfo)
+{
+       unsigned char control_buffer[12]; /* TODO: Compute size correctly. */
+       int retval = 0;
+       struct f11_instance_data *instance_data;
+
+       pr_debug("%s: RMI4 F11 detect\n", __func__);
+
+       if (rmifninfo->fndata) {
+               /* detect routine should only ever be called once
+                * per rmifninfo. */
+               pr_err("%s: WTF?!? F11 instance data is already present!",
+                      __func__);
+               return -EINVAL;
+       }
+       instance_data = kzalloc(sizeof(struct f11_instance_data), GFP_KERNEL);
+       if (!instance_data) {
+               pr_err("%s: Error allocating F11 instance data.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       rmifninfo->fndata = instance_data;
+
+       instance_data->device_info =
+           kzalloc(sizeof(struct rmi_F11_device_query), GFP_KERNEL);
+       if (!instance_data->device_info) {
+               pr_err("%s: Error allocating F11 device query.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       instance_data->sensor_info =
+           kzalloc(sizeof(struct rmi_F11_sensor_query), GFP_KERNEL);
+       if (!instance_data->sensor_info) {
+               pr_err("%s: Error allocating F11 sensor query.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       retval = read_query_registers(rmifninfo);
+       if (retval) {
+               pr_err("%s: Failed to read sensor query registers.", __func__);
+               goto error_exit;
+       }
+
+       instance_data->finger_data_buffer =
+           kcalloc(instance_data->finger_data_buffer_size,
+                   sizeof(unsigned char), GFP_KERNEL);
+       if (!instance_data->finger_data_buffer) {
+               pr_err("%s: Failed to allocate finger data buffer.", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       /* Grab a copy of the control registers. */
+       instance_data->control_registers =
+           kzalloc(sizeof(struct rmi_F11_control), GFP_KERNEL);
+       if (!instance_data->control_registers) {
+               pr_err("%s: Error allocating F11 control registers.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                             rmifninfo->function_descriptor.control_base_addr,
+                             control_buffer, sizeof(control_buffer));
+       if (retval) {
+               pr_err("%s: Failed to read F11 control registers.", __func__);
+               goto error_exit;
+       }
+       instance_data->control_registers->sensor_max_X_pos =
+           (((int)control_buffer[7] & 0x0F) << 8) + control_buffer[6];
+       instance_data->control_registers->sensor_max_Y_pos =
+           (((int)control_buffer[9] & 0x0F) << 8) + control_buffer[8];
+       pr_debug("%s: Max X %d Max Y %d", __func__,
+                instance_data->control_registers->sensor_max_X_pos,
+                instance_data->control_registers->sensor_max_Y_pos);
+       return 0;
+
+error_exit:
+       if (instance_data) {
+               kfree(instance_data->sensor_info);
+               kfree(instance_data->device_info);
+               kfree(instance_data->control_registers);
+               kfree(instance_data->finger_data_buffer);
+       }
+       kfree(instance_data);
+       rmifninfo->fndata = NULL;
+       return retval;
+}
+EXPORT_SYMBOL(FN_11_detect);
+
+static ssize_t rmi_fn_11_maxPos_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u %u\n",
+               instance_data->control_registers->sensor_max_X_pos,
+               instance_data->control_registers->sensor_max_Y_pos);
+}
+
+static ssize_t rmi_fn_11_flip_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u %u\n", instance_data->flip_X,
+                       instance_data->flip_Y);
+}
+
+static ssize_t rmi_fn_11_flip_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+       unsigned int new_X, new_Y;
+
+       if (sscanf(buf, "%u %u", &new_X, &new_Y) != 2)
+               return -EINVAL;
+       if (new_X < 0 || new_X > 1 || new_Y < 0 || new_Y > 1)
+               return -EINVAL;
+       instance_data->flip_X = new_X;
+       instance_data->flip_Y = new_Y;
+
+       return count;
+}
+
+static ssize_t rmi_fn_11_swap_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->swap_axes);
+}
+
+static ssize_t rmi_fn_11_swap_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+       unsigned int newSwap;
+
+       if (sscanf(buf, "%u", &newSwap) != 1)
+               return -EINVAL;
+       if (newSwap < 0 || newSwap > 1)
+               return -EINVAL;
+       instance_data->swap_axes = newSwap;
+
+       f11_set_abs_params(fn);
+
+       return count;
+}
+
+static ssize_t rmi_fn_11_relreport_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE,
+                       "%u\n", instance_data->rel_report_enabled);
+}
+
+static ssize_t rmi_fn_11_relreport_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+       unsigned int new_value;
+
+       if (sscanf(buf, "%u", &new_value) != 1)
+               return -EINVAL;
+       if (new_value < 0 || new_value > 1)
+               return -EINVAL;
+       instance_data->rel_report_enabled = new_value;
+
+       return count;
+}
+
+static ssize_t rmi_fn_11_offset_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%d %d\n", instance_data->offset_X,
+               instance_data->offset_Y);
+}
+
+static ssize_t rmi_fn_11_offset_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+       int new_X, new_Y;
+
+       if (sscanf(buf, "%d %d", &new_X, &new_Y) != 2)
+               return -EINVAL;
+       instance_data->offset_X = new_X;
+       instance_data->offset_Y = new_Y;
+
+       return count;
+}
+
+static ssize_t rmi_fn_11_clip_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u %u %u %u\n",
+                      instance_data->clip_X_low, instance_data->clip_X_high,
+                      instance_data->clip_Y_low, instance_data->clip_Y_high);
+}
+
+static ssize_t rmi_fn_11_clip_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f11_instance_data *instance_data = fn->rfi->fndata;
+       unsigned int new_X_low, new_X_high, new_Y_low, new_Y_high;
+
+       if (sscanf(buf, "%u %u %u %u",
+                       &new_X_low, &new_X_high, &new_Y_low, &new_Y_high) != 4)
+               return -EINVAL;
+       if (new_X_low < 0 || new_X_low >= new_X_high || new_Y_low < 0
+                       || new_Y_low >= new_Y_high)
+               return -EINVAL;
+       instance_data->clip_X_low = new_X_low;
+       instance_data->clip_X_high = new_X_high;
+       instance_data->clip_Y_low = new_Y_low;
+       instance_data->clip_Y_high = new_Y_high;
+
+       f11_set_abs_params(fn);
+
+       return count;
+}
diff --git a/drivers/input/touchscreen/rmi/rmi_f11.h b/drivers/input/touchscreen/rmi/rmi_f11.h
new file mode 100644 (file)
index 0000000..6616084
--- /dev/null
@@ -0,0 +1,110 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 header.
+ * Copyright (c) 2007 - 2010, Synaptics Incorporated
+ *
+ * For every RMI4 function that has a data source - like 2D sensors,
+ * buttons, LEDs, GPIOs, etc. - the user will create a new rmi_function_xx.c
+ * file and add these functions to perform the config(), init(), report()
+ * and detect() functionality. The function pointers are then srored under
+ * the RMI function info and these functions will automatically be called by
+ * the global config(), init(), report() and detect() functions that will
+ * loop through all data sources and call the data sources functions using
+ * these functions pointed to by the function ptrs.
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_F11_H)
+#define _RMI_F11_H
+
+/* This is the data read from the F11 query registers.
+ */
+struct rmi_F11_device_query {
+       bool has_query_9;
+       bool has_query_11;
+       unsigned char number_of_sensors;
+};
+
+struct rmi_F11_sensor_query {
+       bool configurable;
+       bool has_sensitivity_adjust;
+       bool has_gestures;
+       bool has_absolute;
+       bool has_relative;
+       bool has_adj_hyst;
+       bool has_dribble;
+       bool has_pinch;
+       bool has_flick;
+       bool has_tap;
+       bool has_tap_and_hold;
+       bool has_double_tap;
+       bool has_early_tap;
+       bool has_press;
+
+       bool has_palm_detect;
+       bool has_rotate;
+       bool has_touch_shapes;
+       bool has_scroll_zones;
+       bool has_individual_scroll_zones;
+       bool has_multifinger_scroll;
+       bool has_multifinger_scroll_edge_motion;
+       bool has_multifinger_scroll_inertia;
+
+       bool has_pen;
+       bool has_proximity;
+       bool has_palm_detect_sensitivity;
+       bool has_suppress_on_palm_detect;
+
+       bool has_Z_tuning;
+       bool has_algorithm_selection;
+
+       unsigned char number_of_touch_shapes;
+
+       unsigned char number_of_fingers;
+       unsigned char number_of_X_electrodes;
+       unsigned char number_of_Y_electrodes;
+       unsigned char maximum_electrodes;
+       bool has_anchored_finger;
+       unsigned char abs_data_size;
+};
+
+struct rmi_F11_control {
+       bool relative_ballistics;
+       bool relative_position_filter;
+       bool absolute_position_filter;
+       unsigned char reporting_mode;
+       bool manually_tracked_finger;
+       bool manually_tracked_finger_enable;
+       unsigned char motion_sensitivity;
+       unsigned char palm_detect_threshold;
+       unsigned char delta_X_pos_threshold;
+       unsigned char delta_Y_pos_threshold;
+       unsigned char velocity;
+       unsigned char acceleration;
+       unsigned short sensor_max_X_pos;
+       unsigned short sensor_max_Y_pos;
+};
+
+void FN_11_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs);
+int FN_11_config(struct rmi_function_info *rmifninfo);
+int FN_11_init(struct rmi_function_device *function_device);
+int FN_11_detect(struct rmi_function_info *rmifninfo);
+/* No attention function for Fn $11 */
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_f19.c b/drivers/input/touchscreen/rmi/rmi_f19.c
new file mode 100644 (file)
index 0000000..ccd4a05
--- /dev/null
@@ -0,0 +1,620 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/rmi_platformdata.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f19.h"
+
+struct f19_instance_data {
+       struct rmi_F19_query *device_info;
+       struct rmi_F19_control *control_registers;
+       bool *button_down;
+       unsigned char button_data_buffer_size;
+       unsigned char *button_data_buffer;
+       unsigned char *button_map;
+       int control_register_size;
+       int register_count_for_bit_per_button;
+       int usage_and_filter_mode_offset;
+       int interrupt_enable_offset;
+       int interrupt_enable_length;
+       int single_button_control_length;
+       int single_button_control_offset;
+       int sensor_map_control_offset;
+       int sensor_map_control_length;
+       int single_button_sensor_offset;
+       int single_button_sensor_length;
+       int global_sensor_offset;
+       int global_hysteresis_threshold_offset;
+};
+
+static ssize_t rmi_f19_button_count_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+
+static ssize_t rmi_f19_buttonMap_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f19_buttonMap_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count);
+
+static struct device_attribute attrs[] = {
+       __ATTR(button_count, 0444,
+              rmi_f19_button_count_show, rmi_store_error),     /* RO attr */
+       __ATTR(buttonMap, 0666,
+              rmi_f19_buttonMap_show, rmi_f19_buttonMap_store) /* RW attr */
+};
+
+/*
+ * There is no attention function for F19 - it is left NULL
+ * in the function table so it is not called.
+ *
+ */
+
+/*
+ * This reads in a sample and reports the F19 source data to the
+ * input subsystem. It is used for both polling and interrupt driven
+ * operation. This is called a lot so don't put in any informational
+ * printks since they will slow things way down!
+ */
+void FN_19_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs)
+{
+       struct f19_instance_data *instance_data = rmifninfo->fndata;
+       struct rmi_function_device *function_device =
+           rmifninfo->function_device;
+       int button;
+
+       /* Read the button data. */
+
+       if (rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.data_base_addr,
+                       instance_data->button_data_buffer,
+                       instance_data->button_data_buffer_size)) {
+               pr_err("%s: Failed to read button data registers.\n", __func__);
+               return;
+       }
+
+       /* Generate events for buttons that change state. */
+       for (button = 0; button < instance_data->device_info->button_count;
+            button++) {
+               int button_reg;
+               int button_shift;
+               bool button_status;
+
+               /* determine which data byte the button status is in */
+               button_reg = button / 4;
+               /* bit shift to get button's status */
+               button_shift = button % 8;
+               button_status =
+                   ((instance_data->
+                     button_data_buffer[button_reg] >> button_shift) & 0x01) !=
+                   0;
+
+               /* if the button state changed from the last time report it
+                * and store the new state */
+               if (button_status != instance_data->button_down[button]) {
+                       pr_debug("%s: Button %d (code %d) -> %d.", __func__,
+                                button, instance_data->button_map[button],
+                                button_status);
+                       /* Generate an event here. */
+                       input_report_key(function_device->input,
+                                        instance_data->button_map[button],
+                                        button_status);
+                       instance_data->button_down[button] = button_status;
+               }
+       }
+
+       input_sync(function_device->input); /* sync after groups of events */
+}
+EXPORT_SYMBOL(FN_19_inthandler);
+
+/* This is a stub for now.  It will be filled in as the driver implementation
+ * evolves.
+ */
+int FN_19_config(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+
+       pr_debug("%s: RMI4 F19 config\n", __func__);
+
+       /* TODO: Perform configuration.  In particular, write any cached control
+        * register values to the device. */
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_19_config);
+
+/* Initialize any F19 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_19_init(struct rmi_function_device *function_device)
+{
+       int i, retval = 0;
+       int attr_count = 0;
+       struct f19_instance_data *instance_data = function_device->rfi->fndata;
+       struct rmi_f19_functiondata *functiondata =
+           rmi_sensor_get_functiondata(function_device->sensor, RMI_F19_INDEX);
+
+       pr_debug("%s: RMI4 F19 init\n", __func__);
+
+       if (functiondata && functiondata->button_map) {
+               if (functiondata->button_map->nbuttons !=
+                   instance_data->device_info->button_count) {
+                       pr_warning
+                           ("%s: Platformdata button map size (%d) != number "
+                            "of buttons on device (%d) - ignored.",
+                            __func__, functiondata->button_map->nbuttons,
+                            instance_data->device_info->button_count);
+               } else if (!functiondata->button_map->map) {
+                       pr_warning("%s: Platformdata button map is missing!",
+                                  __func__);
+               } else {
+                       for (i = 0; i < functiondata->button_map->nbuttons; i++)
+                               instance_data->button_map[i] =
+                                   functiondata->button_map->map[i];
+               }
+       }
+
+       /* Set up any input events. */
+       set_bit(EV_SYN, function_device->input->evbit);
+       set_bit(EV_KEY, function_device->input->evbit);
+       /* set bits for each button... */
+       for (i = 0; i < instance_data->device_info->button_count; i++)
+               set_bit(instance_data->button_map[i],
+                       function_device->input->keybit);
+
+       pr_debug("%s: Creating sysfs files.", __func__);
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&function_device->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       pr_err
+                           ("%s: Failed to create sysfs file for %s.",
+                            __func__, attrs[attr_count].attr.name);
+                       retval = -ENODEV;
+                       goto error_exit;
+               }
+       }
+
+       return 0;
+
+error_exit:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&function_device->dev.kobj,
+                                 &attrs[attr_count].attr);
+       /* If you alloc anything, free it here. */
+       return retval;
+}
+EXPORT_SYMBOL(FN_19_init);
+
+static int init_control_registers(struct rmi_function_info *rmifninfo)
+{
+       struct f19_instance_data *instance_data = rmifninfo->fndata;
+       unsigned char *control_registers = NULL;
+       int retval = 0;
+
+       if (instance_data->control_registers) {
+               pr_err
+                   ("%s: WTF? F19 control regsiters are already initialized.",
+                    __func__);
+               return -EINVAL;
+       }
+
+       /* Allocate memory for the control registers. */
+       instance_data->control_registers =
+           kzalloc(sizeof(struct rmi_F19_control), GFP_KERNEL);
+       if (!instance_data->control_registers) {
+               pr_err("%s: Error allocating F19 control registers.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       instance_data->register_count_for_bit_per_button =
+           (instance_data->device_info->button_count + 7) / 8;
+
+       /* Need to compute the amount of data to read since it varies with the
+        * number of buttons */
+               /* 1 for filter mode and button usage bits */
+       instance_data->control_register_size = 1
+               /* interrupt enable bits and single button participation bits */
+           + 2 * instance_data->register_count_for_bit_per_button
+               /* sensormap registers + single button sensitivity registers */
+           + 2 * instance_data->device_info->button_count
+               /* 1 for global sensitivity adjust and
+                * 1 for global hysteresis threshold */
+           + 2;
+
+       /* Allocate a temp memory buffer to read the control registers into */
+       control_registers =
+           kzalloc(instance_data->control_register_size, GFP_KERNEL);
+       if (!control_registers) {
+               pr_err
+                   ("%s: Error allocating temp storage to read "
+                    "fn19 control info.\n",
+                    __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       /* Grab a copy of the control registers. */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                             rmifninfo->function_descriptor.control_base_addr,
+                             control_registers,
+                             instance_data->control_register_size);
+       if (retval) {
+               pr_err("%s: Failed to read F19 control registers.", __func__);
+               goto error_exit;
+       }
+
+       /* Copy over control registers data to the instance data */
+       instance_data->usage_and_filter_mode_offset = 0;
+       instance_data->control_registers->button_usage =
+           control_registers[instance_data->
+                             usage_and_filter_mode_offset] & 0x3;
+       instance_data->control_registers->filter_mode =
+           control_registers[instance_data->
+                             usage_and_filter_mode_offset] & 0xc;
+
+       /* Fill in interrupt enable registers */
+       instance_data->interrupt_enable_offset = 1;
+       instance_data->interrupt_enable_length =
+           instance_data->register_count_for_bit_per_button;
+       instance_data->control_registers->interrupt_enable_registers =
+           kzalloc(instance_data->interrupt_enable_length, GFP_KERNEL);
+       if (!instance_data->control_registers->interrupt_enable_registers) {
+               pr_err("%s: Error allocating storage for interrupt "
+                    "enable control info.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       memcpy(instance_data->control_registers->interrupt_enable_registers,
+              &control_registers[instance_data->interrupt_enable_offset],
+              instance_data->interrupt_enable_length);
+
+       /* Fill in single button control registers */
+       instance_data->single_button_control_offset =
+           instance_data->interrupt_enable_offset +
+           instance_data->interrupt_enable_length;
+       instance_data->single_button_control_length =
+           instance_data->register_count_for_bit_per_button;
+       instance_data->control_registers->single_button_control =
+           kzalloc(instance_data->single_button_control_length, GFP_KERNEL);
+       if (!instance_data->control_registers->single_button_control) {
+               pr_err("%s: Error allocating storage for single button "
+                    "participation control info.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       memcpy(instance_data->control_registers->single_button_control,
+              &control_registers[instance_data->single_button_control_offset],
+              instance_data->single_button_control_length);
+
+       /* Fill in sensor map registers */
+       instance_data->sensor_map_control_offset =
+           instance_data->single_button_control_offset +
+           instance_data->single_button_control_length;
+       instance_data->sensor_map_control_length =
+           instance_data->device_info->button_count;
+       instance_data->control_registers->sensor_map =
+           kzalloc(instance_data->sensor_map_control_length, GFP_KERNEL);
+       if (!instance_data->control_registers->sensor_map) {
+               pr_err("%s: Error allocating storage for sensor map "
+                    "control info.", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       memcpy(instance_data->control_registers->sensor_map,
+              &control_registers[instance_data->sensor_map_control_offset],
+              instance_data->sensor_map_control_length);
+
+       /* Fill in single button sensitivity registers */
+       instance_data->single_button_sensor_offset =
+           instance_data->sensor_map_control_offset +
+           instance_data->sensor_map_control_length;
+       instance_data->single_button_sensor_length =
+           instance_data->device_info->button_count;
+       instance_data->control_registers->single_button_sensitivity =
+           kzalloc(instance_data->single_button_sensor_length, GFP_KERNEL);
+       if (!instance_data->control_registers->single_button_sensitivity) {
+               pr_err
+                   ("%s: Error allocating storage for single button "
+                    "sensitivity control info.",
+                    __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       memcpy(instance_data->control_registers->single_button_sensitivity,
+              &control_registers[instance_data->single_button_sensor_offset],
+              instance_data->single_button_sensor_length);
+
+       /* Fill in global sensitivity adjustment and global
+        * hysteresis threshold values */
+       instance_data->global_sensor_offset =
+           instance_data->single_button_sensor_offset +
+           instance_data->single_button_sensor_length;
+       instance_data->global_hysteresis_threshold_offset =
+           instance_data->global_sensor_offset + 1;
+       instance_data->control_registers->global_sensitivity_adjustment =
+           control_registers[instance_data->global_sensor_offset] & 0x1f;
+       instance_data->control_registers->global_hysteresis_threshold =
+           control_registers[instance_data->
+                             global_hysteresis_threshold_offset] & 0x0f;
+
+       /* Free up temp storage that held copy of control registers */
+       kfree(control_registers);
+
+       return 0;
+
+error_exit:
+       if (instance_data->control_registers) {
+               kfree(
+                 instance_data->control_registers->single_button_sensitivity);
+               kfree(
+                 instance_data->control_registers->interrupt_enable_registers);
+               kfree(instance_data->control_registers->sensor_map);
+               kfree(instance_data->control_registers->single_button_control);
+       }
+       kfree(instance_data->control_registers);
+       kfree(control_registers);
+       return retval;
+}
+
+int FN_19_detect(struct rmi_function_info *rmifninfo)
+{
+       unsigned char query_buffer[2];
+       int retval = 0;
+       int i;
+       struct f19_instance_data *instance_data;
+
+       pr_debug("%s: RMI4 F19 detect\n", __func__);
+
+       if (rmifninfo->fndata) {
+               /* detect routine should only ever be called once
+                * per rmifninfo. */
+               pr_err("%s: WTF?!? F19 instance data is already present!",
+                      __func__);
+               return -EINVAL;
+       }
+       instance_data = kzalloc(sizeof(struct f19_instance_data), GFP_KERNEL);
+       if (!instance_data) {
+               pr_err("%s: Error allocating F19 instance data.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       instance_data->device_info =
+           kzalloc(sizeof(struct rmi_F19_query), GFP_KERNEL);
+       if (!instance_data->device_info) {
+               pr_err("%s: Error allocating F19 device query.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       rmifninfo->fndata = instance_data;
+
+       /* need to get number of fingers supported, data size, etc. -
+          to be used when getting data since the number of registers to
+          read depends on the number of fingers supported and data size. */
+       retval =
+           rmi_read_multiple(rmifninfo->sensor,
+                             rmifninfo->function_descriptor.query_base_addr,
+                             query_buffer, sizeof(query_buffer));
+       if (retval) {
+               pr_err("%s: RMI4 F19 detect: "
+                      "Could not read function query registers 0x%x\n",
+                      __func__,
+                      rmifninfo->function_descriptor.query_base_addr);
+               goto error_exit;
+       }
+
+       /* Extract device data. */
+       instance_data->device_info->configurable = query_buffer[0] & 0x01;
+       instance_data->device_info->has_sensitivity_adjust =
+           query_buffer[0] & 0x02;
+       instance_data->device_info->has_hysteresis_threshold =
+           query_buffer[0] & 0x04;
+       instance_data->device_info->button_count = query_buffer[1] & 0x01F;
+       pr_debug("%s: F19 device - %d buttons...", __func__,
+                instance_data->device_info->button_count);
+
+       /* Figure out just how much data we'll need to read. */
+       instance_data->button_down =
+           kcalloc(instance_data->device_info->button_count, sizeof(bool),
+                   GFP_KERNEL);
+       if (!instance_data->button_down) {
+               pr_err("%s: Error allocating F19 button state buffer.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       instance_data->button_data_buffer_size =
+           (instance_data->device_info->button_count + 7) / 8;
+       instance_data->button_data_buffer =
+           kcalloc(instance_data->button_data_buffer_size,
+                   sizeof(unsigned char), GFP_KERNEL);
+       if (!instance_data->button_data_buffer) {
+               pr_err("%s: Failed to allocate button data buffer.", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       instance_data->button_map =
+           kcalloc(instance_data->device_info->button_count,
+                   sizeof(unsigned char), GFP_KERNEL);
+       if (!instance_data->button_map) {
+               pr_err("%s: Error allocating F19 button map.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       for (i = 0; i < instance_data->device_info->button_count; i++)
+               instance_data->button_map[i] = BTN_0 + i; /* default values */
+
+       /* Grab the control register info. */
+       retval = init_control_registers(rmifninfo);
+       if (retval) {
+               pr_err("%s: Error %d getting fn19 control register info.\n",
+                      __func__, retval);
+               goto error_exit;
+       }
+
+       return 0;
+
+error_exit:
+       if (instance_data) {
+               kfree(instance_data->button_map);
+               kfree(instance_data->button_data_buffer);
+               kfree(instance_data->button_down);
+               kfree(instance_data->device_info);
+       }
+       kfree(instance_data);
+       return retval;
+}
+EXPORT_SYMBOL(FN_19_detect);
+
+static ssize_t rmi_f19_button_count_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f19_instance_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->device_info->button_count);
+}
+
+static ssize_t rmi_f19_buttonMap_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f19_instance_data *instance_data = fn->rfi->fndata;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < instance_data->device_info->button_count; i++) {
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", instance_data->button_map[i]);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build button map buffer, "
+                               "code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+
+       return total_len;
+}
+
+static ssize_t rmi_f19_buttonMap_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct f19_instance_data *instance_data = fn->rfi->fndata;
+       unsigned int button;
+       int i;
+       int retval = count;
+       int button_count = 0;
+       unsigned char temp_button_map[instance_data->device_info->button_count];
+
+       /* Do validation on the button map data passed in.  Store button
+        * mappings into a temp buffer and then verify button count and
+        * data prior to clearing out old button mappings and storing the
+        * new ones. */
+       for (i = 0; i < instance_data->device_info->button_count && *buf != 0;
+            i++) {
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               sscanf(buf, "%u", &button);
+
+               /* Make sure the key is a valid key */
+               if (button > KEY_MAX) {
+                       dev_err(dev,
+                               "%s: Error - button map for button %d is not a "
+                               "valid value 0x%x.\n",
+                               __func__, i, button);
+                       retval = -EINVAL;
+                       goto err_ret;
+               }
+
+               temp_button_map[i] = button;
+               button_count++;
+
+               /* bump up buf to point to next item to read */
+               while (*buf != 0) {
+                       buf++;
+                       if (*(buf - 1) == ' ')
+                               break;
+               }
+       }
+
+       /* Make sure the button count matches */
+       if (button_count != instance_data->device_info->button_count) {
+               dev_err(dev,
+                   "%s: Error - button map count of %d doesn't match device "
+                    "button count of %d.\n", __func__, button_count,
+                    instance_data->device_info->button_count);
+               retval = -EINVAL;
+               goto err_ret;
+       }
+
+       /* Clear the key bits for the old button map. */
+       for (i = 0; i < button_count; i++)
+               clear_bit(instance_data->button_map[i], fn->input->keybit);
+
+       /* Switch to the new map. */
+       memcpy(instance_data->button_map, temp_button_map,
+              instance_data->device_info->button_count);
+
+       /* Loop through the key map and set the key bit for the new mapping. */
+       for (i = 0; i < button_count; i++)
+               set_bit(instance_data->button_map[i], fn->input->keybit);
+
+err_ret:
+       return retval;
+}
diff --git a/drivers/input/touchscreen/rmi/rmi_f19.h b/drivers/input/touchscreen/rmi/rmi_f19.h
new file mode 100644 (file)
index 0000000..b5964fe
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 header.
+ * Copyright (c) 2007 - 2010, Synaptics Incorporated
+ *
+ * For every RMI4 function that has a data source - like 2D sensors,
+ * buttons, LEDs, GPIOs, etc. - the user will create a new rmi_function_xx.c
+ * file and add these functions to perform the config(), init(), report()
+ * and detect() functionality. The function pointers are then srored under
+ * the RMI function info and these functions will automatically be called by
+ * the global config(), init(), report() and detect() functions that will
+ * loop through all data sources and call the data sources functions using
+ * these functions pointed to by the function ptrs.
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_F19_H)
+#define _RMI_F19_H
+
+/* This is the data read from the F19 query registers.
+ */
+struct rmi_F19_query {
+       bool has_hysteresis_threshold;
+       bool has_sensitivity_adjust;
+       bool configurable;
+       unsigned char button_count;
+};
+
+struct rmi_F19_control {
+       unsigned char button_usage;
+       unsigned char filter_mode;
+       unsigned char *interrupt_enable_registers;
+       unsigned char *single_button_control;
+       unsigned char *sensor_map;
+       unsigned char *single_button_sensitivity;
+       unsigned char global_sensitivity_adjustment;
+       unsigned char global_hysteresis_threshold;
+};
+
+
+void FN_19_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs);
+int FN_19_config(struct rmi_function_info *rmifninfo);
+int FN_19_init(struct rmi_function_device *function_device);
+int FN_19_detect(struct rmi_function_info *rmifninfo);
+/* No attention function for Fn $19 */
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_f34.c b/drivers/input/touchscreen/rmi/rmi_f34.c
new file mode 100644 (file)
index 0000000..55c317e
--- /dev/null
@@ -0,0 +1,558 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $34 support for sensor
+ * firmware reflashing.
+ *
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/sysfs.h>
+#include <linux/math64.h>
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f34.h"
+
+/* data specific to fn $34 that needs to be kept around */
+struct rmi_fn_34_data {
+       unsigned char status;
+       unsigned char cmd;
+       unsigned short bootloaderid;
+       unsigned short blocksize;
+       unsigned short imageblockcount;
+       unsigned short configblockcount;
+};
+
+static ssize_t rmi_fn_34_status_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_cmd_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_cmd_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count);
+
+static ssize_t rmi_fn_34_data_read(struct file *data_file, struct kobject *kobj,
+                                  struct bin_attribute *attributes,
+                                  char *buf, loff_t pos, size_t count);
+
+static ssize_t rmi_fn_34_data_write(struct file *data_file,
+                                   struct kobject *kobj,
+                                   struct bin_attribute *attributes, char *buf,
+                                   loff_t pos, size_t count);
+
+static ssize_t rmi_fn_34_bootloaderid_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf);
+
+static ssize_t rmi_fn_34_bootloaderid_store(struct device *dev,
+                                           struct device_attribute *attr,
+                                           const char *buf, size_t count);
+
+static ssize_t rmi_fn_34_blocksize_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_34_imageblockcount_show(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf);
+
+static ssize_t rmi_fn_34_configblockcount_show(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf);
+
+static struct device_attribute attrs[] = {
+       __ATTR(status, 0444,
+              rmi_fn_34_status_show, rmi_store_error), /* RO attr */
+       /* Also, sysfs will need to have a file set up to distinguish
+        * between commands - like Config write/read, Image write/verify. */
+       __ATTR(cmd, 0666,
+              rmi_fn_34_cmd_show, rmi_fn_34_cmd_store),        /* RW attr */
+       __ATTR(bootloaderid, 0666,
+              rmi_fn_34_bootloaderid_show, rmi_fn_34_bootloaderid_store),
+              /* RW attr */
+       __ATTR(blocksize, 0444,
+              rmi_fn_34_blocksize_show, rmi_store_error),      /* RO attr */
+       __ATTR(imageblockcount, 0444,
+              rmi_fn_34_imageblockcount_show, rmi_store_error), /* RO attr */
+       __ATTR(configblockcount, 0444,
+              rmi_fn_34_configblockcount_show, rmi_store_error) /* RO attr */
+};
+
+struct bin_attribute dev_attr_data = {
+       .attr = {
+                .name = "data",
+                .mode = 0666},
+       .size = 0,
+       .read = rmi_fn_34_data_read,
+       .write = rmi_fn_34_data_write,
+};
+
+/* Helper fn to convert a byte array representing a short in the RMI
+ * endian-ness to a short in the native processor's specific endianness.
+ * We don't use ntohs/htons here because, well, we're not dealing with
+ * a pair of shorts. And casting dest to short* wouldn't work, because
+ * that would imply knowing the byte order of short in the first place.
+ */
+static void batohs(unsigned short *dest, unsigned char *src)
+{
+       *src = dest[1] * 0x100 + dest[0];
+}
+
+/* Helper function to convert a short (in host processor endianess) to
+ * a byte array in the RMI endianess for shorts.  See above comment for
+ * why we dont us htons or something like that.
+ */
+static void hstoba(unsigned char *dest, unsigned short src)
+{
+       dest[0] = src % 0x100;
+       dest[1] = src / 0x100;
+}
+
+/*.
+ * The interrupt handler for Fn $34.
+ */
+void FN_34_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs)
+{
+       unsigned int status;
+       struct rmi_fn_34_data *instance_data = rmifninfo->fndata;
+
+       /* Read the Fn $34 status register to see whether the previous
+        * command executed OK. inform user space - through a sysfs param. */
+       if (rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.data_base_addr + 3,
+                       (unsigned char *)&status, 1)) {
+               pr_err("%s : Could not read status from 0x%x\n", __func__,
+                      rmifninfo->function_descriptor.data_base_addr + 3);
+               status = 0xff;  /* failure */
+       }
+
+       /* set a sysfs value that the user mode can read - only
+        * upper 4 bits are the status. successful is $80, anything
+        * else is failure */
+       instance_data->status = status & 0xf0;
+}
+EXPORT_SYMBOL(FN_34_inthandler);
+
+/* This is a stub for now, and will be fleshed out or removed as the
+ * implementation matures.
+ */
+void FN_34_attention(struct rmi_function_info *rmifninfo)
+{
+
+}
+EXPORT_SYMBOL(FN_34_attention);
+
+/* This is a stub for now, and will be fleshed out or removed as the
+ * implementation matures.
+ */
+int FN_34_config(struct rmi_function_info *rmifninfo)
+{
+       pr_debug("%s: RMI4 function $34 config\n", __func__);
+       return 0;
+}
+EXPORT_SYMBOL(FN_34_config);
+
+int FN_34_init(struct rmi_function_device *function_device)
+{
+       int retval = 0;
+       int attr_count = 0;
+       unsigned char buf[2];
+       struct rmi_function_info *rmifninfo = function_device->rfi;
+       struct rmi_fn_34_data *instance_data;
+
+       pr_debug("%s: RMI4 function $34 init\n", __func__);
+
+       if (rmifninfo->fndata) {
+               /* detect routine should only ever be called once
+                * per rmifninfo. */
+               pr_err("%s: WTF?!? F34 instance data is already present!",
+                      __func__);
+               return -EINVAL;
+       }
+
+       instance_data = kzalloc(sizeof(struct rmi_fn_34_data), GFP_KERNEL);
+       if (!instance_data) {
+               pr_err("%s: Error allocating memory for rmi_fn_34_data.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       rmifninfo->fndata = instance_data;
+
+       /* get the Bootloader ID and Block Size. */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+               rmifninfo->function_descriptor.query_base_addr,
+               buf, ARRAY_SIZE(buf));
+       if (retval) {
+               pr_err("%s : Could not read bootloaderid from 0x%04x\n",
+                      __func__,
+                      rmifninfo->function_descriptor.query_base_addr);
+               goto error_exit;
+       }
+       batohs(&instance_data->bootloaderid, buf);
+
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.query_base_addr + 3,
+                       buf, ARRAY_SIZE(buf));
+       if (retval) {
+               pr_err("%s: Could not read block size from 0x%04x\n",
+                      __func__,
+                      rmifninfo->function_descriptor.query_base_addr + 3);
+               goto error_exit;
+       }
+       batohs(&instance_data->blocksize, buf);
+
+       /* Get firmware image block count and store it in the instance data */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.query_base_addr + 5,
+                       buf, ARRAY_SIZE(buf));
+       if (retval) {
+               pr_err("%s: Could not read image block count from 0x%x\n",
+                      __func__,
+                      rmifninfo->function_descriptor.query_base_addr + 5);
+               goto error_exit;
+       }
+       batohs(&instance_data->imageblockcount, buf);
+
+       /* Get config block count and store it in the instance data */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.query_base_addr + 7,
+                       buf, ARRAY_SIZE(buf));
+       if (retval) {
+               pr_err("%s: Could not read config block count from 0x%x, "
+                       "error=%d.\n", __func__,
+                       rmifninfo->function_descriptor.query_base_addr + 7,
+                       retval);
+               goto error_exit;
+       }
+       batohs(&instance_data->configblockcount, buf);
+
+       /* We need a sysfs file for the image/config block to write or read.
+        * Set up sysfs bin file for binary data block. Since the image is
+        * already in our format there is no need to convert the data for
+        * endianess. */
+       retval = sysfs_create_bin_file(&function_device->dev.kobj,
+                               &dev_attr_data);
+       if (retval < 0) {
+               pr_err
+                   ("%s: Failed to create sysfs file for fn 34 data "
+                    "(error = %d).\n", __func__, retval);
+               retval = -ENODEV;
+               goto error_exit;
+       }
+
+       pr_debug("%s: Creating sysfs files.", __func__);
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&function_device->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       pr_err
+                           ("%s: Failed to create sysfs file for  %s.",
+                            __func__, attrs[attr_count].attr.name);
+                       retval = -ENODEV;
+                       goto error_exit;
+               }
+       }
+
+       return retval;
+
+error_exit:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&function_device->dev.kobj,
+                                 &attrs[attr_count].attr);
+       kfree(instance_data);
+       return retval;
+}
+EXPORT_SYMBOL(FN_34_init);
+
+int FN_34_detect(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+
+       pr_debug("%s: RMI4 function $34 detect\n", __func__);
+       if (rmifninfo->sensor == NULL) {
+               pr_err("%s: NULL sensor passed in!", __func__);
+               return -EINVAL;
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_34_detect);
+
+static ssize_t rmi_fn_34_bootloaderid_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->bootloaderid);
+}
+
+static ssize_t rmi_fn_34_bootloaderid_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf,
+                                       size_t count)
+{
+       int error;
+       unsigned long val;
+       unsigned char data[2];
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       instance_data->bootloaderid = val;
+
+       /* Write the Bootloader ID key data back to the first two Block
+        * Data registers (F34_Flash_Data2.0 and F34_Flash_Data2.1). */
+       hstoba(data, (unsigned short)val);
+       error = rmi_write_multiple(fn->sensor,
+                                  fn->rfi->function_descriptor.data_base_addr,
+                                  data, ARRAY_SIZE(data));
+       if (error) {
+               dev_err(dev, "%s : Could not write bootloader id to 0x%x\n",
+                      __func__, fn->rfi->function_descriptor.data_base_addr);
+               return error;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_34_blocksize_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->blocksize);
+}
+
+static ssize_t rmi_fn_34_imageblockcount_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->imageblockcount);
+}
+
+static ssize_t rmi_fn_34_configblockcount_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->configblockcount);
+}
+
+static ssize_t rmi_fn_34_status_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->status);
+}
+
+static ssize_t rmi_fn_34_cmd_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->cmd);
+}
+
+static ssize_t rmi_fn_34_cmd_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+       unsigned long val;
+       unsigned short baseaddr = fn->rfi->function_descriptor.data_base_addr;
+       int error;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+       if (error)
+               return error;
+
+       instance_data->cmd = val;
+
+       /* Validate command value and (if necessary) write it to the command
+        * register.
+        */
+       switch (instance_data->cmd) {
+       case ENABLE_FLASH_PROG:
+       case ERASE_ALL:
+       case ERASE_CONFIG:
+       case WRITE_FW_BLOCK:
+       case READ_CONFIG_BLOCK:
+       case WRITE_CONFIG_BLOCK:
+               /* Issue a Write Firmware Block ($02) command to the Flash
+                * Command (F34_Flash_Data3, bits 3:0) field. */
+               error = rmi_write_multiple(fn->sensor, baseaddr + 3,
+                                          &instance_data->cmd, 1);
+               /* return one if succeeds */
+               if (error != 1) {
+                       dev_err(dev, "%s: Could not write command 0x%02x "
+                               "to 0x%04x\n", __func__, instance_data->cmd,
+                               baseaddr + 3);
+                       return error;
+               }
+               break;
+       default:
+               dev_dbg(dev, "%s: RMI4 function $34 - "
+                               "unknown command 0x%02lx.\n", __func__, val);
+               count = -EINVAL;
+               break;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_34_data_read(struct file *data_file,
+                               struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+       int error;
+
+       if (count != instance_data->blocksize) {
+               dev_err(dev,
+                       "%s: Incorrect F34 block size %d. Expected size %d.\n",
+                       __func__, count, instance_data->blocksize);
+               return -EINVAL;
+       }
+
+       /* Read the data from flash into buf.  The app layer will be blocked
+        * at reading from the sysfs file.  When we return the count (or
+        * error if we fail) the app will resume. */
+       error = rmi_read_multiple(fn->sensor,
+                       fn->rfi->function_descriptor.data_base_addr + pos,
+                       (unsigned char *)buf, count);
+       if (error) {
+               dev_err(dev, "%s : Could not read data from 0x%llx\n",
+                       __func__,
+                       fn->rfi->function_descriptor.data_base_addr + pos);
+               return error;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_34_data_write(struct file *data_file,
+                               struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_34_data *instance_data = fn->rfi->fndata;
+       unsigned int blocknum;
+       int error;
+       unsigned int remainder;
+       unsigned short baseaddr = fn->rfi->function_descriptor.data_base_addr;
+
+       /* Write the data from buf to flash. The app layer will be
+        * blocked at writing to the sysfs file.  When we return the
+        * count (or error if we fail) the app will resume. */
+
+       if (count != instance_data->blocksize) {
+               dev_err(dev,
+                       "%s: Incorrect F34 block size %d. Expected size %d.\n",
+                       __func__, count, instance_data->blocksize);
+               return -EINVAL;
+       }
+
+       /* Verify that the byte offset is always aligned on a block boundary
+        * and if not return an error.  We can't just use the mod operator %
+        * and do a (pos % instance_data->blocksize) because of a gcc
+        * bug that results in undefined symbols.  So we have to compute
+        * it the hard way.  Grumble. */
+       div_u64_rem(pos, instance_data->blocksize, &remainder);
+       if (remainder) {
+               dev_err(dev,
+                       "%s: Invalid byte offset of %llx leads to invalid "
+                       "block number.\n", __func__, pos);
+               return -EINVAL;
+       }
+
+       /* Compute the block number using the byte offset (pos) and the
+        * block size.  Once again, we can't just do a divide due to a
+        * gcc bug. */
+       blocknum = div_u64(pos, instance_data->blocksize);
+
+       /* Write the block number first */
+       error = rmi_write_multiple(fn->sensor, baseaddr,
+                                  (unsigned char *)&blocknum, 2);
+       /* return one if succeeds */
+       if (error != 1) {
+               dev_err(dev, "%s: Could not write block number to 0x%x\n",
+                       __func__, baseaddr);
+               return error;
+       }
+
+       /* Write the data block - only if the count is non-zero  */
+       if (count) {
+               error = rmi_write_multiple(fn->sensor, baseaddr + 2,
+                                          (unsigned char *)buf, count);
+               /* return one if succeeds */
+               if (error != 1) {
+                       dev_err(dev, "%s: Could not write block data "
+                               "to 0x%x\n", __func__, baseaddr + 2);
+                       return error;
+               }
+       }
+
+       return count;
+}
diff --git a/drivers/input/touchscreen/rmi/rmi_f34.h b/drivers/input/touchscreen/rmi/rmi_f34.h
new file mode 100644 (file)
index 0000000..c9e8b52
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $34 header.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ * There is only one function $34 for each RMI4 sensor. This will be
+ * the function that is used to reflash the firmware and get the
+ * boot loader address and the boot image block size.
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_F34_H)
+#define _RMI_F34_H
+
+/* define fn $34 commands */
+#define WRITE_FW_BLOCK            2
+#define ERASE_ALL                 3
+#define READ_CONFIG_BLOCK         5
+#define WRITE_CONFIG_BLOCK        6
+#define ERASE_CONFIG              7
+#define ENABLE_FLASH_PROG         15
+
+void FN_34_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs);
+int FN_34_config(struct rmi_function_info *rmifninfo);
+int FN_34_init(struct rmi_function_device *function_device);
+int FN_34_detect(struct rmi_function_info *rmifninfo);
+void FN_34_attention(struct rmi_function_info *rmifninfo);
+
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_f54.c b/drivers/input/touchscreen/rmi/rmi_f54.c
new file mode 100644 (file)
index 0000000..246683d
--- /dev/null
@@ -0,0 +1,666 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $54 support for direct
+ * access to low-level capacitance data.
+ *
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/sysfs.h>
+#include <linux/math64.h>
+
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f54.h"
+
+/* modified from F 34, must check for copy-paste nonsense */
+
+
+static ssize_t rmi_fn_54_reporttype_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_reporttype_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+
+static ssize_t rmi_fn_54_cmd_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_cmd_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count);
+
+static ssize_t rmi_fn_54_status_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_data_read(struct file *filp, struct kobject *kobj,
+                                  struct bin_attribute *attributes,
+                                  char *buf, loff_t pos, size_t count);
+
+static ssize_t rmi_fn_54_numrxelectrodes_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_numtxelectrodes_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_control_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_control_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+
+static ssize_t rmi_fn_54_fifoindexlo_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_fifoindexlo_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count);
+
+static ssize_t rmi_fn_54_fifoindexhi_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_54_fifoindexhi_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count);
+
+/* Should probably change name here to something more appropriate */
+static struct device_attribute attrs[] = {
+       __ATTR(reporttype, 0666,
+               rmi_fn_54_reporttype_show, rmi_fn_54_reporttype_store),
+       __ATTR(cmd, 0666,
+               rmi_fn_54_cmd_show, rmi_fn_54_cmd_store),
+       __ATTR(status, 0444,
+               rmi_fn_54_status_show, rmi_store_error),
+       __ATTR(numrxelectrodes, 0444,
+               rmi_fn_54_numrxelectrodes_show, rmi_store_error),
+       __ATTR(numtxelectrodes, 0444,
+               rmi_fn_54_numtxelectrodes_show, rmi_store_error),
+       __ATTR(control, 0666,
+               rmi_fn_54_control_show, rmi_fn_54_control_store),
+       __ATTR(fifoindexlo, 0666,
+               rmi_fn_54_fifoindexlo_show, rmi_fn_54_fifoindexlo_store),
+       __ATTR(fifoindexhi, 0666,
+               rmi_fn_54_fifoindexhi_show, rmi_fn_54_fifoindexhi_store)
+};
+/* Same as above */
+struct bin_attribute dev_rep_data = {
+       .attr = {
+                .name = "repdata",
+                .mode = 0444},
+       .size = 0,
+       .read = rmi_fn_54_data_read,
+};
+
+
+int FN_54_init(struct rmi_function_device *function_device)
+{
+       int retval = 0;
+       int attr_count = 0;
+       unsigned char buf;
+       struct rmi_function_info *rmifninfo = function_device->rfi;
+       struct rmi_fn_54_data *instance_data;
+
+       pr_debug("%s: RMI4 function $54 init\n", __func__);
+
+       if (rmifninfo->fndata) {
+               /* detect routine should only ever be called once
+                * per rmifninfo. */
+               pr_err("%s: WTF?!? F54 instance data is already present!",
+                      __func__);
+               return -EINVAL;
+       }
+
+       instance_data = kzalloc(sizeof(struct rmi_fn_54_data), GFP_KERNEL);
+       if (!instance_data) {
+               pr_err("%s: Error allocating memory for rmi_fn_54_data.\n",
+                      __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+       rmifninfo->fndata = instance_data;
+
+       /* get the Number of Receiver and Transmitter Electrodes. */
+       retval = rmi_read_multiple(rmifninfo->sensor,
+               rmifninfo->function_descriptor.query_base_addr,
+               &buf, 1);
+       if (retval) {
+               pr_err("%s : Could not read NumberOfReceiverElectrodes from 0x%04x\n",
+                      __func__,
+                      rmifninfo->function_descriptor.query_base_addr);
+               goto error_exit;
+       }
+       instance_data->numrxelectrodes = buf;
+
+       retval = rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.query_base_addr + 1,
+                       &buf, 1);
+       if (retval) {
+               pr_err("%s: Could not read NumberOfTransmitterElectrodes from 0x%04x\n",
+                      __func__,
+                      rmifninfo->function_descriptor.query_base_addr + 1);
+               goto error_exit;
+       }
+       instance_data->numtxelectrodes = buf;
+
+       __mutex_init(&instance_data->data_mutex, "data_mutex",
+                    &instance_data->data_key);
+
+       /* We need a sysfs file for the image/config block to write or read.
+        * Set up sysfs bin file for binary data block. Since the image is
+        * already in our format there is no need to convert the data for
+        * endianess. */
+       retval = sysfs_create_bin_file(&function_device->dev.kobj,
+                               &dev_rep_data);
+       if (retval < 0) {
+               pr_err
+                   ("%s: Failed to create sysfs file for fn 54 data "
+                    "(error = %d).\n", __func__, retval);
+               retval = -ENODEV;
+               goto error_exit;
+       }
+
+       pr_debug("%s: Creating sysfs files.", __func__);
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&function_device->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       pr_err
+                           ("%s: Failed to create sysfs file for  %s.",
+                            __func__, attrs[attr_count].attr.name);
+                       retval = -ENODEV;
+                       goto error_exit;
+               }
+       }
+
+       return retval;
+
+error_exit:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&function_device->dev.kobj,
+                                 &attrs[attr_count].attr);
+       kfree(instance_data);
+       return retval;
+}
+EXPORT_SYMBOL(FN_54_init);
+
+
+void FN_54_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs)
+{
+
+       struct rmi_fn_54_data *instance_data = rmifninfo->fndata;
+       int error = 0;
+       char *to_write;
+
+       /* TODO: do something to disable all other interupts : ? */
+       /* TODO: Need to do something for timeout? */
+
+       instance_data->status = 1; /* busy */
+
+       switch (instance_data->reporttype) {
+       case r8bit_image:
+               instance_data->reportsize = instance_data->numrxelectrodes *
+                                       instance_data->numtxelectrodes;
+               break;
+       case r16bit_image:
+       case autoscan:
+               instance_data->reportsize = 2 * instance_data->numrxelectrodes *
+                                       instance_data->numtxelectrodes;
+               break;
+       case trans2trans:
+       case trans2trans_short:
+               instance_data->reportsize = instance_data->numtxelectrodes *
+                                       instance_data->numtxelectrodes;
+               break;
+       case rec2rec:
+               instance_data->reportsize = instance_data->numrxelectrodes *
+                                       instance_data->numrxelectrodes;
+               break;
+       default:
+               instance_data->reportsize = 0;
+               pr_err("%s:Invalid report type. This should never happen.\n",
+                       __func__);
+       }
+       /* We need to ensure the buffer is big enough.
+        * A Buffer size of 0 means that the buffer has not been allocated.
+        */
+       if (instance_data->bufsize < instance_data->reportsize) {
+               mutex_lock(&instance_data->data_mutex);
+               if (instance_data->bufsize > 0)
+                       kfree(instance_data->report_data);
+
+               instance_data->report_data = kzalloc(instance_data->reportsize,
+                                                    GFP_KERNEL);
+               if (!instance_data->report_data) {
+                       pr_err("%s: Error allocating memory for report data.\n",
+                              __func__);
+                       instance_data->status = ENOMEM;
+                       instance_data->bufsize = 0;
+                       mutex_unlock(&instance_data->data_mutex);
+                       return;
+               }
+               instance_data->bufsize = instance_data->reportsize;
+               mutex_unlock(&instance_data->data_mutex);
+       }
+       if (!instance_data->report_data) {
+               pr_err("%s: Error allocating memory for f54 report_data.\n",
+                      __func__);
+               instance_data->status = ENOMEM;
+               return;
+       }
+       pr_err("%s: Stuff is actually running.\n\n Size : %d\n",
+                      __func__, instance_data->reportsize);
+       /* Loop requesting data until we reach the end. */
+
+       to_write = instance_data->report_data;
+
+
+       error = rmi_read_multiple(rmifninfo->sensor,
+               rmifninfo->function_descriptor.data_base_addr + 3,
+               instance_data->report_data,
+               instance_data->reportsize);
+       if (error)
+               pr_err("%s: ERROR F54 data read failed. "
+                       "Code: %d.\n", __func__, error);
+
+       /*for (i = 0; i < instance_data->reportsize; i++) {
+               // attempt to write FIFOData to the next space in the data file.
+               error = rmi_read_multiple(rmifninfo->sensor,
+                       rmifninfo->function_descriptor.data_base_addr + 3,
+                       to_write, 1);
+               *to_write = 'a';
+               pr_info("%d: %c",i, *to_write);
+               if ( error ) {
+                       pr_err("%s: Error while reading data: Error %d\n",
+                              __func__, error);
+                       instance_data->status = error;
+                       // Do some sort of error handling?
+               }
+               to_write++;
+       }*/
+       if (!error)
+               instance_data->status = 0; /* Success */
+       else
+               instance_data->status = error;
+}
+EXPORT_SYMBOL(FN_54_inthandler);
+
+/* This is a stub for now, and will be fleshed out or removed as the
+ * implementation matures.
+ */
+int FN_54_config(struct rmi_function_info *rmifninfo)
+{
+       pr_debug("%s: RMI4 function $54 config\n", __func__);
+       return 0;
+}
+EXPORT_SYMBOL(FN_54_config);
+
+int FN_54_detect(struct rmi_function_info *rmifninfo)
+{
+       int retval = 0;
+
+       pr_debug("%s: RMI4 function $54 detect\n", __func__);
+       if (rmifninfo->sensor == NULL) {
+               pr_err("%s: NULL sensor passed in!", __func__);
+               return -EINVAL;
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(FN_54_detect);
+
+/* SYSFS file show/store functions */
+static ssize_t rmi_fn_54_reporttype_show(struct device *dev,
+                               struct device_attribute *attr, char *buf) {
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->reporttype);
+}
+
+static ssize_t rmi_fn_54_reporttype_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count) {
+       int error, result;
+       unsigned long val;
+       unsigned char data;
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       instance_data->reporttype = (enum Report)val;
+       data = (char)val;
+       /* Write the Report Type back to the first Block
+        * Data registers (F54_AD_Data0). */
+       result = rmi_write_multiple(fn->sensor,
+                       fn->rfi->function_descriptor.data_base_addr, &data, 1);
+       if (result != count) {
+               if (result < 0) {
+                       dev_err(dev, "%s : Could not write report type "
+                               "to 0x%x\n", __func__,
+                               fn->rfi->function_descriptor.data_base_addr);
+               } else {
+                       dev_err(dev, "%s : Unexpected number of lines written "
+                               "to 0x%x\n", __func__,
+                               fn->rfi->function_descriptor.data_base_addr);
+                       dev_err(dev, "Wrote: %d\tExpected:%d\n", result, count);
+               }
+       }
+       return result;
+}
+
+static ssize_t rmi_fn_54_cmd_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->cmd);
+}
+
+static ssize_t rmi_fn_54_cmd_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+       u16 baseaddr = fn->rfi->function_descriptor.command_base_addr;
+       unsigned long val;
+       int error, result;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+       if (error)
+               return error;
+
+       instance_data->cmd = (unsigned char)val;
+
+       /* Validate command value and (if necessary) write it to the command
+        * register.
+        */
+       switch (instance_data->cmd) {
+       case GET_REPORT:
+               /* This starts the report getting process. We calculate the
+                * expcected file size based on the report type, number of
+                * transmitters and receivers, and eventually the fifoindexlo
+                * and fifoindexhi. Currently, the firmware assumes those are
+                * 0 when it gets reports, and I'm not sure exactly how they're
+                * going to eventually effect report sizes, so they're ignored
+                * for now.
+                */
+               switch (instance_data->reporttype) {
+               case r8bit_image:
+               case r16bit_image:
+               case autoscan:
+               case trans2trans:
+               case trans2trans_short:
+               case rec2rec:
+                       break;
+               case trans_open:
+               case rec_open:
+               case high_resistance:
+                       dev_err(dev, "%s : Report type unimplemented\n",
+                               __func__);
+                       return -EINVAL;
+                       break;
+               default:
+                       dev_err(dev, "%s : Report type invalid\n", __func__);
+                       return -EINVAL;
+               }
+       case FORCE_CAL:
+               /* Write the command to the command register */
+               result = rmi_write_multiple(fn->sensor, baseaddr,
+                                           &instance_data->cmd, 1);
+               if (result != count) {
+                       if (result < 0) {
+                               dev_err(dev, "%s : Could not write command "
+                                       "to 0x%x\n", __func__, baseaddr);
+                       } else {
+                               dev_err(dev, "%s : Unexpected number of lines "
+                                       "written to 0x%x\n",
+                                       __func__, baseaddr);
+                               dev_err(dev, "Wrote: %d\tExpected:%d\n",
+                                       result, count);
+                       }
+               }
+               break;
+       default:
+               dev_dbg(dev, "%s: RMI4 function $54 - "
+                               "unknown command 0x%02lx.\n", __func__, val);
+               count = -EINVAL;
+               break;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_54_status_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->status);
+}
+
+static ssize_t rmi_fn_54_numrxelectrodes_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->numrxelectrodes);
+}
+
+static ssize_t rmi_fn_54_numtxelectrodes_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->numtxelectrodes);
+}
+
+static ssize_t rmi_fn_54_control_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->no_auto_cal ? 1 : 0);
+}
+
+static ssize_t rmi_fn_54_control_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       int error, result;
+       unsigned long val;
+       unsigned char data;
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+       u16 ctrlbase = fn->rfi->function_descriptor.control_base_addr;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       /* Write the control back to the control register (F54_AD_Ctrl0)
+        * Ignores everything but bit 0 */
+       data = (unsigned char)(val & 0x01); /* bit mask for lowest bit */
+       instance_data->no_auto_cal = (data == (unsigned char)0x01);
+       result = rmi_write_multiple(fn->sensor, ctrlbase, &data, 1);
+       if (result != count) {
+               if (result < 0) {
+                       dev_err(dev, "%s : Could not write control to 0x%x\n",
+                              __func__, ctrlbase);
+               } else {
+                       dev_err(dev, "%s : Unexpected number of lines written "
+                               "to 0x%x\n", __func__, ctrlbase);
+                       dev_err(dev, "Wrote: %d\tExpected:%d\n", result, count);
+               }
+       }
+       return result;
+}
+
+static ssize_t rmi_fn_54_fifoindexlo_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       /* Might want to read from device */
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->fifoindexlo);
+}
+
+static ssize_t rmi_fn_54_fifoindexlo_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       int error, result;
+       unsigned long val;
+       unsigned char data;
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+       u16 database = fn->rfi->function_descriptor.data_base_addr;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       instance_data->fifoindexlo = (unsigned char)val;
+
+       /* Write the FIFOIndexLo back to the
+        * Data register (F54_AD_Data1). */
+       /* hstoba(data, (unsigned short)val); Don't need this */
+       data = (unsigned char)val;
+       result = rmi_write_multiple(fn->sensor, database + 1, &data, 1);
+       if (result != count) {
+               if (result < 0) {
+                       dev_err(dev, "%s : Could not write FIFOIndexLo "
+                               "to 0x%x\n", __func__, database + 1);
+               } else {
+                       dev_err(dev, "%s : Unexpected number of lines written "
+                               "to 0x%x\n", __func__, database + 1);
+                       dev_err(dev, "Wrote: %d\tExpected:%d\n", result, count);
+               }
+       }
+       return result;
+}
+
+static ssize_t rmi_fn_54_fifoindexhi_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       /* Might want to read from device */
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->fifoindexhi);
+}
+
+static ssize_t rmi_fn_54_fifoindexhi_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       int error, result;
+       unsigned long val;
+       unsigned char data;
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+       u16 database = fn->rfi->function_descriptor.data_base_addr;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error; /* Should this be -error? */
+       instance_data->fifoindexhi = (unsigned char)val;
+
+       /* Write the FIFOIndexLo back to the
+        * Data register (F54_AD_Data2). */
+       /* hstoba(data, (unsigned short)val); Don't need this */
+       data = (unsigned char)val;
+       result =
+           rmi_write_multiple(fn->sensor, database + 2, &data, 1);
+       if (result != count) {
+               if (result < 0) {
+                       dev_err(dev, "%s : Could not write FIFOIndexHi to "
+                               "0x%x\n", __func__, database + 2);
+               } else {
+                       dev_err(dev, "%s : Unexpected number of lines written "
+                               " to 0x%x\n", __func__, database + 2);
+                       dev_err(dev, "Wrote: %d\tExpected:%d\n", result, count);
+               }
+       }
+       return result;
+}
+
+/* Provide access to last report */
+
+static ssize_t rmi_fn_54_data_read(struct file *filp, struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct rmi_function_device *fn = dev_get_drvdata(dev);
+       struct rmi_fn_54_data *instance_data = fn->rfi->fndata;
+
+       dev_dbg(dev, "%s: Trying to read data. count: %d pos: %ld\n",
+               __func__, count, (long)pos);
+       /* May run into issues here is a new report type is set before reading
+        * the old data. MAy need to keep track of 2. */
+       if (count < instance_data->reportsize) {
+               dev_err(dev,
+                       "%s: Incorrect F54 report size %d. Expected size %d.\n",
+                       __func__, count, instance_data->reportsize);
+               return -EINVAL;
+       }
+
+       /* Copy data from instance_data to buffer */
+       mutex_lock(&instance_data->data_mutex);
+       memcpy(buf, instance_data->report_data, instance_data->reportsize);
+       mutex_unlock(&instance_data->data_mutex);
+       dev_info(dev, "%s: Presumably successful.", __func__);
+
+       return instance_data->reportsize;
+}
diff --git a/drivers/input/touchscreen/rmi/rmi_f54.h b/drivers/input/touchscreen/rmi/rmi_f54.h
new file mode 100644 (file)
index 0000000..8ad43c9
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $54 header.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ * TODO: Description here
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_F54_H)
+#define _RMI_F54_H
+
+/* define fn $54 commands */
+#define GET_REPORT                1
+#define FORCE_CAL                 2
+
+/* define report types */
+enum Report {
+       /* The numbering should follow automatically, here for clarity */
+       reserved = 0,
+       r8bit_image = 1,
+       r16bit_image = 2,
+       autoscan = 3,
+       trans2trans = 4,
+       trans2trans_short = 5,
+       trans_open = 6,
+       rec2rec = 7,
+       rec_open = 8,
+       high_resistance = 9
+};
+
+/* data specific to fn $54 that needs to be kept around */
+struct rmi_fn_54_data {
+       unsigned char cmd;
+       enum Report reporttype;
+       unsigned char fifoindexlo;
+       unsigned char fifoindexhi;
+       unsigned char numrxelectrodes;
+       unsigned char numtxelectrodes;
+       unsigned char status;
+       bool no_auto_cal;
+       /* May need to do something to make sure this reflects what is
+        * currently in data. */
+       unsigned int reportsize;
+       unsigned char *report_data;
+       unsigned int bufsize;
+       struct mutex data_mutex;
+       struct lock_class_key data_key;
+};
+
+
+
+void FN_54_inthandler(struct rmi_function_info *rmifninfo,
+                     unsigned int asserted_IRQs);
+int FN_54_config(struct rmi_function_info *rmifninfo);
+int FN_54_init(struct rmi_function_device *function_device);
+int FN_54_detect(struct rmi_function_info *rmifninfo);
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_function.c b/drivers/input/touchscreen/rmi/rmi_function.c
new file mode 100644 (file)
index 0000000..a9737f3
--- /dev/null
@@ -0,0 +1,312 @@
+/**
+ * Synaptics Register Mapped Interface (RMI4) - RMI Function Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+
+#include "rmi_drvr.h"
+#include "rmi_function.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_f01.h"
+#include "rmi_f05.h"
+#include "rmi_f11.h"
+#include "rmi_f19.h"
+#include "rmi_f34.h"
+#include "rmi_f54.h"
+
+
+#define FUNCTION_NAME_SIZE 10
+
+static int rmi_function_suspendable(struct rmi_function_info *rmifninfo);
+
+
+/* NOTE: Developer - add in any new RMI4 fn data info - function number
+ * and ptrs to report, config, init and detect functions.  This data is
+ * used to point to the functions that need to be called to config, init,
+ * detect and report data for the new RMI4 function. Refer to the RMI4
+ * specification for information on RMI4 functions.
+ */
+/* TODO: This will eventually be built dynamically, as individual function
+ * implementations registered.  For now, though we create it statically. */
+static struct rmi_function_ops supported_functions[] = {
+       /* Fn $01 - device control */
+       {
+               .function_number = RMI_F01_INDEX,
+               .inthandler = FN_01_inthandler,
+               .config = FN_01_config,
+               .init = FN_01_init,
+               .detect = FN_01_detect,
+               .attention = FN_01_attention,
+               .suspend = FN_01_suspend,
+               .resume = FN_01_resume,
+               .suspendable = rmi_function_suspendable},
+       /* Fn $05 - analog report */
+       {
+               .function_number = RMI_F05_INDEX,
+               .inthandler = FN_05_inthandler,
+               .config = FN_05_config,
+               .init = FN_05_init,
+               .detect = FN_05_detect,
+               .attention = NULL,
+               .suspend = NULL,
+               .resume = NULL,
+               .suspendable = rmi_function_suspendable},
+        /* Fn $11 - 2D sensing */
+        {
+                .function_number = RMI_F11_INDEX,
+                .inthandler = FN_11_inthandler,
+                .config = FN_11_config,
+                .init = FN_11_init,
+                .detect = FN_11_detect,
+                .attention = NULL,
+                .suspend = NULL,
+                .resume = NULL,
+                .suspendable = rmi_function_suspendable},
+       /* Fn $19 - buttons */
+       {
+               .function_number = RMI_F19_INDEX,
+               .inthandler = FN_19_inthandler,
+               .config = FN_19_config,
+               .init = FN_19_init,
+               .detect = FN_19_detect,
+               .attention = NULL,
+               .suspend = NULL,
+               .resume = NULL,
+               .suspendable = rmi_function_suspendable},
+       /* Fn $1a - buttons */
+       {
+               .function_number = 0x1a,
+               .inthandler = FN_19_inthandler,
+               .config = FN_19_config,
+               .init = FN_19_init,
+               .detect = FN_19_detect,
+               .attention = NULL,
+               .suspend = NULL,
+               .resume = NULL,
+               .suspendable = rmi_function_suspendable},
+       /* Fn $34 - firmware reflash */
+       {
+               .function_number = RMI_F34_INDEX,
+               .inthandler = FN_34_inthandler,
+               .config = FN_34_config,
+               .init = FN_34_init,
+               .detect = FN_34_detect,
+               .attention = FN_34_attention,
+               .suspend = NULL,
+               .resume = NULL,
+               .suspendable = rmi_function_suspendable},
+       /* Fn $54 - diagnostics. */
+       {
+               .function_number = RMI_F54_INDEX,
+               .inthandler = FN_54_inthandler,
+               .config = FN_54_config,
+               .init = FN_54_init,
+               .detect = FN_54_detect,
+               .attention = NULL,
+               .suspend = NULL,
+               .resume = NULL,
+               .suspendable = rmi_function_suspendable},
+};
+
+/* This function is here to provide a way for external modules to access the
+ * functions list.  It will try to find a matching function base on the passed
+ * in RMI4 function number and return  the pointer to the struct rmi_functions
+ * if a match is found or NULL if not found.
+ */
+struct rmi_function_ops *rmi_find_function(int function_number)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(supported_functions); i++) {
+               if (function_number == supported_functions[i].function_number)
+                       return &supported_functions[i];
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL(rmi_find_function);
+
+static int rmi_function_suspendable(struct rmi_function_info *rmifninfo)
+{
+       return 1;
+}
+
+static void rmi_function_config(struct rmi_function_device *function)
+{
+       pr_debug("%s: rmi_function_config", __func__);
+}
+
+/* Just a stub for now.
+ */
+static int rmi_function_suspend(struct device *dev, pm_message_t state)
+{
+       pr_info("%s: function suspend called.", __func__);
+       return 0;
+}
+
+/* Just a stub for now.
+ */
+static int rmi_function_resume(struct device *dev)
+{
+       pr_info("%s: function resume called.", __func__);
+       return 0;
+}
+
+int rmi_function_register_driver(struct rmi_function_driver *drv,
+                               int function_number)
+{
+       int retval = 0;
+       char *driver_name;
+
+       pr_info("%s: Registering function driver for F%02x.\n", __func__,
+               function_number);
+
+
+       /* Create a function device and function driver for this Fn */
+       driver_name = kzalloc(FUNCTION_NAME_SIZE, GFP_KERNEL);
+       if (!driver_name) {
+               pr_err("%s: Error allocating memory for "
+                    "rmi_function_driver name.", __func__);
+               return -ENOMEM;
+       }
+       snprintf(driver_name, FUNCTION_NAME_SIZE, "fn%02x", function_number);
+
+       drv->drv.name = driver_name;
+       drv->module = drv->drv.owner;
+
+       drv->drv.suspend = rmi_function_suspend;
+       drv->drv.resume = rmi_function_resume;
+
+       /* register the sensor driver */
+       retval = driver_register(&drv->drv);
+       if (retval) {
+               pr_err("%s: Failed driver_register %d\n", __func__, retval);
+               drv->drv.name = NULL;
+               kfree(driver_name);
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL(rmi_function_register_driver);
+
+void rmi_function_unregister_driver(struct rmi_function_driver *drv)
+{
+       char *driver_name =  (char *) drv->drv.name;
+
+       pr_info("%s: Unregistering function driver.\n", __func__);
+
+       /* TODO: Unregister the devices first. */
+       driver_unregister(&drv->drv);
+       kfree(driver_name);
+}
+EXPORT_SYMBOL(rmi_function_unregister_driver);
+
+int rmi_function_register_device(struct rmi_function_device *function_device,
+                                int fnNumber)
+{
+       struct input_dev *input;
+       int retval = 0;
+
+       pr_info("%s: Registering function device for F%02x.\n", __func__,
+               fnNumber);
+
+       /* make name - fn11, fn19, etc. */
+       dev_set_name(&function_device->dev, "%sfn%02x",
+                    function_device->sensor->drv.name, fnNumber);
+       dev_set_drvdata(&function_device->dev, function_device);
+       retval = device_register(&function_device->dev);
+       if (retval) {
+               pr_err("%s:  Failed device_register for function device.\n",
+                      __func__);
+               return retval;
+       }
+
+       input = input_allocate_device();
+       if (input == NULL) {
+               pr_err("%s:  Failed to allocate memory for a "
+                      "new input device.\n", __func__);
+               retval = -ENOMEM;
+               goto error_exit;
+       }
+
+       input->name = dev_name(&function_device->dev);
+       input->phys = "rmi_function";
+       function_device->input = input;
+
+       /* init any input specific params for this function */
+       function_device->rmi_funcs->init(function_device);
+
+       retval = input_register_device(input);
+       if (retval) {
+               pr_err("%s:  Failed input_register_device.\n", __func__);
+               goto error_exit;
+       }
+
+       rmi_function_config(function_device);
+
+       return retval;
+
+error_exit:
+       kfree(input);
+       return retval;
+}
+EXPORT_SYMBOL(rmi_function_register_device);
+
+void rmi_function_unregister_device(struct rmi_function_device *dev)
+{
+       pr_info("%s: Unregistering function device.n", __func__);
+
+       input_unregister_device(dev->input);
+       device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(rmi_function_unregister_device);
+
+static int __init rmi_function_init(void)
+{
+       pr_debug("%s: RMI Function Init\n", __func__);
+
+       return 0;
+}
+
+static void __exit rmi_function_exit(void)
+{
+       pr_debug("%s: RMI Function Exit\n", __func__);
+}
+
+module_init(rmi_function_init);
+module_exit(rmi_function_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Function Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi/rmi_function.h b/drivers/input/touchscreen/rmi/rmi_function.h
new file mode 100644 (file)
index 0000000..18e4277
--- /dev/null
@@ -0,0 +1,190 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function Device Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_FUNCTION_H)
+#define _RMI_FUNCTION_H
+
+#include <linux/input.h>
+#include <linux/device.h>
+/* For each function present on the RMI device, we need to get the RMI4 Function
+ * Descriptor info from the Page Descriptor Table. This will give us the
+ * addresses for Query, Command, Control, Data and the Source Count (number
+ * of sources for this function) and the function id.
+ * This version contains the full addresses, needed in the case of multiple
+ * pages with PDT's on them.
+ */
+struct rmi_function_descriptor_short {
+       unsigned short query_base_addr;
+       unsigned short command_base_addr;
+       unsigned short control_base_addr;
+       unsigned short data_base_addr;
+       unsigned char interrupt_source_count;
+       unsigned char function_number;
+};
+/* For each function present on the RMI device, there will be a corresponding
+ * entry in the functions list of the rmi_sensor_driver structure.  This entry
+ * gives information about the number of data sources and the number of data
+ * registers associated with the function.
+ */
+struct rmi_function_info {
+       /* The sensor this function belongs to.
+        */
+       struct rmi_sensor_driver *sensor;
+
+       /* A device associated with this function.
+        */
+       struct rmi_function_device *function_device;
+
+       unsigned char function_number;
+
+       /* This is the number of data sources associated with the function. */
+       unsigned char num_data_sources;
+
+       /* This is the interrupt register and mask - needed for enabling the
+        *  interrupts and for checking what source had caused the attention
+        * line interrupt.
+        */
+       unsigned char interrupt_register;
+       unsigned char interrupt_mask;
+
+       /* This is the RMI function descriptor associated with this function.
+        *  It contains the Base addresses for the functions query, command,
+        *  control, and data registers. It includes the page in the addresses.
+        */
+       struct rmi_function_descriptor_short function_descriptor;
+
+       /* pointer to data specific to a functions implementation. */
+       void *fndata;
+
+       /* A list of the function information.
+        *  This list uses the standard kernel linked list implementation.
+        *  Documentation on on how to use it can be found at
+        *  http://isis.poly.edu/kulesh/stuff/src/klist/.
+        */
+       struct list_head link;
+};
+
+/* This struct is for creating a list of RMI4 functions that have data sources
+associated with them. This is to facilitate adding new support for other
+data sources besides 2D sensors.
+To add a new data source support, the developer will create a new file
+and add these 4 functions below with FN$## in front of the names - where
+## is the hex number for the function taken from the RMI4 specification.
+
+The function number will be associated with this and later will be used to
+match the RMI4 function to the 4 functions for that RMI4 function number.
+The user will also have to add code that adds the new rmi_functions item
+to the global list of RMI4 functions and stores the pointers to the 4
+functions in the function pointers.
+ */
+struct rmi_function_ops {
+       unsigned char function_number;
+
+       /* Pointers to function specific functions for interruptHandler,
+        * config, init, detect and attention. These ptrs. need to be filled
+        * in for every RMI4 function that has data source(s) associated with
+        * it - like fn $11 (2D sensors), fn $19 (buttons), etc. Each RMI4
+        * function that has data sources will be added into a list that is
+        * used to match the function number against the number stored here.
+        *
+        * The sensor implementation will call this whenever and IRQ is
+        * dispatched that this function is interested in.
+        */
+       void (*inthandler) (struct rmi_function_info *rfi,
+                           unsigned int asserted_IRQs);
+
+       int (*config) (struct rmi_function_info *rmifninfo);
+       int (*init) (struct rmi_function_device *function_device);
+       int (*detect) (struct rmi_function_info *rmifninfo);
+       /* If this is non-null, the sensor implementation will call this
+        * whenever the ATTN line is asserted.
+        */
+       void (*attention) (struct rmi_function_info *rmifninfo);
+       /**
+        *  suspend/resume provided from each function
+        */
+       int (*suspend) (struct rmi_function_info *rmifninfo);
+       void (*resume) (struct rmi_function_info *rmifninfo);
+       /**
+        *  suspendable
+        *  return zero if the function cannot be suspended at the moment
+        *  nonzero if the function can be suspended
+        */
+       int (*suspendable)(struct rmi_function_info *rmifninfo);
+};
+
+struct rmi_function_ops *rmi_find_function(int function_number);
+int rmi_functions_init(struct input_dev *inputdev);
+
+struct rmi_function_driver {
+       struct module *module;
+       struct device_driver drv;
+
+       /* Probe Function
+        *  This function is called to give the function driver layer an
+        *  opportunity to claim an RMI function.
+        */
+       int (*probe) (struct rmi_function_driver *function);
+       /* Config Function
+        *  This function is called after a successful probe.  It gives the
+        *  function driver an opportunity to query and/or configure an RMI
+        *  function before data starts flowing.
+        */
+       void (*config) (struct rmi_function_driver *function);
+
+       unsigned short query_base_address;
+       unsigned short control_base_address;
+       unsigned short command_base_address;
+       unsigned short data_base_address;
+       /* offset from start of interrupt registers */
+       unsigned int interrupt_register_offset;
+       unsigned int interrupt_mask;
+
+       /* Pointer to the corresponding phys driver info for this sensor.
+        * The phys driver has the pointers to read, write, etc.  Probably
+        * don't need it here - used down in bus driver and sensor driver. */
+       struct rmi_phys_driver *rpd;
+
+       struct list_head function_drivers;
+};
+
+struct rmi_function_device {
+       /*TODO: function driver should be removed if/when we don't need it.*/
+       /*struct rmi_function_driver *function;*/
+       struct device dev;
+       struct input_dev *input;
+       /* need this to be bound to phys driver layer */
+       struct rmi_sensor_driver *sensor;
+
+       /* The function ptrs to the config, init, detect and
+        * report functions for this rmi function device. */
+       struct rmi_function_ops *rmi_funcs;
+       struct rmi_function_info *rfi;
+       struct list_head functions;     /* link functions into list */
+};
+
+int rmi_function_register_device(struct rmi_function_device *dev,
+                                int function_number);
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_i2c.c b/drivers/input/touchscreen/rmi/rmi_i2c.c
new file mode 100644 (file)
index 0000000..ec25b18
--- /dev/null
@@ -0,0 +1,713 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) I2C Physical Layer Driver.
+ * Copyright (c) 2007-2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+/* #define DEBUG 1 */
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/rmi_i2c.h>
+#include "rmi_drvr.h"
+#include "rmi_sensor.h"
+
+#define DRIVER_NAME "rmi4_ts"
+#define DEVICE_NAME "rmi4_ts"
+
+#define COMM_DEBUG  0          /* Set to 1 to dump transfers. */
+#define PAGE_SELECT_REGISTER   0xFF
+
+static const struct i2c_device_id rmi_i2c_id_table[] = {
+       {"synaptics_3202", 0},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, rmi_i2c_id_table);
+
+/*
+ * This is the data kept on a per instance (client) basis.  This data is
+ * always accessible by using the container_of() macro of the various elements
+ * inside.
+ */
+struct instance_data {
+       int instance_no;
+       int irq;
+       int attn_polarity;
+       int attn_gpio;
+       int enabled;
+       struct rmi_phys_driver rmiphysdrvr;
+       struct i2c_client *i2cclient;   /* pointer to client for later use in
+                                          read, write, read_multiple, etc. */
+       struct mutex page_mutex;
+       struct lock_class_key page_key;
+       int page;
+};
+
+static irqreturn_t i2c_attn_isr(int irq, void *info);
+
+/*
+ * RMI devices have 16-bit addressing, but some of the physical
+ * implementations (like SMBus) only have 8-bit addressing.  So RMI implements
+ * a page address at 0xff of every page so we can reliable page addresses
+ * every 256 registers.  This function sets the page.
+ *
+ * The page_mutex lock must be held when this function is entered.
+ *
+ * param[in] id - The pointer to the instance_data struct
+ * param[in] page - The new page address.
+ * returns zero on success, non-zero on failure.
+ */
+/* Writing to page select is giving errors in some configurations.  It's
+ * not needed for basic operation [see note], so we've turned it off for the
+ * moment. Once we figure out why this happening (is it a bug in our code? or
+ * in some I2C chips?  or maybe in the driver for some chips?) we'll either
+ * turn this opperation back on, move the choice to platform data, or
+ * determine whether to use it based on I2C driver capability).
+ *
+ * [NOTE: The current driver feature set doesn't require us to access
+ * addresses outside of the first page, so we're OK for the time being.
+ * Obviously this must be remedied before implementing the more advanced
+ * features that are in the pipeline.]
+ */
+#if    defined(USE_PAGESELECT)
+int rmi_set_page(struct instance_data *instance_data, unsigned int page)
+{
+       char txbuf[2] = {PAGE_SELECT_REGISTER, page};
+       int retval;
+
+#if    COMM_DEBUG
+       dev_info(&instance_data->i2cclient->dev,
+                "%s: Set page to 0x%02X.", __func__, page);
+#endif
+
+       retval = i2c_master_send(instance_data->i2cclient,
+                               txbuf, ARRAY_SIZE(txbuf));
+       if (retval != ARRAY_SIZE(txbuf)) {
+               dev_err(&instance_data->i2cclient->dev,
+                       "%s: Set page failed: %d.", __func__, retval);
+       } else {
+               retval = 0;
+               instance_data->page = page;
+       }
+       return retval;
+}
+#else
+int rmi_set_page(struct instance_data *instance_data, unsigned int page)
+{
+       return 0;
+}
+#endif
+
+/*
+ * Same as rmi_i2c_read, except that multiple bytes are allowed to be read.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the data read.
+ * param[out] valp - Pointer to the buffer where the data will be stored.  This
+ *     buffer must be at least size bytes long.
+ * param[in] size - The number of bytes to be read.
+ * returns zero upon success (with the byte read in valp), non-zero upon error.
+ *
+ */
+static int rmi_i2c_read_multiple(struct rmi_phys_driver *physdrvr,
+                               unsigned short address,
+                               char *valp, int size)
+{
+       struct instance_data *instance_data =
+           container_of(physdrvr, struct instance_data, rmiphysdrvr);
+       char txbuf[1] = {address & 0xff};
+       int retval = 0;
+       int retry_count = 0;
+
+#if    COMM_DEBUG
+       dev_info(&instance_data->i2cclient->dev, "%s: Read %d bytes at 0x%04x",
+                __func__, size, address);
+#endif
+
+       /* Can't have anyone else changing the page behind our backs */
+       mutex_lock(&instance_data->page_mutex);
+
+       if (((address >> 8) & 0xff) != instance_data->page) {
+               /* Switch pages */
+               retval = rmi_set_page(instance_data, ((address >> 8) & 0xff));
+               if (retval)
+                       goto exit;
+       }
+
+retry:
+       physdrvr->tx_count++;
+       physdrvr->tx_bytes += ARRAY_SIZE(txbuf);
+       retval = i2c_master_send(instance_data->i2cclient,
+                                txbuf, ARRAY_SIZE(txbuf));
+       if (retval != 1) {
+               dev_err(&instance_data->i2cclient->dev, "%s: Write fail: %d\n",
+                       __func__, retval);
+               physdrvr->tx_errors++;
+               goto exit;
+       }
+
+       physdrvr->rx_count++;
+       physdrvr->rx_bytes += size;
+       retval = i2c_master_recv(instance_data->i2cclient, valp, size);
+
+       if (retval != size) {
+               physdrvr->rx_errors++;
+               if (++retry_count == 5) {
+                       dev_err(&instance_data->i2cclient->dev,
+                               "%s: Read of 0x%04x size %d fail: %d\n",
+                               __func__, address, size, retval);
+               } else {
+                       mdelay(10);
+                       rmi_set_page(instance_data, ((address >> 8) & 0xff));
+                       goto retry;
+               }
+       } else {
+               retval = 0;
+       }
+
+exit:
+       mutex_unlock(&instance_data->page_mutex);
+       return retval;
+}
+
+/*
+ * Read a single register through i2c.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the data read.
+ * param[out] valp - Pointer to the buffer where the data will be stored.
+ * returns zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_i2c_read(struct rmi_phys_driver *physdrvr, unsigned short address,
+            char *valp)
+{
+       return rmi_i2c_read_multiple(physdrvr, address, valp, 1);
+}
+
+/*
+ * Write multiple registers.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the write.
+ * param[in] valp - A pointer to a buffer containing the data to be written.
+ * param[in] size - The number of bytes to write.
+ * returns one upon success, something else upon error.
+ */
+static int
+rmi_i2c_write_multiple(struct rmi_phys_driver *physdrvr, unsigned short address,
+                      char *valp, int size)
+{
+       struct instance_data *instance_data =
+           container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+       unsigned char txbuf[size+1];
+       int retval = 0;
+
+       memcpy(txbuf+1, valp, size);
+
+       /* Can't have anyone else changing the page behind our backs */
+       mutex_lock(&instance_data->page_mutex);
+
+       if (((address >> 8) & 0xff) != instance_data->page) {
+               /* Switch pages */
+               retval = rmi_set_page(instance_data, ((address >> 8) & 0xff));
+               if (retval) {
+                       /* error occurs we change return value to -1 */
+                       retval = -1;
+                       goto exit;
+               }
+       }
+
+       txbuf[0] = address & 0xff;      /* put the address in the first byte */
+       retval = i2c_master_send(instance_data->i2cclient,
+                               txbuf, ARRAY_SIZE(txbuf));
+       physdrvr->tx_count++;
+       physdrvr->tx_bytes += ARRAY_SIZE(txbuf);
+
+       /* TODO: Add in retry on writes only in certain error return values */
+       if (retval != ARRAY_SIZE(txbuf)) {
+               dev_err(&instance_data->i2cclient->dev, "%s: Write fail: %d\n",
+                       __func__, retval);
+               physdrvr->tx_errors++;
+               /* error occurs we change return value to -2 */
+               retval = -2;
+               goto exit;
+       } else
+               retval = 1; /* return one if succeeds */
+
+exit:
+       mutex_unlock(&instance_data->page_mutex);
+       return retval;
+}
+
+/*
+ * Write a single register through i2c.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver structnew file (copy)
+ * param[in] address - The address at which to start the write.
+ * param[in] data - The data to be written.
+ * returns one upon success, something else upon error.
+ */
+static int
+rmi_i2c_write(struct rmi_phys_driver *physdrvr, unsigned short address,
+             char data)
+{
+       return rmi_i2c_write_multiple(physdrvr, address, &data, 1);
+}
+
+/*
+ * This is the Interrupt Service Routine.  It just notifies the application
+ * layer that attention is required.
+ */
+static irqreturn_t i2c_attn_isr(int irq, void *info)
+{
+       struct instance_data *instance_data = info;
+
+       disable_irq_nosync(instance_data->irq);
+       instance_data->rmiphysdrvr.attn_count++;
+
+       if (instance_data->rmiphysdrvr.attention &&
+                       (gpio_get_value(instance_data->attn_gpio) ==
+                       instance_data->attn_polarity)) {
+               instance_data->rmiphysdrvr.attention(
+                       &instance_data->rmiphysdrvr);
+       } else {
+               enable_irq(instance_data->irq);
+       }
+
+       return IRQ_HANDLED;
+}
+
+
+static int
+acquire_attn_irq(struct instance_data *instance_data)
+{
+       int retval;
+
+       unsigned long irq_type = IRQ_TYPE_EDGE_FALLING;
+       retval = request_irq(instance_data->irq, i2c_attn_isr,
+                       irq_type, "rmi_i2c", instance_data);
+       if (retval)
+               return retval;
+
+       dev_dbg(&instance_data->rmiphysdrvr.sensor->sensor_device->dev,
+               "got ATTN irq.\n");
+
+       /*
+        * For some reason if we setup as level trigger, and execute
+        * 'instance_data->rmiphysdrvr.atten',
+        * there will be no more IRQ triggered.
+        * On the contrary, if we setup as edge trigger, we have to execute
+        * 'instance_data->rmiphysdrvr.atten'.
+        * Or, we won't receive any IRQ.
+        *
+        */
+       if ((irq_type & IRQ_TYPE_EDGE_BOTH) != 0)
+               if (instance_data->attn_gpio &&
+                       gpio_get_value(instance_data->attn_gpio) ==
+                       instance_data->attn_polarity &&
+                       instance_data->rmiphysdrvr.attention) {
+
+                       disable_irq(instance_data->irq);
+                       instance_data->rmiphysdrvr.attention(
+                                       &instance_data->rmiphysdrvr);
+               }
+
+       return retval;
+}
+
+/* Specify the routine that will be called when attention is asserted.
+ */
+static void set_attn_handler (struct rmi_phys_driver *physdrvr,
+       void (*attention) (struct rmi_phys_driver *physdrvr))
+{
+       struct instance_data *instance_data =
+               container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+       physdrvr->attention = attention;
+       if (instance_data->attn_gpio &&
+                       gpio_get_value(instance_data->attn_gpio) ==
+                       instance_data->attn_polarity &&
+                       instance_data->rmiphysdrvr.attention) {
+               disable_irq(instance_data->irq);
+               instance_data->rmiphysdrvr.attention(
+                       &instance_data->rmiphysdrvr);
+       }
+}
+
+
+static void release_attn_irq(struct rmi_phys_driver *physdrvr)
+{
+       struct instance_data *instance_data =
+       container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+       dev_info(&physdrvr->sensor->sensor_device->dev,
+                "Releasing ATTN irq.\n");
+       disable_irq(instance_data->irq);
+       free_irq(instance_data->irq, instance_data);
+}
+
+
+static int
+enable_device(struct rmi_phys_driver *physdrvr)
+{
+       int retval = 0;
+       struct instance_data *instance_data =
+               container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+       if (instance_data->enabled)
+               return 0;
+
+       retval = acquire_attn_irq(instance_data);
+       if (retval)
+               goto error_exit;
+       instance_data->enabled = true;
+       dev_dbg(&physdrvr->sensor->sensor_device->dev,
+               "Physical device enabled.\n");
+       return 0;
+
+error_exit:
+       dev_err(&physdrvr->sensor->sensor_device->dev,
+               "Failed to enable physical device.  Code=%d.\n", retval);
+       return retval;
+}
+
+
+static void
+disable_device(struct rmi_phys_driver *physdrvr)
+{
+       struct instance_data *instance_data =
+       container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+       if (!instance_data->enabled)
+               return;
+
+       release_attn_irq(physdrvr);
+       dev_dbg(&physdrvr->sensor->sensor_device->dev,
+               "Physical device disabled.\n");
+       instance_data->enabled = false;
+}
+
+/* The Driver probe function - will allocate and initialize the instance
+ * data and request the irq and set the instance data as the clients
+ * platform data then register the physical driver which will do a scan of
+ * the RMI4 Physical Device Table and enumerate any RMI4 functions that
+ * have data sources associated with them.
+ */
+static int
+rmi_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)
+{
+       struct instance_data *instance_data;
+       int retval = 0;
+       struct rmi_i2c_platformdata *platformdata;
+       struct rmi_sensordata *sensordata;
+
+       if (client == NULL) {
+               pr_err("%s: Invalid NULL client received.", __func__);
+               return -EINVAL;
+       }
+
+       platformdata = client->dev.platform_data;
+       if (platformdata == NULL) {
+               dev_err(&client->dev, "%s: CONFIGURATION ERROR - "
+               "platform data is NULL.\n", __func__);
+               retval = -EINVAL;
+       }
+       sensordata = platformdata->sensordata;
+
+       dev_dbg(&client->dev, "%s: Probing i2c RMI device, addr: 0x%02x",
+                 __func__, client->addr);
+
+       /* Allocate and initialize the instance data for this client */
+       instance_data = kzalloc(sizeof(*instance_data), GFP_KERNEL);
+       if (!instance_data) {
+               dev_err(&client->dev,
+                       "%s: Failed to allocate instance_data.\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       __mutex_init(&instance_data->page_mutex, "page_mutex",
+                    &instance_data->page_key);
+       instance_data->rmiphysdrvr.name = RMI4_I2C_DRIVER_NAME;
+       instance_data->rmiphysdrvr.write = rmi_i2c_write;
+       instance_data->rmiphysdrvr.read = rmi_i2c_read;
+       instance_data->rmiphysdrvr.write_multiple = rmi_i2c_write_multiple;
+       instance_data->rmiphysdrvr.read_multiple = rmi_i2c_read_multiple;
+       instance_data->rmiphysdrvr.set_attn_handler = set_attn_handler;
+       instance_data->rmiphysdrvr.enable_device = enable_device;
+       instance_data->rmiphysdrvr.disable_device = disable_device;
+       instance_data->rmiphysdrvr.module = THIS_MODULE;
+       /* Set default to polling in case no matching platform data is located
+          for this device. We'll still work but in polling mode since we didn't
+          find any irq info */
+       instance_data->rmiphysdrvr.polling_required = true;
+       instance_data->rmiphysdrvr.proto_name = "i2c";
+
+       instance_data->page = 0xffff;   /* Force a set page the first time */
+       instance_data->enabled = true;  /* We plan to come up enabled. */
+
+       /* Egregiously horrible delay here that seems to prevent I2C disasters
+        * on certain broken dev systems.  In most cases, you can safely
+        * leave this as zero.
+        */
+       dev_dbg(&client->dev, "%s: sensor addr: 0x%02x irq: %d\n",
+                __func__, platformdata->i2c_address,
+               sensordata->attn_gpio_number ?
+                       gpio_to_irq(sensordata->attn_gpio_number) : -1);
+       if (client->addr != platformdata->i2c_address) {
+               dev_err(&client->dev,
+                       "%s: CONFIGURATION ERROR - client I2C address 0x%02x "
+                       "doesn't match platform data address 0x%02x.\n",
+                       __func__, client->addr, platformdata->i2c_address);
+               retval = -EINVAL;
+               goto error_exit;
+       }
+
+       instance_data->instance_no = rmi_next_sensor_id();
+
+       /* set the device name using the instance_no appended to DEVICE_NAME
+        * to make a unique name */
+       dev_set_name(&client->dev, "%s%d", RMI4_I2C_DEVICE_NAME,
+                    instance_data->instance_no);
+
+       retval = gpio_request(sensordata->attn_gpio_number, "rmi");
+       if (retval < 0) {
+               dev_err(&client->dev, "%s: Unable to request GPIO\n", __func__);
+               goto error_exit;
+       }
+       retval = gpio_direction_input(sensordata->attn_gpio_number);
+       if (retval < 0) {
+               dev_err(&client->dev, "%s: Unable to set GPIO direction\n",
+                       __func__);
+               goto error_exit;
+       }
+
+       retval = gpio_request(sensordata->rst_gpio_number, "rmi");
+       if (retval < 0) {
+               dev_err(&client->dev, "%s: Unable to request RESET GPIO\n",
+                       __func__);
+               goto error_exit;
+       }
+       retval = gpio_direction_output(sensordata->rst_gpio_number, 1);
+       if (retval < 0) {
+               dev_err(&client->dev, "%s: Unable to set RESET GPIO "
+                       "direction\n", __func__);
+               goto error_exit;
+       }
+       gpio_set_value(sensordata->rst_gpio_number, 1);
+
+       if (platformdata->delay_ms > 0)
+               mdelay(platformdata->delay_ms);
+
+
+       /* Determine if we need to poll (inefficient) or use interrupts.
+        */
+       if (sensordata->attn_gpio_number) {
+               instance_data->irq = gpio_to_irq(sensordata->attn_gpio_number);
+               instance_data->attn_polarity = sensordata->attn_polarity;
+               instance_data->attn_gpio = sensordata->attn_gpio_number;
+               instance_data->rmiphysdrvr.polling_required = false;
+               instance_data->rmiphysdrvr.irq = instance_data->irq;
+
+       } else {
+               instance_data->rmiphysdrvr.polling_required = true;
+               dev_info(&client->dev,
+                        "%s: No IRQ info given. Polling required.\n",
+                        __func__);
+       }
+
+       /* Store the instance data in the i2c_client - we need to do this prior
+        * to calling register_physical_driver since it may use the read, write
+        * functions. If nothing was found then the id fields will be set to 0
+        * for the irq and the default  will be set to polling required so we
+        * will still work but in polling mode. */
+       i2c_set_clientdata(client, instance_data);
+
+       /* Copy i2c_client pointer into instance_data's i2c_client pointer for
+          later use in rmi4_read, rmi4_write, etc. */
+       instance_data->i2cclient = client;
+
+       /* Call the platform setup routine, to do any setup that is required
+        * before interacting with the device.  When we refined the bus
+        * architecture, this will be done elsewhere.
+        */
+       if (sensordata && sensordata->rmi_sensor_setup) {
+               retval = sensordata->rmi_sensor_setup();
+               if (retval) {
+                       dev_err(&client->dev,
+                               "%s: sensor setup failed with code %d.",
+                              __func__, retval);
+                       goto error_exit;
+               }
+       }
+
+       /* Register sensor drivers - this will call the detect function that
+        * will then scan the device and determine the supported RMI4 sensors
+        * and functions.
+        */
+       retval = rmi_register_sensor(&instance_data->rmiphysdrvr,
+                               platformdata->sensordata);
+       if (retval) {
+               dev_err(&client->dev,
+                       "%s: Failed to register %s sensor drivers\n", __func__,
+                       instance_data->rmiphysdrvr.name);
+               goto error_exit;
+       }
+
+       if (instance_data->rmiphysdrvr.polling_required == false) {
+               retval = acquire_attn_irq(instance_data);
+               if (retval) {
+                       dev_warn(&client->dev,
+                               "Failed to obtain IRQ %d. Result: %d.",
+                               instance_data->irq, retval);
+                       dev_info(&client->dev, "%s: Reverting to polling.\n",
+                                __func__);
+                       instance_data->rmiphysdrvr.polling_required = true;
+                       /* TODO: Need to revert back to polling - create and
+                        * start timer. */
+                       retval = 0;
+               }
+
+               /* export GPIO for attention handling */
+
+#if defined(CONFIG_SYNA_RMI_DEV)
+               retval = gpio_export(instance_data->attn_gpio, false);
+               if (retval) {
+                       dev_warn(&client->dev, "%s: WARNING: Failed to "
+                               "export ATTN gpio!.", __func__);
+                       retval = 0;
+               } else {
+                       retval = gpio_export_link(
+                               &instance_data->rmiphysdrvr.sensor->
+                               sensor_device->dev, "attn",
+                               instance_data->attn_gpio);
+                       if (retval) {
+                               dev_warn(
+                                       &instance_data->rmiphysdrvr.sensor->
+                                       sensor_device->dev, "%s: WARNING: "
+                                       "Failed to symlink ATTN gpio!.",
+                                       __func__);
+                               retval = 0;
+                       } else {
+                               dev_info(&instance_data->
+                                       rmiphysdrvr.sensor->sensor_device->dev,
+                                        "%s: Exported GPIO %d.",
+                                       __func__, instance_data->attn_gpio);
+                       }
+               }
+#endif /* CONFIG_SYNA_RMI_DEV */
+       }
+
+       dev_dbg(&client->dev, "%s: Successfully registered %s sensor driver.\n",
+               __func__, instance_data->rmiphysdrvr.name);
+
+       return retval;
+
+error_exit:
+       kfree(instance_data);
+       /* return error for clean-up*/
+       return retval;
+}
+
+static int rmi_i2c_remove(struct i2c_client *client)
+{
+       struct instance_data *instance_data = i2c_get_clientdata(client);
+
+       dev_dbg(&client->dev, "%s: Unregistering phys driver %s\n", __func__,
+               instance_data->rmiphysdrvr.name);
+
+       rmi_unregister_sensors(&instance_data->rmiphysdrvr);
+
+       dev_dbg(&client->dev, "%s: Unregistered phys driver %s\n",
+               __func__, instance_data->rmiphysdrvr.name);
+
+       /* only free irq if we have an irq - otherwise the instance_data
+          will be 0 for that field */
+       if (instance_data->irq)
+               free_irq(instance_data->irq, instance_data);
+
+       kfree(instance_data);
+       dev_dbg(&client->dev, "%s: Remove successful\n", __func__);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int rmi_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       /* Touch sleep mode */
+       return 0;
+}
+
+static int rmi_i2c_resume(struct i2c_client *client)
+{
+       /* Re-initialize upon resume */
+       return 0;
+}
+#else
+#define rmi_i2c_suspend        NULL
+#define rmi_i2c_resume NULL
+#endif
+
+/*
+ * This structure tells the i2c subsystem about us.
+ *
+ * TODO: we should add .suspend and .resume fns.
+ *
+ */
+static struct i2c_driver rmi_i2c_driver = {
+       .probe = rmi_i2c_probe,
+       .remove = rmi_i2c_remove,
+       .suspend = rmi_i2c_suspend,
+       .resume = rmi_i2c_resume,
+       .driver = {
+               .name = RMI4_I2C_DRIVER_NAME,
+               .owner = THIS_MODULE,
+       },
+       .id_table = rmi_i2c_id_table,
+};
+
+static int __init rmi_phys_i2c_init(void)
+{
+       return i2c_add_driver(&rmi_i2c_driver);
+}
+
+static void __exit rmi_phys_i2c_exit(void)
+{
+       i2c_del_driver(&rmi_i2c_driver);
+}
+
+module_init(rmi_phys_i2c_init);
+module_exit(rmi_phys_i2c_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Driver I2C Physical Layer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi/rmi_sensor.c b/drivers/input/touchscreen/rmi/rmi_sensor.c
new file mode 100644 (file)
index 0000000..09917e6
--- /dev/null
@@ -0,0 +1,1289 @@
+/**
+ * Synaptics Register Mapped Interface (RMI4) - RMI Sensor Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_function.h"
+#include "rmi_sensor.h"
+
+/* Context data for each sensor.
+ */
+struct sensor_instance_data {
+       unsigned char pdt_props;
+       unsigned char bsr;
+       bool enabled;
+};
+
+#define HAS_BSR_MASK 0x20
+#define HAS_NONSTANDARD_PDT_MASK 0x40
+
+static bool has_bsr(struct sensor_instance_data *instance_data)
+{
+       return (instance_data->pdt_props & HAS_BSR_MASK) != 0;
+}
+
+long polltime = 25000000;      /* Shared with rmi_function.c. */
+EXPORT_SYMBOL(polltime);
+module_param(polltime, long, 0644);
+MODULE_PARM_DESC(polltime, "How long to wait between polls (in nano seconds).");
+
+#define PDT_START_SCAN_OFFSET 0x00E9
+#define PDT_END_SCAN_OFFSET 0x0005
+#define PDT_ENTRY_SIZE 0x0006
+#define PDT_PROPERTIES_LOCATION 0x00EF
+#define BSR_LOCATION 0x00FE
+
+static DEFINE_MUTEX(rfi_mutex);
+
+struct rmi_function_ops *rmi_find_function(int function_number);
+
+/* sysfs files for sensor attributes for BSR register value. */
+static ssize_t rmi_sensor_hasbsr_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_sensor_bsr_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_sensor_bsr_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t rmi_sensor_enabled_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_sensor_enabled_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t rmi_sensor_phy_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static struct device_attribute attrs[] = {
+       __ATTR(hasbsr, 0444,
+              rmi_sensor_hasbsr_show, rmi_store_error),        /* RO attr */
+       __ATTR(bsr, 0666,
+              rmi_sensor_bsr_show, rmi_sensor_bsr_store),      /* RW attr */
+       __ATTR(enabled, 0666,
+              rmi_sensor_enabled_show, rmi_sensor_enabled_store), /* RW attr */
+       __ATTR(phy, 0444,
+              rmi_sensor_phy_show, rmi_store_error)            /* RO attr */
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void rmi_sensor_early_suspend(struct early_suspend *h);
+static void rmi_sensor_late_resume(struct early_suspend *h);
+#endif
+
+int rmi_read(struct rmi_sensor_driver *sensor, unsigned short address,
+            char *dest)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct rmi_sensor_device *sensor_device = sensor->sensor_device;
+       struct sensor_instance_data *instance_data;
+
+       /* we could read while sensor_device is not ready */
+       if (sensor_device) {
+               instance_data = sensor_device->sensordata;
+               /* we could read while instance_data is not ready */
+               if (instance_data)
+                       if (!instance_data->enabled)
+                               return -ENODEV;
+       }
+
+       if (!rpd)
+               return -ENODEV;
+
+       return rpd->read(rpd, address, dest);
+}
+EXPORT_SYMBOL(rmi_read);
+
+int rmi_write(struct rmi_sensor_driver *sensor, unsigned short address,
+             unsigned char data)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct rmi_sensor_device *sensor_device = sensor->sensor_device;
+       struct sensor_instance_data *instance_data;
+
+       /* we could write while sensor_device is not ready */
+       if (sensor_device) {
+               instance_data = sensor_device->sensordata;
+               /* we could write while instance_data is not ready */
+               if (instance_data)
+                       if (!instance_data->enabled)
+                               return -ENODEV;
+       }
+
+       if (!rpd)
+               return -ENODEV;
+
+       return rpd->write(rpd, address, data);
+}
+EXPORT_SYMBOL(rmi_write);
+
+int rmi_read_multiple(struct rmi_sensor_driver *sensor, unsigned short address,
+                     char *dest, int length)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct rmi_sensor_device *sensor_device = sensor->sensor_device;
+
+       /* we could read while sensor_device is not ready */
+       if (sensor_device) {
+               struct sensor_instance_data *instance_data =
+                               sensor_device->sensordata;
+               /* we could read while instance_data is not ready */
+               if (instance_data)
+                       if (!instance_data->enabled)
+                               return -ENODEV;
+       }
+       if (!rpd)
+               return -ENODEV;
+
+       return rpd->read_multiple(rpd, address, dest, length);
+}
+EXPORT_SYMBOL(rmi_read_multiple);
+
+int rmi_write_multiple(struct rmi_sensor_driver *sensor, unsigned short address,
+                      unsigned char *data, int length)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct rmi_sensor_device *sensor_device = sensor->sensor_device;
+       struct sensor_instance_data *instance_data;
+
+       /* we could write while sensor_device is not ready */
+       if (sensor_device) {
+               instance_data = sensor_device->sensordata;
+               /* we could write while instance_data is not ready */
+               if (instance_data)
+                       if (!instance_data->enabled)
+                               return -ENODEV;
+       }
+       if (!rpd)
+               return -ENODEV;
+
+       return rpd->write_multiple(rpd, address, data, length);
+}
+EXPORT_SYMBOL(rmi_write_multiple);
+
+/* Utility routine to set bits in a register. */
+int rmi_set_bits(struct rmi_sensor_driver *sensor, unsigned short address,
+                unsigned char bits)
+{
+       unsigned char reg_contents;
+       int retval;
+
+       retval = rmi_read(sensor, address, &reg_contents);
+       if (retval) {
+               pr_debug("%s: Read at 0x%04x failed, code: %d.\n",
+                       __func__, address, retval);
+               return retval;
+       }
+       reg_contents = reg_contents | bits;
+       retval = rmi_write(sensor, address, reg_contents);
+       if (retval == 1)
+               return 0;
+       else if (retval == 0) {
+               pr_debug("%s: Write at 0x%04x failed.\n",
+                       __func__, address);
+               return -EINVAL; /* TODO: What should this be? */
+       }
+       return retval;
+}
+EXPORT_SYMBOL(rmi_set_bits);
+
+/* Utility routine to clear bits in a register. */
+int rmi_clear_bits(struct rmi_sensor_driver *sensor, unsigned short address,
+                  unsigned char bits)
+{
+       unsigned char reg_contents;
+       int retval;
+
+       retval = rmi_read(sensor, address, &reg_contents);
+       if (retval)
+               return retval;
+       reg_contents = reg_contents & ~bits;
+       retval = rmi_write(sensor, address, reg_contents);
+       if (retval == 1)
+               return 0;
+       else if (retval == 0)
+               return -EINVAL; /* TODO: What should this be? */
+       return retval;
+}
+EXPORT_SYMBOL(rmi_clear_bits);
+
+/* Utility routine to set the value of a bit field in a register. */
+int rmi_set_bit_field(struct rmi_sensor_driver *sensor, unsigned short address,
+                     unsigned char field_mask, unsigned char bits)
+{
+       unsigned char reg_contents;
+       int retval;
+
+       retval = rmi_read(sensor, address, &reg_contents);
+       if (retval)
+               return retval;
+       reg_contents = (reg_contents & ~field_mask) | bits;
+       retval = rmi_write(sensor, address, reg_contents);
+       if (retval == 1)
+               return 0;
+       else if (retval == 0)
+               return -EINVAL; /* TODO: What should this be? */
+       return retval;
+}
+EXPORT_SYMBOL(rmi_set_bit_field);
+
+bool rmi_polling_required(struct rmi_sensor_driver *sensor)
+{
+       return sensor->polling_required;
+}
+EXPORT_SYMBOL(rmi_polling_required);
+
+/* Keeps track of how many sensors we've seen so far.  TODO: What happens
+ * if we disconnect from a sensor?  Does it sensor number get recycled?
+ */
+static int sensor_count;
+
+/* Sensors are identified starting at 0 and working up.  This will retrieve
+ * the current sensor number, and increment the sensor_count.
+ */
+int rmi_next_sensor_id()
+{
+       int id = sensor_count;
+       sensor_count++;
+       return id;
+}
+EXPORT_SYMBOL(rmi_next_sensor_id);
+
+/* Functions can call this in order to dispatch IRQs. */
+void dispatchIRQs(struct rmi_sensor_driver *sensor, unsigned int irq_status)
+{
+       struct rmi_function_info *function_info;
+
+       list_for_each_entry(function_info, &sensor->functions, link) {
+               if ((function_info->interrupt_mask & irq_status)
+                   && function_info->function_device
+                   && function_info->function_device->rmi_funcs->
+                               inthandler) {
+                       /* Call the function's interrupt handler. */
+                       function_info->function_device->rmi_funcs->
+                               inthandler(function_info,
+                                       (function_info->
+                                       interrupt_mask & irq_status));
+               }
+       }
+}
+
+/*
+ * This is the function we pass to the RMI4 subsystem so we can be notified
+ * when attention is required.  It may be called in interrupt context.
+ */
+static void attention(struct rmi_phys_driver *physdrvr)
+{
+       /* All we have to do is schedule work. */
+       schedule_work(&(physdrvr->sensor->work));
+}
+
+static void disable_sensor(struct rmi_sensor_driver *sensor)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct sensor_instance_data *instance_data =
+               sensor->sensor_device->sensordata;
+
+       rpd->disable_device(rpd);
+       instance_data->enabled = false;
+}
+
+static int enable_sensor(struct rmi_sensor_driver *sensor)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct sensor_instance_data *instance_data =
+               sensor->sensor_device->sensordata;
+       int retval = 0;
+
+       retval = rpd->enable_device(rpd);
+       /* non-zero means error occurred */
+       if (retval)
+               return retval;
+       instance_data->enabled = true;
+
+       return 0;
+}
+
+/* This notifies any interested functions that there is an Attention interrupt.
+ * The interested functions should take appropriate actions (such as reading
+ * the interrupt status register and dispatching any appropriate RMI4
+ * interrupts).
+ */
+void attn_notify(struct rmi_sensor_driver *sensor)
+{
+       struct rmi_function_info *function_info;
+
+       list_for_each_entry(function_info, &sensor->functions, link) {
+               if (function_info->function_device
+                   && function_info->function_device->rmi_funcs->attention) {
+                       function_info->function_device->rmi_funcs->
+                           attention(function_info);
+               }
+       }
+}
+
+/* This is the worker function - for now it simply has to call attn_notify.
+ * This work should be scheduled whenever an ATTN interrupt is asserted by
+ * the touch sensor.  We then call attn_notify to dispatch notification of
+ * the ATTN interrupt to all interested functions. After all the attention
+ * handling functions have returned, it is presumed safe to re-enable the
+ * Attention interrupt.
+ */
+static void sensor_work_func(struct work_struct *work)
+{
+       struct rmi_sensor_driver *sensor =
+                       container_of(work, struct rmi_sensor_driver, work);
+       struct rmi_sensor_device *sensor_dev = sensor->sensor_device;
+
+       mutex_lock(&sensor->work_lock);
+       attn_notify(sensor);
+
+       /* we only need to enable the irq if doing interrupts */
+       /*
+       * if suspend operation occurs and
+       * this is the function during execution
+       * we cannot enable irq again
+       */
+       if (!rmi_polling_required(sensor) &&
+                       !sensor_dev->device_is_suspended)
+               enable_irq(sensor->rpd->irq);
+       mutex_unlock(&sensor->work_lock);
+}
+
+/* This is the timer function for polling - it simply has to schedule work
+ * and restart the timer. */
+static enum hrtimer_restart sensor_poll_timer_func(struct hrtimer *timer)
+{
+       struct rmi_sensor_driver *sensor =
+                       container_of(timer, struct rmi_sensor_driver, timer);
+
+       if (!work_pending(&sensor->work))
+               schedule_work(&sensor->work);
+       hrtimer_start(&sensor->timer, ktime_set(0, polltime), HRTIMER_MODE_REL);
+       return HRTIMER_NORESTART;
+}
+
+/* This is the probe function passed to the RMI4 subsystem that gives us a
+ * chance to recognize an RMI4 device.  In this case, we're looking for
+ * Synaptics devices that have data sources - such as touch screens, buttons,
+ * etc.
+ *
+ * TODO: Well, it used to do this.  I'm not sure it's required any more.
+ */
+static int probe(struct rmi_sensor_driver *sensor)
+{
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       pr_debug("%s: PROBE CALLED", __func__);
+
+       if (!rpd) {
+               pr_err("%s: Invalid rmi physical driver - null ptr: %p\n",
+                      __func__, rpd);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void config(struct rmi_sensor_driver *sensor)
+{
+       /* For each data source we had detected print info and set up interrupts
+          or polling. */
+       struct rmi_function_info *function_info;
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       struct sensor_instance_data *instance_data =
+                       sensor->sensor_device->sensordata;
+       int attr_count = 0;
+
+       int retval;
+
+       dev_dbg(&sensor->sensor_device->dev, "%s: CONFIG CALLED", __func__);
+
+       list_for_each_entry(function_info, &sensor->functions, link) {
+               /* Get and print some info about the data sources... */
+               struct rmi_function_ops *fn;
+               /* check if function number matches - if so call that
+                  config function */
+               fn = rmi_find_function(function_info->function_number);
+               if (fn) {
+                       if (fn->config) {
+                               fn->config(function_info);
+                       } else {
+                               dev_warn(&sensor->sensor_device->dev,
+                                       "%s: no config function for "
+                                       "function 0x%02x.\n", __func__,
+                                       function_info->function_number);
+                       }
+               } else {
+                       /* if no support found for this RMI4 function
+                          it means the developer did not add the
+                          appropriate function pointer list into the
+                          rmi4_supported_data_src_functions array and/or
+                          did not bump up the number of supported RMI4
+                          functions in rmi.h as required */
+                       dev_err(&sensor->sensor_device->dev,
+                              "%s: no support found for function 0x%02x.\n",
+                              __func__, function_info->function_number);
+               }
+       }
+
+       retval = rpd->read(rpd, PDT_PROPERTIES_LOCATION,
+                          (char *) &instance_data->pdt_props);
+       if (retval) {
+               dev_warn(&sensor->sensor_device->dev,
+                       "%s: Could not read PDT propertys from 0x%04x. "
+                       "Assuming 0x00.\n",
+                      __func__, PDT_PROPERTIES_LOCATION);
+       }
+
+
+       dev_dbg(&sensor->sensor_device->dev, "%s: Creating sysfs files.",
+               __func__);
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (device_create_file(&sensor->sensor_device->dev,
+                                       &attrs[attr_count]) < 0) {
+                       dev_err(&sensor->sensor_device->dev,
+                               "%s: Failed to create sysfs file for %s.\n",
+                               __func__, attrs[attr_count].attr.name);
+                       goto error_exit;
+               }
+       }
+
+       if (rmi_polling_required(sensor)) {
+               /* We're polling driven, so set up the polling timer
+                  and timer function. */
+               hrtimer_init(&sensor->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               sensor->timer.function = sensor_poll_timer_func;
+               hrtimer_start(&sensor->timer, ktime_set(1, 0),
+                             HRTIMER_MODE_REL);
+       }
+
+       instance_data->enabled = true;
+       return;
+
+error_exit:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               device_remove_file(&sensor->sensor_device->dev,
+                                  &attrs[attr_count]);
+       /* If you alloc anything, free it here. */
+}
+
+void *rmi_sensor_get_functiondata(struct rmi_sensor_driver *driver,
+                                 unsigned char function_index)
+{
+       int i;
+
+       if (!driver->perfunctiondata)
+               return NULL;
+
+       for (i = 0; i < driver->perfunctiondata->count; i++) {
+               if (driver->perfunctiondata->functiondata[i].function_index ==
+                   function_index)
+                       return driver->perfunctiondata->functiondata[i].data;
+       }
+
+       return NULL;
+}
+
+/*
+ *  final implementation of suspend/early_suspend function
+ */
+static int rmi_sensor_suspend(struct device *dev, pm_message_t state)
+{
+       struct rmi_sensor_device *sensor_device =
+           container_of(dev, struct rmi_sensor_device, dev);
+       struct rmi_phys_driver *phys_drvr = sensor_device->driver->rpd;
+       struct rmi_sensor_driver *sensor_drvr = sensor_device->driver;
+       struct rmi_sensor_suspend_custom_ops *custom_ops =
+           sensor_drvr->custom_suspend_ops;
+       int retval;
+       struct rmi_function_info *function_info;
+       bool canSuspend = true;
+
+       mutex_lock(&sensor_drvr->sensor_device->setup_suspend_flag);
+
+       if (sensor_device->device_is_suspended) {
+               mutex_unlock(&sensor_drvr->sensor_device->setup_suspend_flag);
+               return 0;
+       }
+
+       /* iterates all of the functions to make sure that we
+        * can enter suspend mode. */
+       list_for_each_entry(function_info, &sensor_drvr->functions, link) {
+               if (function_info->function_device
+                       && function_info->function_device->
+                               rmi_funcs->suspendable) {
+
+                       if (!(function_info->function_device->rmi_funcs->
+                           suspendable(function_info))) {
+                               canSuspend = false;
+                               dev_err(dev, "%s: suspend fails, F0x%02X is "
+                                       "not suspendable", __func__,
+                                       function_info->function_number);
+                               break;
+                       }
+
+               }
+       }
+
+       if (!canSuspend) {
+               mutex_unlock(&sensor_drvr->sensor_device->setup_suspend_flag);
+               return -1;
+       }
+
+       /* set flag before disabling irq */
+       sensor_device->device_is_suspended = 1;
+
+       if (rmi_polling_required(sensor_drvr)) {
+               hrtimer_cancel(&(sensor_drvr->timer));
+       } else {
+               if (phys_drvr)
+                       disable_irq(phys_drvr->irq);
+       }
+       retval = cancel_work_sync(&sensor_drvr->work);
+       if (retval && !(rmi_polling_required(sensor_drvr))) {
+               /* if work is pending ,suspend fail */
+               if (phys_drvr)
+                       enable_irq(phys_drvr->irq);
+               /* reset suspend flag */
+               sensor_device->device_is_suspended = 0;
+               dev_err(dev, "%s: suspend fails, work pending", __func__);
+               retval = -1;
+               goto exit;
+       }
+
+       /* invoke the suspend handler of each functions of this sensor */
+       /* ex. we will call suspend of F01 in the loop*/
+       list_for_each_entry(function_info, &sensor_drvr->functions, link) {
+               if (function_info->function_device
+                       && function_info->function_device->rmi_funcs->suspend) {
+
+                       retval = function_info->function_device->rmi_funcs->
+                               suspend(function_info);
+                       if (retval) {
+                               /* reset suspend flag */
+                               sensor_device->device_is_suspended = 0;
+
+                               if (rmi_polling_required(sensor_drvr)) {
+                                       /* restart polling timer*/
+                                       hrtimer_start(&(sensor_drvr->timer),
+                                                       ktime_set(1, 0),
+                                                       HRTIMER_MODE_REL);
+                               } else {
+                                       if (phys_drvr) {
+                                               /* re-enalbe irq*/
+                                               enable_irq(phys_drvr->irq);
+                                       }
+                               }
+                               dev_err(dev, "%s: failed to suspend F0x%02x.",
+                                       __func__,
+                                       function_info->function_number);
+                               retval = -1;
+                               goto exit;
+                       }
+               }
+       }
+
+       /* apply customized settings */
+       if (custom_ops->rmi_sensor_custom_suspend)
+               custom_ops->rmi_sensor_custom_suspend();
+
+exit:
+       mutex_unlock(&sensor_drvr->sensor_device->setup_suspend_flag);
+       return retval;
+}
+
+/*
+ *  final implementation of resume/late_resume function
+ */
+static int rmi_sensor_resume(struct device *dev)
+{
+       struct rmi_sensor_device *sensor_device =
+           container_of(dev, struct rmi_sensor_device, dev);
+       struct rmi_phys_driver *phys_drvr = sensor_device->driver->rpd;
+       struct rmi_sensor_driver *sensor_drvr = sensor_device->driver;
+       struct rmi_sensor_suspend_custom_ops *custom_ops =
+           sensor_drvr->custom_suspend_ops;
+       struct rmi_function_info *function_info;
+
+       mutex_lock(&sensor_drvr->sensor_device->setup_suspend_flag);
+       if (sensor_device->device_is_suspended) {
+               /* reset suspend flag reenable irq */
+               sensor_device->device_is_suspended = 0;
+               /* apply customized settings */
+               if (custom_ops->rmi_sensor_custom_resume)
+                       custom_ops->rmi_sensor_custom_resume();
+
+               /* invoke the resume handler of each functions of this sensor */
+               /* ex. we will call resume of F01 in the loop*/
+               list_for_each_entry(function_info,
+                               &sensor_drvr->functions, link) {
+                       if (function_info->function_device
+                               && function_info->function_device->
+                                       rmi_funcs->resume)
+                               function_info->function_device->rmi_funcs->
+                                   resume(function_info);
+               }
+
+               /* apply delay after setup hardware */
+               if (custom_ops->delay_resume)
+                       mdelay(custom_ops->delay_resume);
+
+               if (rmi_polling_required(sensor_drvr)) {
+                       hrtimer_start(&(sensor_drvr->timer), ktime_set(1, 0),
+                                     HRTIMER_MODE_REL);
+               } else {
+                       if (phys_drvr)
+                               enable_irq(phys_drvr->irq);
+               }
+       }
+       mutex_unlock(&sensor_drvr->sensor_device->setup_suspend_flag);
+       return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+/*
+ * Handler for early suspend
+ */
+static void rmi_sensor_early_suspend(struct early_suspend *h)
+{
+       struct rmi_sensor_device *sensor_device =
+           container_of(h, struct rmi_sensor_device, early_suspend_handler);
+       pm_message_t state;
+       state.event = PM_EVENT_SUSPEND;
+       (void)rmi_sensor_suspend(&(sensor_device->dev), state);
+}
+
+/*
+ * Handler for late resume
+ */
+static void rmi_sensor_late_resume(struct early_suspend *h)
+{
+       struct rmi_sensor_device *sensor_device =
+           container_of(h, struct rmi_sensor_device, early_suspend_handler);
+       (void)rmi_sensor_resume(&(sensor_device->dev));
+}
+#endif
+
+
+#define RMI4_MAX_PAGE 0xFF
+#define RMI4_PAGE_SIZE 0x100
+
+/*
+ * This method is called, whenever a new sensor device is added for the rmi
+ * bus.
+ *
+ * It will scan the devices PDT to determine the supported functions
+ * and create a new function device for each of these. It will read
+ * the query, control, command and data regsiters for the function
+ * to be used for each newly created function device.
+ *
+ * The sensor device is then bound to every function it supports.
+ *
+ */
+static int rmi_sensor_register_functions(struct rmi_sensor_driver *sensor)
+{
+       struct rmi_function_device *function;
+       unsigned int interrupt_register_count = 0;
+       struct rmi_phys_driver *rpd = sensor->rpd;
+       int i;
+       int j;
+       int page;
+       bool done; /* Indicates the last page we checked for PDT's had none */
+       int interrupt_offset;
+       unsigned char interrupt_count = 0;
+       struct rmi_function_descriptor rmi_fd;
+       struct rmi_function_ops *fops;
+       int retval = 0;
+       struct device *dev = &sensor->sensor_device->dev;
+       struct rmi_function_info *function_info = NULL;
+
+       /* Read the Page Descriptor Table to determine what functions
+        * are present */
+       dev_dbg(dev, "%s: Scanning page descriptors.", __func__);
+       for (page = 0; (page <= RMI4_MAX_PAGE) && !done; page++) {
+               int page_start = RMI4_PAGE_SIZE * page;
+               int pdt_start = page_start + PDT_START_SCAN_OFFSET;
+               int pdt_end = page_start + PDT_END_SCAN_OFFSET;
+               done = true; /* Assume we are done until we read a
+                               valid function */
+
+               for (i = pdt_start; i >= pdt_end; i -= PDT_ENTRY_SIZE) {
+                       dev_dbg(dev, "%s: Reading page descriptor at 0x%04x.\n",
+                               __func__,  i);
+                       retval = rpd->read_multiple(rpd, i, (char *)&rmi_fd,
+                                                   sizeof(rmi_fd));
+
+                       if (retval) {
+                               /* failed to read next PDT entry - end PDT
+                                  scan - this may result in an incomplete set
+                                  of recognized functions - we could return
+                                  an error here but the driver may still be
+                                  viable for diagnostics and debugging so let's
+                                  let it continue. */
+                               dev_err(dev,
+                                   "%s: Read error %d at PDT entry 0x%02x, "
+                                    "ending scan.\n", __func__, retval, i);
+                               break;
+                       }
+
+                       if (!RMI_IS_VALID_FUNCTION_ID(rmi_fd.function_number)) {
+                               /* A zero or 0xff in the function number
+                                  signals the end of the PDT */
+                               dev_dbg(dev, "%s: Found end of PDT.\n",
+                                       __func__);
+                               break;
+                       } else {
+                               /* There must be at least one valid function on
+                                * a page for this code to run. We must check
+                                * the next page.
+                                */
+                                done = false;
+                       }
+
+                       dev_dbg(dev, "%s: F%02x - queries %02x commands %02x "
+                               "control %02x data %02x ints %02x",
+                               __func__, rmi_fd.function_number,
+                               rmi_fd.query_base_addr,
+                               rmi_fd.command_base_addr,
+                               rmi_fd.control_base_addr, rmi_fd.data_base_addr,
+                               rmi_fd.interrupt_source_count);
+
+                       /* determine if the function is supported and if so
+                        * then bind this function device to the sensor */
+                       function_info = kzalloc(sizeof(*function_info),
+                                               GFP_KERNEL);
+                       if (!function_info) {
+                               dev_err(dev,
+                                   "%s: out of memory for function F%02x.",
+                                    __func__, rmi_fd.function_number);
+                               retval = -ENOMEM;
+                               goto exit_fail;
+                       }
+                       function_info->sensor = sensor;
+                       function_info->function_number = rmi_fd.function_number;
+                       /* Here we add in the current page start address to our
+                        * addressess. According to current RMI specification,
+                        * all PDT entries are located on the same page as
+                        * their corresponding function. This is because we
+                        * don't have the room to store page info in the table,
+                        * but can infer it off of the current page.
+                        */
+
+                       function_info->function_descriptor.query_base_addr =
+                               rmi_fd.query_base_addr + page_start;
+                       function_info->function_descriptor.command_base_addr =
+                               rmi_fd.command_base_addr + page_start;
+                       function_info->function_descriptor.control_base_addr =
+                               rmi_fd.control_base_addr + page_start;
+                       function_info->function_descriptor.data_base_addr =
+                               rmi_fd.data_base_addr + page_start;
+
+                       function_info->function_descriptor.function_number =
+                               rmi_fd.function_number;
+                       function_info->num_data_sources =
+                               rmi_fd.interrupt_source_count;
+                       function_info->interrupt_register = interrupt_count / 8;
+                       /* loop through interrupts for each source and or in
+                        * a bit to the interrupt mask for each. */
+                       interrupt_offset = interrupt_count % 8;
+
+                       for (j = interrupt_offset;
+                               j < ((rmi_fd.interrupt_source_count & 0x7)
+                                       + interrupt_offset);
+                               j++) {
+                               function_info->interrupt_mask |= 1 << j;
+                       }
+                       INIT_LIST_HEAD(&function_info->link);
+
+                       /* Get the ptr to the detect function based on
+                        * the function number */
+                       dev_dbg(dev, "%s: Checking for RMI function F%02x.",
+                               __func__, rmi_fd.function_number);
+                       fops = rmi_find_function(rmi_fd.function_number);
+                       if (!fops) {
+                               dev_err(dev,
+                                       "%s: couldn't find support for F%02X.",
+                                       __func__, rmi_fd.function_number);
+                       } else {
+                               retval = fops->detect(function_info);
+                               if (retval)
+                                       dev_err(dev,
+                                           "%s: Function detect for F%02x "
+                                           "failed with %d.",
+                                            __func__, rmi_fd.function_number,
+                                            retval);
+
+                               /* Create a function device and
+                                * function driver. */
+                               function = kzalloc(sizeof(*function),
+                                                  GFP_KERNEL);
+                               if (!function) {
+                                       dev_err(dev,
+                                           "%s: Error allocating memory for "
+                                            "rmi_function_device.",
+                                            __func__);
+                                       retval = -ENOMEM;
+                                       goto exit_fail;
+                               }
+
+                               function->dev.parent =
+                                       &sensor->sensor_device->dev;
+                               function->dev.bus =
+                                       sensor->sensor_device->dev.bus;
+                               function->rmi_funcs = fops;
+                               function->sensor = sensor;
+                               function->rfi = function_info;
+                               function_info->function_device = function;
+
+                               /* Check if we have an interrupt mask of 0 and
+                                * a non-NULL interrupt handler function and
+                                * print a debug message since we should never
+                                * have this.
+                                */
+                               if (function_info->interrupt_mask == 0
+                                   && fops->inthandler != NULL) {
+                                       dev_warn(dev,
+                                           "%s: Can't have a zero interrupt mask "
+                                            "for function F%02x (which requires an "
+                                            "interrupt handler).",
+                                            __func__, rmi_fd.function_number);
+                               }
+
+                               /* Check if we have a non-zero interrupt mask
+                                * and a NULL interrupt handler function and
+                                * print a debug message since we should never
+                                * have this.
+                                */
+                               if (function_info->interrupt_mask != 0
+                                   && fops->inthandler == NULL) {
+                                       dev_warn(dev,
+                                           "%s: Can't have a non-zero interrupt "
+                                            "mask %d for function F%02x with a NULL "
+                                            "inthandler fn.\n",
+                                            __func__,
+                                            function_info->interrupt_mask,
+                                            rmi_fd.function_number);
+                               }
+
+                               /* Register the rmi function device */
+                               retval = rmi_function_register_device(function,
+                                                       rmi_fd.function_number);
+                               if (retval) {
+                                       dev_err(dev,
+                                           "%s: Failed to register function "
+                                           " device.", __func__);
+                                       goto exit_fail;
+                               }
+                       }
+
+                       /* bump interrupt count for next iteration.
+                        * NOTE: The value 7 is reserved - for now,
+                        * only bump up one for an interrupt count of 7.
+                        */
+                       if ((rmi_fd.interrupt_source_count & 0x7) == 0x7) {
+                               interrupt_count += 1;
+                       } else {
+                               interrupt_count +=
+                                   (rmi_fd.interrupt_source_count & 0x7);
+                       }
+
+                       /* link this function info to the RMI module infos list
+                        * of functions. */
+                       if (function_info == NULL) {
+                               dev_dbg(dev, "%s: WTF? function_info is null "
+                                       " here.", __func__);
+                       } else {
+                               dev_dbg(dev, "%s: Adding F%02x with %d sources.",
+                                        __func__,
+                                        function_info->function_number,
+                                        function_info->num_data_sources);
+
+                               mutex_lock(&rfi_mutex);
+                               list_add_tail(&function_info->link,
+                                             &sensor->functions);
+                               mutex_unlock(&rfi_mutex);
+                       }
+                       function_info = NULL;
+               }
+       }
+       dev_dbg(dev, "%s: Done scanning.", __func__);
+
+       /* calculate the interrupt register count - used in the
+        * ISR to read the correct number of interrupt registers */
+       interrupt_register_count = (interrupt_count + 7) / 8;
+       /* TODO: Is interrupt_register_count needed by the sensor anymore? */
+       sensor->interrupt_register_count = interrupt_register_count;
+
+       return 0;
+
+exit_fail:
+       if (function_info)
+               kfree(function_info->function_device);
+       kfree(function_info);
+       return retval;
+}
+
+/* sysfs show and store fns for sensor dev */
+static ssize_t rmi_sensor_hasbsr_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_sensor_device *sensor = dev_get_drvdata(dev);
+       struct sensor_instance_data *instance_data =
+           (struct sensor_instance_data *)sensor->sensordata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", has_bsr(instance_data));
+}
+
+/* Show physical connection information as:
+ *     prot tx_count tx_bytes tx_errors rx_count rx_bytes rx_errors attn
+ */
+static ssize_t rmi_sensor_phy_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct rmi_sensor_device *sensor = dev_get_drvdata(dev);
+       struct rmi_phys_driver *rpd = sensor->driver->rpd;
+
+       return snprintf(buf, PAGE_SIZE, "%s %ld %ld %ld %ld %ld %ld %ld\n",
+                       rpd->proto_name, rpd->tx_count, rpd->tx_bytes,
+                       rpd->tx_errors, rpd->rx_count, rpd->rx_bytes,
+                       rpd->rx_errors, rpd->attn_count);
+}
+
+static ssize_t rmi_sensor_bsr_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rmi_sensor_device *sensor = dev_get_drvdata(dev);
+       struct sensor_instance_data *instance_data =
+           (struct sensor_instance_data *)sensor->sensordata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->bsr);
+}
+
+static ssize_t rmi_sensor_bsr_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       int retval;
+       struct rmi_sensor_device *sensor = dev_get_drvdata(dev);
+       struct sensor_instance_data *instance_data =
+           (struct sensor_instance_data *)sensor->sensordata;
+       unsigned long val;
+
+       /* need to convert the string data to an actual value */
+       retval = strict_strtoul(buf, 10, &val);
+       if (retval < 0)
+               return retval;
+
+
+       retval = rmi_write(sensor->driver, BSR_LOCATION, (unsigned char)val);
+       if (retval) {
+               dev_err(dev, "%s : failed to write bsr %u to 0x%x\n",
+                      __func__, (unsigned int)val, BSR_LOCATION);
+               return -EIO;
+       }
+
+       instance_data->bsr = val;
+
+       return count;
+}
+
+static ssize_t rmi_sensor_enabled_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct rmi_sensor_device *sensor = dev_get_drvdata(dev);
+       struct sensor_instance_data *instance_data = sensor->sensordata;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->enabled);
+}
+
+static ssize_t rmi_sensor_enabled_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       int retval;
+       struct rmi_sensor_device *sensor = dev_get_drvdata(dev);
+       bool new_value;
+
+       if (sysfs_streq(buf, "0"))
+               new_value = false;
+       else if (sysfs_streq(buf, "1"))
+               new_value = true;
+       else
+               return -EINVAL;
+
+       if (new_value) {
+               retval = enable_sensor(sensor->driver);
+               if (retval) {
+                       dev_err(dev, "Failed to ensable sensor, code=%d.\n",
+                               retval);
+                       return -EIO;
+               }
+       } else {
+               disable_sensor(sensor->driver);
+       }
+
+       return count;
+}
+
+/* Call this to instantiate a new sensor driver.
+ */
+struct rmi_sensor_driver *rmi_sensor_create_driver(
+                               struct rmi_sensor_device *sensor_device,
+                               struct rmi_phys_driver *physical_driver,
+                               struct rmi_sensordata *sensor_data)
+{
+       struct rmi_sensor_driver *driver =
+           kzalloc(sizeof(struct rmi_sensor_driver), GFP_KERNEL);
+       if (!driver) {
+               dev_err(&sensor_device->dev,
+                       "%s: Out of memory for rmi_sensor_driver\n",
+                      __func__);
+               goto error_exit;
+       }
+       driver->sensor_device = sensor_device;
+       driver->polling_required = physical_driver->polling_required;
+       driver->rpd = physical_driver;
+
+       mutex_init(&driver->work_lock);
+
+       if (sensor_data) {
+               driver->perfunctiondata = sensor_data->perfunctiondata;
+               /* pass reference to customized operations for suspend/resume */
+               driver->custom_suspend_ops = sensor_data->custom_suspend_ops;
+       }
+       INIT_LIST_HEAD(&driver->functions);
+
+       /* This will handle interrupts on the ATTN line (interrupt driven)
+        * or will be called every poll interval (when we're not interrupt
+        * driven).
+        */
+       INIT_WORK(&driver->work, sensor_work_func);
+
+       return driver;
+
+error_exit:
+       rmi_sensor_destroy_driver(driver);
+       return NULL;
+}
+
+/* Call this when you're done with the sensor driver.  This will clean up any
+ * pending actions, cancel any running threads or works, and release all
+ * storage.
+ */
+void rmi_sensor_destroy_driver(struct rmi_sensor_driver *driver)
+{
+       kfree(driver);
+}
+
+int rmi_sensor_register_device(struct rmi_sensor_device *dev, int index)
+{
+       int status;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend *early_suspend_handler;
+#endif
+       struct sensor_instance_data *instance_data;
+
+       pr_debug("%s: Registering sensor device.\n", __func__);
+
+       /* make name - sensor00, sensor01, etc. */
+       dev_set_name(&dev->dev, "sensor%02d", index);
+
+       dev->sensordata =
+           kzalloc(sizeof(struct sensor_instance_data), GFP_KERNEL);
+       if (!dev->sensordata) {
+               dev_err(&dev->dev,
+                   "%s: Out of memory for sensor instance data.\n", __func__);
+               return -ENOMEM;
+       }
+       instance_data = dev->sensordata;
+       /* let initial rmi_read_multiple/rmi_read happy */
+       instance_data->enabled = true;
+
+       status = device_register(&dev->dev);
+
+       if (status < 0) {
+               dev_err(&dev->dev, "%s: device register failed with %d.",
+                       __func__, status);
+               goto error_exit;
+       }
+
+       mutex_init(&dev->setup_suspend_flag);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       /* register early_suspend handler after device is registered
+        */
+       early_suspend_handler = &(dev->early_suspend_handler);
+       early_suspend_handler->level =
+               EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+       early_suspend_handler->suspend = rmi_sensor_early_suspend;
+       early_suspend_handler->resume = rmi_sensor_late_resume;
+       register_early_suspend(early_suspend_handler);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+       return 0;
+
+error_exit:
+       kfree(dev->sensordata);
+       return status;
+}
+EXPORT_SYMBOL(rmi_sensor_register_device);
+
+static void rmi_sensor_unregister_device(struct rmi_sensor_device *rmisensordev)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend *early_suspend_handler;
+
+       /* unregister early_suspend handler before driver is unregistered
+        */
+       early_suspend_handler =
+                   &(rmisensordev->early_suspend_handler);
+       unregister_early_suspend(early_suspend_handler);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+       dev_dbg(&rmisensordev->dev,
+               "%s: Unregistering sensor device.\n", __func__);
+
+       device_unregister(&rmisensordev->dev);
+}
+EXPORT_SYMBOL(rmi_sensor_unregister_device);
+
+#define DRIVER_NAME_CHARS      16
+
+int rmi_sensor_register_driver(struct rmi_sensor_driver *driver)
+{
+       static int index;
+       int ret;
+       char *drvrname;
+
+       pr_info("%s: Registering sensor driver.\n", __func__);
+       driver->dispatchIRQs = dispatchIRQs;
+       driver->attention = attention;
+       driver->config = config;
+       driver->probe = probe;
+
+       driver->drv.suspend = rmi_sensor_suspend;
+       driver->drv.resume = rmi_sensor_resume;
+       /* Create a function device and function driver for this Fn */
+       drvrname = kzalloc(DRIVER_NAME_CHARS, GFP_KERNEL);
+       if (!drvrname) {
+               pr_err
+                   ("%s: Error allocating memory for rmi_sensor_driver name.",
+                    __func__);
+               return -ENOMEM;
+       }
+       snprintf(drvrname, DRIVER_NAME_CHARS, "sensor%02d", index++);
+
+       driver->drv.name = drvrname;
+       driver->module = driver->drv.owner;
+
+       /* Register the sensor driver on the bus. */
+       ret = rmi_bus_register_sensor_driver(driver);
+       if (ret) {
+               pr_err("%s: Failed to register driver on bus, error = %d",
+                      __func__, ret);
+               goto exit_fail;
+       }
+
+       /* register the functions on the sensor */
+       ret = rmi_sensor_register_functions(driver);
+       if (ret) {
+               pr_err("%s: Failed rmi_sensor_register_functions %d",
+                      __func__, ret);
+               goto exit_fail;
+       }
+
+       /* configure the sensor - enable interrupts for each function,
+        * init work, set polling timer or adjust report rate, etc. */
+       config(driver);
+#if defined(CONFIG_SYNA_RMI_DEV)
+       if (rmi_char_dev_register(driver->rpd, driver->sensor_device))
+               pr_err("%s: error register char device", __func__);
+#endif /*CONFIG_SYNA_RMI_DEV*/
+       pr_debug("%s: sensor driver registration completed.", __func__);
+
+exit_fail:
+       kfree(drvrname);
+       return ret;
+}
+EXPORT_SYMBOL(rmi_sensor_register_driver);
+
+static void rmi_sensor_unregister_driver(struct rmi_sensor_driver *driver)
+{
+#if defined(CONFIG_SYNA_RMI_DEV)
+       struct rmi_sensor_device *rmisensordev = driver->sensor_device;
+#endif /* CONFIG_SYNA_RMI_DEV */
+       pr_debug("%s: Unregistering sensor driver.\n", __func__);
+
+#if defined(CONFIG_SYNA_RMI_DEV)
+       rmi_char_dev_unregister(rmisensordev->char_dev,
+                       rmisensordev->rmi_char_device_class);
+#endif /*CONFIG_SYNA_RMI_DEV*/
+
+       /* Stop the polling timer if doing polling */
+       if (rmi_polling_required(driver))
+               hrtimer_cancel(&driver->timer);
+
+       flush_scheduled_work(); /* Make sure all scheduled work is stopped */
+
+       rmi_bus_register_sensor_driver(driver);
+}
+EXPORT_SYMBOL(rmi_sensor_unregister_driver);
+
+static int __init rmi_sensor_init(void)
+{
+       pr_debug("%s: RMI Sensor Init\n", __func__);
+       return 0;
+}
+
+static void __exit rmi_sensor_exit(void)
+{
+       pr_debug("%s: RMI Sensor Driver Exit\n", __func__);
+       flush_scheduled_work(); /* Make sure all scheduled work is stopped */
+}
+
+module_init(rmi_sensor_init);
+module_exit(rmi_sensor_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Sensor Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi/rmi_sensor.h b/drivers/input/touchscreen/rmi/rmi_sensor.h
new file mode 100644 (file)
index 0000000..0aca071
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) - RMI Sensor Module Header.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ *
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_SENSOR_H)
+#define _RMI_SENSOR_H
+
+
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include <linux/rmi_platformdata.h>
+#include "rmi_dev.h"
+
+struct rmi_sensor_driver {
+       struct module *module;
+       struct device_driver drv;
+       struct rmi_sensor_device *sensor_device;
+
+       /* Attention Function
+        *  This function is called by the low level isr in the physical
+        * driver. It merely schedules work to be done.
+        */
+       void (*attention) (struct rmi_phys_driver *physdrvr);
+       /* Probe Function
+        *  This function is called to give the sensor driver layer an
+        *  opportunity to claim an RMI device.  The sensor layer cannot
+        *  read RMI registers at this point since the rmi physical driver
+        *  has not been bound to it yet.  Defer that to the config
+        *  function call which occurs immediately after a successful probe.
+        */
+       int (*probe) (struct rmi_sensor_driver *sensor);
+       /* Config Function
+        *  This function is called after a successful probe.  It gives the
+        *  sensor driver an opportunity to query and/or configure an RMI
+        *  device before data starts flowing.
+        */
+       void (*config) (struct rmi_sensor_driver *sensor);
+
+       /* Functions can call this in order to dispatch IRQs. */
+       void (*dispatchIRQs) (struct rmi_sensor_driver *sensor,
+                             unsigned int irq_status);
+
+       unsigned int interrupt_register_count;
+
+       bool polling_required;
+
+       /* pointer to the corresponding phys driver info for this sensor */
+       /* The phys driver has the pointers to read, write, etc. */
+       struct rmi_phys_driver *rpd;
+
+       struct hrtimer timer;
+       struct work_struct work;
+       struct mutex work_lock;
+
+       struct list_head functions;     /* List of rmi_function_infos */
+               /* Per function initialization data. */
+       struct rmi_functiondata_list *perfunctiondata;
+               /* non-default operation for suspend/resume */
+       struct rmi_sensor_suspend_custom_ops *custom_suspend_ops;
+};
+
+/* macro to get the pointer to the device_driver struct from the sensor */
+#define to_rmi_sensor_driver(drv) \
+       container_of(drv, struct rmi_sensor_driver, drv);
+
+struct rmi_sensor_device {
+       struct rmi_sensor_driver *driver;
+       struct device dev;
+
+       /* mutex for setting device_is_supended flag*/
+       struct mutex setup_suspend_flag;
+       int device_is_suspended;        /*it will be initialized to false(0) */
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       /* handler to handle early_suspend and late_resume */
+       struct early_suspend early_suspend_handler;
+#endif
+       /* pointer to data specific to a sensor implementation. */
+       void *sensordata;
+
+       struct list_head sensors;       /* link sensors into list */
+#ifdef CONFIG_SYNA_RMI_DEV
+       /* pointer to attention char device and char device */
+       struct rmi_char_dev *char_dev;
+       struct class *rmi_char_device_class;
+#endif /*CONFIG_SYNA_RMI_DEV*/
+};
+
+int rmi_sensor_register_device(struct rmi_sensor_device *dev, int index);
+int rmi_sensor_register_driver(struct rmi_sensor_driver *driver);
+bool rmi_polling_required(struct rmi_sensor_driver *sensor);
+int rmi_next_sensor_id(void);
+
+void *rmi_sensor_get_functiondata(struct rmi_sensor_driver *driver,
+                                 unsigned char function_index);
+
+
+/* Call this to instantiate a new sensor driver.
+ */
+struct rmi_sensor_driver *rmi_sensor_create_driver(
+                       struct rmi_sensor_device *sensor_device,
+                       struct rmi_phys_driver *physical_driver,
+                       struct rmi_sensordata *sensor_data);
+
+/* Call this when you're done with the sensor driver.  This will clean up any
+ * pending actions, cancel any running threads or works, and release all
+ * storage.
+ */
+void rmi_sensor_destroy_driver(struct rmi_sensor_driver *driver);
+#endif
diff --git a/drivers/input/touchscreen/rmi/rmi_spi.c b/drivers/input/touchscreen/rmi/rmi_spi.c
new file mode 100644 (file)
index 0000000..148842b
--- /dev/null
@@ -0,0 +1,770 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) SPI Physical Layer Driver.
+ * Copyright (C) 2008-2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/spi/spi.h>
+#include <linux/wait.h>
+#include <linux/gpio.h>
+
+#include "rmi_spi.h"
+#include "rmi_drvr.h"
+#include "rmi_sensor.h"
+
+#define COMM_DEBUG  0          /* Set to 1 to dump transfers. */
+
+/* For V1 protocol, the high bit in the address is set to indicate reads. */
+#define SPI_V1_READ_FLAG 0x80
+
+/* For V2 protocol, first byte of transmission indicates what operation is
+ * to be performed.
+ */
+#define SPI_V2_UNIFIED_READ       0xC0
+#define SPI_V2_WRITE              0x40
+#define SPI_V2_PREPARE_SPLIT_READ 0xC8
+#define SPI_V2_EXECUTE_SPLIT_READ 0xCA
+
+/* Once the sensor has prepared a V2 split read, we always send the same
+ * bytes to tell it to execute the read. For convenience, we keep a static
+ * copy of those bytes around.
+ */
+static unsigned char execute_split_read[] = { SPI_V2_EXECUTE_SPLIT_READ, 0x00 };
+
+/* This is the data kept on a per instance (client) basis.  This data is
+ * always accessible by using the container_of() macro of the various elements
+ * inside.
+ */
+struct spi_device_instance_data {
+       int instance_no;
+       int irq;
+       int attn_polarity;
+       int attn_gpio;
+       unsigned int byte_delay_us;
+       unsigned int block_delay_us;
+       unsigned int split_read_byte_delay_us;
+       unsigned int split_read_block_delay_us;
+       unsigned int buffer_size;
+       unsigned char spi_version;
+       int v2_transaction_size;
+       wait_queue_head_t attn_event;
+       bool attn_seen;
+       bool split_read_pending;
+       struct rmi_phys_driver rpd;
+       struct spi_device *spidev;
+       struct rmi_spi_platformdata *platformdata;
+};
+
+
+static int spi_xfer(struct spi_device_instance_data *instance_data,
+                   const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx)
+{
+       struct spi_device *spi = instance_data->spidev;
+#if COMM_DEBUG
+       int i;
+#endif
+       int status;
+       struct spi_message message;
+       struct spi_transfer *xfer_list;
+       const int total_bytes = n_tx + n_rx;
+       u8 local_buf[total_bytes];
+       int xfers_in_message = 0;
+       int xfer_index = 0;
+       int block_delay = n_rx > 0 ? instance_data->block_delay_us : 0;
+       int byte_delay = n_tx > 1 ? instance_data->byte_delay_us : 0;
+       if (instance_data->split_read_pending) {
+               block_delay =
+                   n_rx > 0 ? instance_data->split_read_block_delay_us : 0;
+               byte_delay =
+                   n_tx > 1 ? instance_data->split_read_byte_delay_us : 0;
+       }
+
+       if (n_tx) {
+               xfers_in_message += 1;
+               instance_data->rpd.tx_count++;
+               instance_data->rpd.tx_bytes += n_tx;
+       }
+       if (n_rx) {
+               instance_data->rpd.rx_count++;
+               instance_data->rpd.rx_bytes += n_rx;
+               if (byte_delay)
+                       xfers_in_message += n_rx;
+               else
+                       xfers_in_message += 1;
+       }
+
+       xfer_list = kcalloc(xfers_in_message,
+                           sizeof(struct spi_transfer), GFP_KERNEL);
+       if (!xfer_list)
+               return -ENOMEM;
+
+       spi_message_init(&message);
+
+       if (n_tx) {
+               memset(&xfer_list[0], 0, sizeof(struct spi_transfer));
+               xfer_list[0].len = n_tx;
+               xfer_list[0].delay_usecs = block_delay;
+               spi_message_add_tail(&xfer_list[0], &message);
+               memcpy(local_buf, txbuf, n_tx);
+               xfer_list[0].tx_buf = local_buf;
+               xfer_index++;
+       }
+       if (n_rx) {
+               if (byte_delay) {
+                       int buffer_offset = n_tx;
+                       for (; xfer_index < xfers_in_message; xfer_index++) {
+                               memset(&xfer_list[xfer_index], 0,
+                                      sizeof(struct spi_transfer));
+                               xfer_list[xfer_index].len = 1;
+                               xfer_list[xfer_index].delay_usecs = byte_delay;
+                               xfer_list[xfer_index].rx_buf =
+                                   local_buf + buffer_offset;
+                               buffer_offset++;
+                               spi_message_add_tail(&xfer_list[xfer_index],
+                                                    &message);
+                       }
+               } else {
+                       memset(&xfer_list[xfer_index], 0,
+                              sizeof(struct spi_transfer));
+                       xfer_list[xfer_index].len = n_rx;
+                       xfer_list[xfer_index].rx_buf = local_buf + n_tx;
+                       spi_message_add_tail(&xfer_list[xfer_index], &message);
+                       xfer_index++;
+               }
+       }
+#if COMM_DEBUG
+       pr_info("%s: SPI transmits %d bytes...", __func__, n_tx);
+       for (i = 0; i < n_tx; i++)
+               pr_info("    0x%02X", local_buf[i]);
+#endif
+
+       /* do the i/o */
+       if (instance_data->platformdata->cs_assert) {
+               status = instance_data->platformdata->cs_assert(
+                       instance_data->platformdata->cs_assert_data, true);
+               if (!status) {
+                       pr_err("%s: Failed to assert CS.", __func__);
+                       /* nonzero means error */
+                       status = -1;
+                       goto error_exit;
+               } else
+                       status = 0;
+       }
+       status = spi_sync(spi, &message);
+       if (instance_data->platformdata->cs_assert) {
+               status = instance_data->platformdata->cs_assert(
+                       instance_data->platformdata->cs_assert_data, false);
+               if (!status) {
+                       pr_err("%s: Failed to deassert CS.", __func__);
+                       /* nonzero means error */
+                       status = -1;
+                       goto error_exit;
+               } else
+                       status = 0;
+       }
+       if (status == 0) {
+               memcpy(rxbuf, local_buf + n_tx, n_rx);
+               status = message.status;
+#if COMM_DEBUG
+               if (n_rx) {
+                       pr_info("%s: SPI received %d bytes...", __func__, n_rx);
+                       for (i = 0; i < n_rx; i++)
+                               pr_info("    0x%02X", rxbuf[i]);
+               }
+#endif
+       } else {
+               if (n_tx)
+                       instance_data->rpd.tx_errors++;
+               if (n_rx)
+                       instance_data->rpd.rx_errors++;
+               pr_err("%s: spi_sync failed with error code %d.",
+                      __func__, status);
+       }
+
+error_exit:
+       kfree(xfer_list);
+       return status;
+}
+
+/* Same as rmi_spi_read_v1, except that multiple bytes are allowed to be read.
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored.  This
+ * buffer must be at least size bytes long.
+ * \param[in] size The number of bytes to be read.
+ * \return zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_spi_read_multiple_v1(struct rmi_phys_driver *pd, unsigned short address,
+                        char *valp, int size)
+{
+       struct spi_device_instance_data *instance_data =
+           container_of(pd, struct spi_device_instance_data, rpd);
+       int retval;
+       unsigned char txbuf[2];
+
+       txbuf[1] = address;
+       txbuf[0] = address >> 8;
+       txbuf[0] |= SPI_V1_READ_FLAG;
+
+       retval = spi_xfer(instance_data, txbuf, ARRAY_SIZE(txbuf), valp, size);
+
+       return retval;
+}
+
+/*
+ * Read a single register through SPI, V1 protocol.
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored.
+ * \return zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_spi_read_v1(struct rmi_phys_driver *pd, unsigned short address, char *valp)
+{
+       return rmi_spi_read_multiple_v1(pd, address, valp, 1);
+}
+
+/* Write multiple registers using version 1 of the RMI4 SPI interface.
+ * \param[in] pd
+ * \param[in] address The address at which to start the write.
+ * \param[in] valp A pointer to a buffer containing the data to be written.
+ * \param[in] size The number of bytes to write.
+ * \return one upon success, something else upon error.
+ */
+static int
+rmi_spi_write_multiple_v1(struct rmi_phys_driver *pd, unsigned short address,
+                         char *valp, int size)
+{
+       struct spi_device_instance_data *id =
+           container_of(pd, struct spi_device_instance_data, rpd);
+       int buffer_size = size + 2;
+       unsigned char txbuf[buffer_size];
+       int retval;
+       int i;
+
+       txbuf[1] = address;
+       txbuf[0] = address >> 8;
+
+       for (i = 0; i < size; i++)
+               txbuf[i + 2] = valp[i];
+
+       retval = spi_xfer(id, txbuf, buffer_size, NULL, 0);
+
+       return retval ? 0 : 1;
+}
+
+/* Write a single register through SPI using version 1 of the interface.
+ * You can write multiple registers at once, but I made the functions for that
+ * seperate for performance reasons.  Writing multiple requires allocation and
+ * freeing.
+ * \param[in] pd
+ * \param[in] address The address at which to start the write.
+ * \param[in] data The data to be written.
+ * \return one upon success, something else upon error.
+ */
+static int
+rmi_spi_write_v1(struct rmi_phys_driver *pd, unsigned short address, char data)
+{
+       return rmi_spi_write_multiple_v1(pd, address, &data, 1);
+}
+
+/* Read multiple bytes using version 2 of the RMI4 SPI interface.
+ *
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored.  This
+ * buffer must be at least size bytes long.
+ * \param[in] size The number of bytes to be read.
+ * \return zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_spi_read_multiple_v2(struct rmi_phys_driver *pd, unsigned short address,
+                        char *valp, int size)
+{
+       struct spi_device_instance_data *instance_data =
+           container_of(pd, struct spi_device_instance_data, rpd);
+       int retval;
+       char header_buf[4];
+
+       header_buf[0] = SPI_V2_UNIFIED_READ;
+       header_buf[1] = (address >> 8) & 0x00FF;
+       header_buf[2] = address & 0x00ff;
+       header_buf[3] = size;
+
+       retval = spi_xfer(instance_data, header_buf, ARRAY_SIZE(header_buf),
+                         valp, size);
+
+       return retval;
+}
+
+/* Read a single register (one byte) from the device, using version 2 of the
+ * RMI4 SPI interface.
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored.
+ * \return zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_spi_read_v2(struct rmi_phys_driver *pd, unsigned short address, char *valp)
+{
+       return rmi_spi_read_multiple_v2(pd, address, valp, 1);
+}
+
+/* Read multiple bytes using version 2 of the RMI4 SPI interface.
+ *
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored.  This
+ * buffer must be at least size bytes long.
+ * \param[in] size The number of bytes to be read.
+ * \return zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_spi_split_read_v2(struct rmi_phys_driver *pd, unsigned short address,
+                     char *valp, int size)
+{
+       struct spi_device_instance_data *instance_data =
+           container_of(pd, struct spi_device_instance_data, rpd);
+       int retval;
+       char header_buf[4];
+       int read_size = size + 1; /* Add a byte for dummy byte at start. */
+       char read_buf[read_size];
+
+       header_buf[0] = SPI_V2_PREPARE_SPLIT_READ;
+       header_buf[1] = (address >> 8) & 0x00FF;
+       header_buf[2] = address & 0x00ff;
+       header_buf[3] = size;
+
+       instance_data->attn_seen = false;
+       instance_data->split_read_pending = true;
+
+       retval = spi_xfer(instance_data, header_buf, ARRAY_SIZE(header_buf),
+                         NULL, 0);
+       if (retval) {
+               instance_data->split_read_pending = false;
+               return retval;
+       }
+
+       enable_irq(pd->irq);
+       wait_event_interruptible((instance_data->attn_event),
+                                (instance_data->attn_seen == true));
+
+       retval = spi_xfer(instance_data,
+                         execute_split_read, ARRAY_SIZE(execute_split_read),
+                         read_buf, read_size);
+       instance_data->split_read_pending = false;
+       if (retval)
+               return retval;
+       if (read_buf[0] != size)
+               return -EIO;
+       memcpy(valp, &read_buf[1], size);
+
+       return retval;
+}
+
+/* Write multiple registers using version 2 of the RMI4 SPI interface.
+ *
+ * \param[in] pd
+ * \param[in] address The address at which to start the write.
+ * \param[in] valp A pointer to a buffer containing the data to be written.
+ * \param[in] size The number of bytes to write.
+ * \return one upon success, something else upon error.
+ */
+static int
+rmi_spi_write_multiple_v2(struct rmi_phys_driver *pd, unsigned short address,
+                         char *valp, int size)
+{
+       struct spi_device_instance_data *id =
+           container_of(pd, struct spi_device_instance_data, rpd);
+       unsigned char txbuf[size + 4];
+       int retval;
+
+       txbuf[0] = SPI_V2_WRITE;
+       txbuf[1] = (address >> 8) & 0x00FF;
+       txbuf[2] = address & 0x00FF;
+       txbuf[3] = size;
+
+       memcpy(&txbuf[4], valp, size);
+
+       retval = spi_xfer(id, txbuf, size + 4, NULL, 0);
+
+       return retval ? 0 : 1;
+}
+
+/* Write a single byte/register using version 2 of the RMI4 SPI interface.
+ *
+ * \param[in] pd
+ * \param[in] address The address at which to start the write.
+ * \param[in] data The data to be written.
+ * \return one upon success, something else upon error.
+ */
+static int
+rmi_spi_write_v2(struct rmi_phys_driver *pd, unsigned short address, char data)
+{
+       return rmi_spi_write_multiple_v2(pd, address, &data, 1);
+}
+
+/* This is the Interrupt Service Routine.  It just notifies the physical device
+ * that attention is required.
+ */
+static irqreturn_t spi_attn_isr(int irq, void *info)
+{
+       struct spi_device_instance_data *instance_data = info;
+
+       disable_irq_nosync(instance_data->irq);
+       instance_data->rpd.attn_count++;
+
+       if (instance_data->spi_version == 2 &&
+           instance_data->split_read_pending) {
+               instance_data->attn_seen = true;
+               wake_up(&instance_data->attn_event);
+               return IRQ_HANDLED;
+       }
+
+       if (instance_data->rpd.attention)
+               instance_data->rpd.attention(&instance_data->rpd);
+       return IRQ_HANDLED;
+}
+
+/* Specify the routine that will be called when attention is asserted.
+ */
+static void set_attn_handler (struct rmi_phys_driver *physdrvr,
+       void (*attention) (struct rmi_phys_driver *physdrvr))
+{
+       physdrvr->attention = attention;
+}
+
+static int __devinit rmi_spi_probe(struct spi_device *spi)
+{
+       struct spi_device_instance_data *instance_data;
+       int retval;
+       struct rmi_spi_platformdata *platformdata;
+       struct rmi_sensordata *sensordata;
+       char buf[6];
+       unsigned long irq_type = IRQ_TYPE_LEVEL_LOW;
+
+       dev_info(&spi->dev, "%s: Probing RMI4 SPI device", __func__);
+
+       platformdata = spi->dev.platform_data;
+       if (platformdata == NULL) {
+               dev_err(&spi->dev,
+                       "%s: CONFIGURATION ERROR - platform data is NULL.",
+                      __func__);
+               return -EINVAL;
+       }
+
+       spi->bits_per_word = 8;
+       /* This should have already been set up in the board file,
+        * shouldn't it? */
+       spi->mode = SPI_MODE_3;
+
+       retval = spi_setup(spi);
+       if (retval < 0) {
+               dev_err(&spi->dev,
+                       "%s: spi_setup failed with %d.", __func__, retval);
+               return retval;
+       }
+
+       instance_data = kzalloc(sizeof(*instance_data), GFP_KERNEL);
+       if (!instance_data) {
+               dev_err(&spi->dev,
+                       "%s: Failed to allocate memory for instance data.",
+                      __func__);
+               kfree(platformdata);
+               return -ENOMEM;
+       }
+
+       instance_data->platformdata = platformdata;
+       sensordata = platformdata->sensordata;
+       instance_data->block_delay_us =
+           platformdata->block_delay_us ? platformdata->
+           block_delay_us : RMI_DEFAULT_BLOCK_DELAY_US;
+       instance_data->byte_delay_us =
+           platformdata->byte_delay_us ? platformdata->
+           byte_delay_us : RMI_DEFAULT_BYTE_DELAY_US;
+       instance_data->split_read_block_delay_us =
+           platformdata->split_read_block_delay_us;
+       instance_data->split_read_byte_delay_us =
+           platformdata->split_read_byte_delay_us;
+
+       instance_data->spidev = spi;
+       instance_data->rpd.name = RMI4_SPI_DRIVER_NAME;
+       instance_data->rpd.proto_name = "spi1";
+       instance_data->rpd.write = rmi_spi_write_v1;
+       instance_data->rpd.read = rmi_spi_read_v1;
+       instance_data->rpd.write_multiple = rmi_spi_write_multiple_v1;
+       instance_data->rpd.read_multiple = rmi_spi_read_multiple_v1;
+       instance_data->rpd.set_attn_handler = set_attn_handler;
+       instance_data->rpd.module = THIS_MODULE;
+               /* default to polling if irq not used */
+       instance_data->rpd.polling_required = true;
+
+
+       /* Call the platform setup routine, to do any setup that is
+        * required before interacting with the device.
+        */
+       if (sensordata && sensordata->rmi_sensor_setup) {
+               retval = sensordata->rmi_sensor_setup();
+               if (retval) {
+                       dev_err(&spi->dev,
+                               "%s: sensor setup failed with code %d.",
+                              __func__, retval);
+                       goto error_exit;
+               }
+       }
+
+       instance_data->instance_no = rmi_next_sensor_id();
+       dev_set_name(&spi->dev, "%s%d", RMI4_SPI_DEVICE_NAME,
+                       instance_data->instance_no);
+
+       /* Determine if we need to poll (inefficient) or use interrupts.
+        */
+       if (sensordata->attn_gpio_number) {
+               instance_data->attn_polarity = sensordata->attn_polarity;
+               instance_data->attn_gpio = sensordata->attn_gpio_number;
+               instance_data->rpd.polling_required = false;
+       } else {
+               instance_data->rpd.polling_required = true;
+               dev_info(&spi->dev,
+                        "%s: No IRQ info given. Polling required.\n",
+          __func__);
+       }
+
+       /* Store instance data for later access. */
+       if (instance_data)
+               spi_set_drvdata(spi, instance_data);
+
+#if    defined(CONFIG_MACH_OMAP3_BEAGLE)
+       /* Fixes an issue on Beagleboard - first time read is all 0's,
+        * brief wait required afterwards. */
+       retval = instance_data->rpd.read_multiple(&(instance_data->rpd),
+                                       RMI_PDT_START_ADDRESS, (char *)buf,
+                                       6);
+       msleep(20);
+#endif
+
+       retval = instance_data->rpd.read_multiple(&(instance_data->rpd),
+                                       RMI_PROTOCOL_VERSION_ADDRESS, buf,
+                                       2);
+       if (retval < 0) {
+               dev_err(&spi->dev,
+                       "%s: Protocol discovery for SPI V2 failed with %d.",
+                       __func__, retval);
+               goto error_exit;
+       }
+#if    COMM_DEBUG
+       dev_info(&spi->dev,
+                "%s: SPI V2 probe got %02X %02X.", __func__, buf[0], buf[1]);
+#endif
+
+       /* buf[0] is equal to SPI proto version - 1. */
+       instance_data->spi_version = buf[0] + 1;
+       switch (instance_data->spi_version) {
+       case 1:
+               break;
+       case 2:
+               instance_data->v2_transaction_size = (unsigned char)buf[1];
+               instance_data->rpd.proto_name = "spi2";
+               instance_data->rpd.write = rmi_spi_write_v2;
+               instance_data->rpd.write_multiple = rmi_spi_write_multiple_v2;
+               instance_data->rpd.read = rmi_spi_read_v2;
+               instance_data->rpd.read_multiple = rmi_spi_read_multiple_v2;
+               dev_info(&spi->dev,
+                               "%s: Identified SPI V2, transaction size=%d.",
+                               __func__, instance_data->v2_transaction_size);
+               break;
+       default:
+               instance_data->spi_version = 1;
+               dev_warn(&spi->dev,
+                   "%s: Unknown SPI version %d encountered. Assuming SPI V1.",
+                    __func__, instance_data->spi_version);
+       }
+
+       /* Register the sensor driver - which will trigger a scan of the PDT. */
+       retval =
+           rmi_register_sensor(&instance_data->rpd, platformdata->sensordata);
+       if (retval) {
+               dev_err(&spi->dev,
+                       "%s: sensor registration failed with code %d.",
+                       __func__, retval);
+               goto error_exit;
+       }
+
+       if (instance_data->rpd.polling_required == false) {
+               retval = request_irq(instance_data->irq, spi_attn_isr,
+                               irq_type, dev_name(&spi->dev),
+                               instance_data);
+               if (retval) {
+                       dev_err(&spi->dev,
+                               "%s: failed to obtain IRQ %d. Result: %d.",
+                               __func__, instance_data->irq, retval);
+                       dev_info(&spi->dev, "%s: Reverting to polling.\n",
+                                __func__);
+                       instance_data->rpd.polling_required = true;
+                       instance_data->irq = 0;
+                       /* TODO: Need to revert back to polling -
+                        * create and start timer. */
+               } else {
+                       dev_dbg(&spi->dev, "%s: got irq.\n", __func__);
+                       instance_data->irq =
+                       gpio_to_irq(sensordata->attn_gpio_number);
+
+                       instance_data->rpd.irq = instance_data->irq;
+                       if (instance_data->spi_version == 2) {
+                               init_waitqueue_head(&instance_data->attn_event);
+                               instance_data->rpd.read_multiple =
+                                   rmi_spi_split_read_v2;
+                       }
+                       if ((irq_type & IRQ_TYPE_EDGE_BOTH) != 0)
+
+                               if (instance_data->attn_gpio &&
+                                       gpio_get_value(
+                                       instance_data->attn_gpio
+                                       ) == instance_data->attn_polarity &&
+                                       instance_data->rpd.attention) {
+
+                                       disable_irq(instance_data->irq);
+                                       instance_data->rpd.attention(
+                                                       &instance_data->rpd);
+                               }
+               }
+
+               /* export GPIO for attention handling */
+
+#if defined(CONFIG_SYNA_RMI_DEV)
+               retval = gpio_export(instance_data->attn_gpio, false);
+               if (retval) {
+                       dev_warn(&spi->dev, "%s: WARNING: Failed to "
+                               "export ATTN gpio!.", __func__);
+                       retval = 0;
+               } else {
+                       retval = gpio_export_link(
+                               &instance_data->rpd.sensor->
+                               sensor_device->dev, "attn",
+                               instance_data->attn_gpio);
+                       if (retval) {
+                               dev_warn(
+                                       &instance_data->rpd.sensor->
+                                       sensor_device->dev, "%s: WARNING: "
+                                       "Failed to symlink ATTN gpio!.",
+                                       __func__);
+                               retval = 0;
+                       } else {
+                               dev_info(&instance_data->
+                                       rpd.sensor->sensor_device->dev,
+                                        "%s: Exported GPIO %d.",
+                                       __func__, instance_data->attn_gpio);
+                       }
+               }
+#endif /* CONFIG_SYNA_RMI_DEV */
+       }
+
+       dev_info(&spi->dev, "%s: Successfully registered %s.", __func__,
+               instance_data->rpd.name);
+
+       return 0;
+
+error_exit:
+       if (sensordata && sensordata->rmi_sensor_teardown)
+               sensordata->rmi_sensor_teardown();
+       if (instance_data->irq)
+               free_irq(instance_data->irq, instance_data);
+       kfree(instance_data);
+       return retval;
+}
+
+static int rmi_spi_suspend(struct spi_device *spi, pm_message_t message)
+{
+       pr_info("%s: Suspending...", __func__);
+       return 0;
+}
+
+static int rmi_spi_resume(struct spi_device *spi)
+{
+       pr_info("%s: Resuming...", __func__);
+       return 0;
+}
+
+static int __devexit rmi_spi_remove(struct spi_device *spi)
+{
+       struct spi_device_instance_data *instance_data = spi_get_drvdata(spi);
+       pr_info("%s: RMI SPI device removed.", __func__);
+
+       rmi_spi_suspend(spi, PMSG_SUSPEND);
+
+       rmi_unregister_sensors(&instance_data->rpd);
+
+       if (instance_data) {
+               if (instance_data->irq)
+                       free_irq(instance_data->irq, instance_data);
+               kfree(instance_data);
+       }
+
+       return 0;
+}
+
+static struct spi_driver rmi_spi_driver = {
+       .driver = {
+               .name = RMI4_SPI_DRIVER_NAME,
+               .bus = &spi_bus_type,
+               .owner = THIS_MODULE,
+               },
+       .probe = rmi_spi_probe,
+       .remove = __devexit_p(rmi_spi_remove),
+       .suspend = rmi_spi_suspend,
+       .resume = rmi_spi_resume,
+};
+
+static int __init rmi_spi_init(void)
+{
+       int retval;
+       pr_info("%s: RMI SPI physical layer initialization.", __func__);
+       retval = spi_register_driver(&rmi_spi_driver);
+       if (retval < 0) {
+               pr_err("%s: Failed to register spi driver, code = %d.",
+                      __func__, retval);
+               return retval;
+       }
+       pr_debug("%s: SPI initialization complete.", __func__);
+       return retval;
+}
+
+module_init(rmi_spi_init);
+
+static void __exit rmi_spi_exit(void)
+{
+       pr_info("%s: RMI SPI physical layer exits.", __func__);
+       spi_unregister_driver(&rmi_spi_driver);
+}
+
+module_exit(rmi_spi_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Driver SPI Physical Layer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi/rmi_spi.h b/drivers/input/touchscreen/rmi/rmi_spi.h
new file mode 100644 (file)
index 0000000..54775d2
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+ *
+ * Register Mapped Interface SPI Physical Layer Driver Header File.
+ * Copyright (C) 2008-2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_SPI_H)
+#define _RMI_SPI_H
+
+#include <linux/rmi_platformdata.h>
+
+#define RMI4_SPI_DRIVER_NAME "rmi4_ts"
+#define RMI4_SPI_DEVICE_NAME "rmi4_ts"
+
+/* Some RMI4 SPI devices require a delay between writing the address and
+ * starting the read.  A subset of those required a delay between each
+ * byte transferred during the read.
+ */
+
+/* microseconds between header and start of read operation. */
+#define RMI_DEFAULT_BLOCK_DELAY_US     65
+
+/* microseconds inter-byte delay between bytes during read. */
+#define RMI_DEFAULT_BYTE_DELAY_US      65
+
+/* Use this to specify SPI interface dependent parameters on a per device basis.
+ *
+ * Interface independent data is given in the sensor_data field of this struct.
+ */
+struct rmi_spi_platformdata {
+       /* RMI4 devices implement two different ways of talking to the
+        * device over SPI.  These are called SPIv1 and SPIv2.  Due to
+        * resource constraints on some ASICs, delays may be required when
+        * reading data from the chip.
+        *
+        * The block delay specifies the number of microseconds the
+        * driver should delay between sending the read request and
+        * the start of reading data from the ASIC.  If you don't know
+        * what value to use here, you should specify
+        * RMI_DEFAULT_BLOCK_DELAY_US.
+        *
+        * The byte delay specifies the number of microseconds the driver should
+        * delay between each byte of a read request.  If don't know what value
+        * to use here, you should specify RMI_DEFAULT_BLOCK_DELAY_US.
+        *
+        * Usually these two values should be the same, but in some cases
+        * it may be desirable to use different values.
+        */
+       unsigned int block_delay_us;
+       unsigned int byte_delay_us;
+
+       /* SPIv2 supports a special "split read" operation, which can permit the
+        * SPI interface to run at full speed (subject to product specific
+        * limitations) with no delay between blocks and bytes.  In almost all
+        * cases, it is permissible to default these values to zero.
+        */
+       unsigned int split_read_block_delay_us;
+       unsigned int split_read_byte_delay_us;
+
+       /* Some SPI hardware and/or drivers do not manage the SSB/CS line in a
+        * reasonable way.  In particular, the problem is that SSB/CS will be
+        * deasserted in between every spi_transfer in an spi_message (despite
+        * whatever you might have set the spi_transfer.cs_change flag to),
+        * rather than asserting it at the start of the spi_message and leaving
+        * it asserted until all transfers are completed.  In this case, we
+        * have to manage the SSB/CS line manually, and you need to provide
+        * the cs_assert callback here.
+        *
+        * If the cs_assert function is non-null, it will be called before
+        * the driver submits an spi_message in order to assert the line (the
+        * assert parameter will be TRUE), and afterwards to clear it (the
+        * assert parameter will be FALSE).  cs_assert should return 0 for
+        * success, or a negative error code if it fails.
+        *
+        * You can provide any needed context data in the cs_assert_data
+        * variable, which will be passed into all cs_assert calls.
+        */
+       void *cs_assert_data;
+       int (*cs_assert) (const void *cs_assert_data, const bool assert);
+
+
+       /* Use this to specify platformdata that is not SPI specific. */
+       struct rmi_sensordata *sensordata;
+};
+
+#endif
diff --git a/include/linux/rmi_i2c.h b/include/linux/rmi_i2c.h
new file mode 100644 (file)
index 0000000..061c757
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ *
+ * Synaptics RMI over I2C Physical Layer Driver Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_I2C_H)
+#define _RMI_I2C_H
+
+#include <linux/rmi_platformdata.h>
+
+/* In the future, we may change the device name.  If so, defining it here
+ * makes life easier.
+ */
+#define RMI4_I2C_DRIVER_NAME "rmi4_ts"
+#define RMI4_I2C_DEVICE_NAME "rmi4_ts"
+
+/* Sensor-specific configuration data, to be included as the platform data
+ * for the relevant i2c_board_info entry.
+ *
+ * This describes a single RMI4 sensor on an I2C bus, including:
+ * its I2C address, IRQ (if any), the type of IRQ (if applicable), and an
+ * optional list of any non-default settings (on a per function basis)
+ * to be applied at start up.
+ */
+struct rmi_i2c_platformdata {
+       /* The seven-bit i2c address of the sensor. */
+       int i2c_address;
+
+       /* If >0, the driver will delay this many milliseconds before attempting
+        * I2C communications.  This is necessary because some horribly broken
+        * development systems don't bring their I2C up very fast after system
+        * power on or reboot.  In most cases, you can safely ignore this.
+        */
+       int delay_ms;
+
+       /* Use this to specify platformdata that is not I2C specific. */
+       struct rmi_sensordata *sensordata;
+};
+
+#endif
diff --git a/include/linux/rmi_platformdata.h b/include/linux/rmi_platformdata.h
new file mode 100644 (file)
index 0000000..c3eb7d3
--- /dev/null
@@ -0,0 +1,144 @@
+/**
+ *
+ * Synaptics RMI platform data definitions for use in board files.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_PLATFORMDATA_H)
+#define _RMI_PLATFORMDATA_H
+
+/* A couple of structs that are useful for frequently occuring constructs, such
+ * as coordinate origin offsets or coordinate clipping values.
+ */
+struct rmi_XY_pair {
+       int x;
+       int y;
+};
+
+struct rmi_range {
+       int min;
+       int max;
+};
+
+struct rmi_sensor_suspend_custom_ops {
+       /* This will be called when suspend or early_suspend is issued.
+        * Use this for any initial setting related to IRQ (for Attention
+        * signal) or anything else to lower power consumption. This will
+        * be called before any internal process related to suspend mode. */
+       void (*rmi_sensor_custom_suspend) (void);
+       /* This will be called when resume or late_resume is issued. Use
+        * this for any setting related to IRQ (for Attention signal) or
+        * anything else to restore from low power mode. This will be called
+        * after all internal process related to resume mode*/
+       void (*rmi_sensor_custom_resume) (void);
+       /* custom delay in millisecond waiting for stability of hardware
+        * from low power mode */
+       int delay_resume;
+
+};
+
+#define RMI_ATTN_ACTIVE_LOW  0
+#define RMI_ATTN_ACTIVE_HIGH 1
+
+/* This contains sensor specific data that is not specialized to I2C or SPI.
+ */
+struct rmi_sensordata {
+       /* This will be called from rmi_register_sensor().  You can use
+        * it to set up gpios, IRQs, and other platform specific
+        * infrastructure. */
+       int (*rmi_sensor_setup) (void);
+
+       /* This will be called when the sensor is unloaded.  Use this to release
+        * gpios, IRQs, and other platform specific infrastructure. */
+       void (*rmi_sensor_teardown) (void);
+
+       /* The number of gpio for irq.  Set to zero if polling is required. */
+       int attn_gpio_number;
+       int rst_gpio_number;
+       int attn_polarity;
+
+       /* Use this to customize non-default setting regarding suspend/resume */
+       struct rmi_sensor_suspend_custom_ops *custom_suspend_ops;
+       /* Use this to specify non-default settings on a per function basis. */
+       struct rmi_functiondata_list *perfunctiondata;
+};
+
+/* This contains the per-function customization for a given function.  We store
+ * the data this way in order to avoid allocating a large sparse array -
+ * typically only a few functions are present on a sensor, and even fewer
+ * will be have custom settings.  There is a very small penalty paid for
+ * doing a linear search through the list to find a given function's data,
+ * but since the list is typically very short and is searched only at system
+ * boot time, this is considered acceptable.
+ *
+ * When adding new fields to a functiondata struct, please follow these rules:
+ *     - Where possible, use 0 to indicate that the value should be defaulted.
+ *       This works pretty well for bools, ints, and chars.
+ *     - Where this is not practical (for example, in coordinate offsets or
+ *       range clipping), use a pointer.  Set that pointer to null to indicate
+ *       that the value should be defaulted.
+ */
+struct rmi_functiondata {
+       unsigned char function_index;
+       void *data;
+};
+
+/* This can be included in the platformdata for SPI or I2C RMI4 devices to
+ * customize the settings of the functions on a given sensor.
+ */
+struct rmi_functiondata_list {
+       unsigned char count;    /* Number of elements in the array */
+       struct rmi_functiondata *functiondata;
+};
+
+struct rmi_f01_functiondata {
+       /* What this does is product specific.  For most, but not all, RMI4
+        * devices, you can set this to true in order to request the device
+        * report data at half the usual rate.  This can be useful on slow
+        * CPUs that don't have the resources to process data at the usual
+        * rate.  However, the meaning of this field is product specific, and
+        * you should consult the product spec for your sensor to find out
+        * what this will do.
+        */
+       bool nonstandard_report_rate;
+};
+
+struct rmi_f11_functiondata {
+       bool swap_axes;
+       bool flip_X;
+       bool flip_Y;
+       struct rmi_XY_pair *offset;
+       struct rmi_range *clip_X;
+       struct rmi_range *clip_Y;
+};
+
+struct rmi_button_map {
+       unsigned char nbuttons;
+       unsigned char *map;
+};
+
+struct rmi_f19_functiondata {
+       struct rmi_button_map *button_map;
+};
+
+#define USE_PAGESELECT /* for RMI_I2C */
+
+#endif