* [PATCH 0/1] input synaptics-rmi4: Synaptics Touchscreen Driver
@ 2011-01-13 2:40 Christopher Heiny
2011-01-13 2:40 ` [PATCH 1/1] " Christopher Heiny
0 siblings, 1 reply; 2+ messages in thread
From: Christopher Heiny @ 2011-01-13 2:40 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
Allie Xiong, William Manson, Joerie de Gram, Linus Walleij,
Naveen Kumar Gaddipati, Abraham Arce
This patch implements a driver supporting Synaptics ClearPad and other
touchscreens that use the RMI4 protocol, as defined here:
http://www.synaptics.com/sites/default/files/511-000136-01_revA.pdf
This patch is against the synaptics-rmi4 branch of Dmitry's Torokhov's input
git repository. Base point is the origin of the branch, commit
a6268cc5f94c89c9e661150fe136b24e69d6cc01.
I2C functionality was previously ACK'ed by Jean Delvare on 2010/05/29.
This patch builds and runs in our development environment, but I cannot
guarantee that it will build for you. We're working on making sure it
builds generically, and feedback relating to that will be greatly
appreciated (special thanks to Joerie de Gram for his previous feedback on
this).
This version of the driver implements the following:
- basic device control support
- support basic multifinger touchscreen behavior
- support for device reflash
It represents a significant rearchitecture and reimplementation since
our patch of 2010/07/27, based on feedback from that patch and subsequent
discussions with kernel maintainers.
This patch supports a system having one or more RMI sensors attached to it.
Most devices have just a single touch sensor, but some have more than one.
An example is the Fuse concept phone, which has 4 RMI sensors in it).
Each sensor implements a number of RMI4 functions, which are best represented
as devices on the bus.
Included in this patch are the following components:
- a low level layer providing access to the physical bus (rmi_i2c
and rmi_spi).
- an rmi_bus module, implementing /sys/bus/rmi. This module presents
the individual devices on the bus, handles interdevice communications
(mostly just IRQ notifications from F01 to other functions), and
proxies register read/write requests to the appropriate physical layer
for a given sensor.
- individual sensors are presented on the bus as /sys/bus/rmi/sensor0/,
/sys/bus/rmi/sensor01/, and so on.
- functions for each sensor are presented as devices below that sensor, for
example /sys/bus/rmi/sensor0/f01, /sys/bus/rmi/sensor0/f11, and so on.
- per-function drivers are matched to these devices by the kernel bus
functionality
We chose this approach because almost all RMI4 functions are independent
of one another. The sole exception is F01, and its primary interaction
with other functions is to notify them of the need to read or write data
from or to the sensor.
This structure eliminates the ad hoc device matching that was present in our
previous driver submissions. It also enables easy addition of support for
additional RMI4 functions, either by Synaptics or by third parties.
Comments and other feedback on this driver are welcomed.
Bill Manson
Allie Xiong
Christopher Heiny
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
Cc: Abraham Arce <x0066660@ti.com>
---
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 1/1] input synaptics-rmi4: Synaptics Touchscreen Driver
2011-01-13 2:40 [PATCH 0/1] input synaptics-rmi4: Synaptics Touchscreen Driver Christopher Heiny
@ 2011-01-13 2:40 ` Christopher Heiny
0 siblings, 0 replies; 2+ messages in thread
From: Christopher Heiny @ 2011-01-13 2:40 UTC (permalink / raw)
Cc: Jean Delvare, Linux Kernel, Linux Input, Christopher Heiny,
Allie Xiong, William Manson, Joerie de Gram, Dmitry Torokhov,
Linus Walleij, Naveen Kumar Gaddipati, Abraham Arce
Driver for Synaptics touchscreens using RMI4 protocol.
Signed-off-by: William Manson <wmanson@synaptics.com>
Signed-off-by: Allie Xiong <axiong@synaptics.com>
Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
Cc: Abraham Arce <x0066660@ti.com>
Acked-by: Jean Delvare <khali@linux-fr.org>
---
drivers/input/touchscreen/Kconfig | 19 +-
drivers/input/touchscreen/Makefile | 3 +-
drivers/input/touchscreen/rmi_app_touchpad.c | 400 ---------------
drivers/input/touchscreen/rmi_bus.c | 393 ++++++++++++++
drivers/input/touchscreen/rmi_bus.h | 41 ++
drivers/input/touchscreen/rmi_core.c | 708 --------------------------
drivers/input/touchscreen/rmi_core.h | 57 --
drivers/input/touchscreen/rmi_drvr.h | 203 ++++++++
drivers/input/touchscreen/rmi_f01.c | 169 ++++++
drivers/input/touchscreen/rmi_f01.h | 46 ++
drivers/input/touchscreen/rmi_f11.c | 472 +++++++++++++++++
drivers/input/touchscreen/rmi_f11.h | 47 ++
drivers/input/touchscreen/rmi_f34.c | 556 ++++++++++++++++++++
drivers/input/touchscreen/rmi_f34.h | 56 ++
drivers/input/touchscreen/rmi_function.c | 352 +++++++++++++
drivers/input/touchscreen/rmi_function.h | 199 ++++++++
drivers/input/touchscreen/rmi_function_11.c | 439 ----------------
drivers/input/touchscreen/rmi_function_11.h | 43 --
drivers/input/touchscreen/rmi_functions.h | 111 ----
drivers/input/touchscreen/rmi_i2c.c | 588 +++++++++++++++++++++
drivers/input/touchscreen/rmi_phys_i2c.c | 577 ---------------------
drivers/input/touchscreen/rmi_sensor.c | 706 +++++++++++++++++++++++++
drivers/input/touchscreen/rmi_sensor.h | 121 +++++
drivers/input/touchscreen/rmi_spi.c | 477 +++++++++++++++++
drivers/input/touchscreen/rmi_spi.h | 53 ++
25 files changed, 4499 insertions(+), 2337 deletions(-)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index b62139b..48219b3 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -314,7 +314,24 @@ config TOUCHSCREEN_SYNAPTICS_RMI4_I2C
If unsure, say N.
To compile this driver as a set of modules, choose M here: the
- modules will be called rmi, rmi_app_touchpad, rmi_phys_i2c.
+ modules will be called rmi_core, rmi_app_touchpad, rmi_phys_i2c.
+
+config TOUCHSCREEN_SYNAPTICS_RMI4_SPI
+ tristate "Synaptics RMI4 SPI touchscreens"
+ depends on SPI
+ help
+ Say Y here if you have a Synaptics RMI4 SPI touchscreen connected to
+ your system. This enables support for Synaptics RMI4 over SPI 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_spi.
+
+config SYNA_MULTI_TOUCH
+ bool "Synaptics pointing using multi-touch events"
+ depends on TOUCHSCREEN_SYNAPTICS_RMI4_I2C || TOUCHSCREEN_SYNAPTICS_RMI4_SPI
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index b81109b..a17e03e 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -31,7 +31,8 @@ obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C) += rmi_core.o rmi_app_touchpad.o rmi_function_11.o rmi_phys_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C) += rmi_bus.o rmi_sensor.o rmi_function.o rmi_f01.o rmi_f11.o rmi_f34.o rmi_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_SPI) += rmi_bus.o rmi_sensor.o rmi_function.o rmi_f01.o rmi_f11.o rmi_f34.o rmi_spi.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
diff --git a/drivers/input/touchscreen/rmi_app_touchpad.c b/drivers/input/touchscreen/rmi_app_touchpad.c
deleted file mode 100644
index 5f3bd81..0000000
--- a/drivers/input/touchscreen/rmi_app_touchpad.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/**
- *
- * Synaptics Register Mapped Interface (RMI4) TouchPad Application Layer Driver.
- * Copyright (c) 2007 - 2010, Synaptics Incorporated
- *
- *
- * This code implements a polling mechanism using a timer as well as
- * interrupt-driven sampling.
- *
- * Note that it is the lower-level drivers that determine whether this driver
- * has to do polling or interrupt-driven. Polling can always be done, but if
- * we have an interrupt connected to the attention (ATTN) line, then it is
- * better to be interrupt driven.
- *
- */
-/*
- * 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/hrtimer.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-
-#include "rmi.h"
-#include "rmi_core.h"
-#include "rmi_functions.h"
-
-#define RMI_REPORT_RATE_80 0
-#define RMI_REPORT_RATE_40 (1 << 6)
-
-static long polltime = 25000000;
-module_param(polltime, long, 0644);
-MODULE_PARM_DESC(polltime, "How long to wait between polls (in nano seconds).");
-
-static struct rmi_application *app;
-
-/* TODO: We should move this to the application data struct and allow more than
- one input device per system. We'll address in a follow up patch. */
-static struct input_dev *input;
-
-/* RMI4 device control == function 0x01 */
-extern unsigned short fn01ControlBaseAddr;
-/* number of total interrupt registers to read */
-extern unsigned int interruptRegisterCount;
-
-
-/**
- * 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 *rpd, int instance)
-{
- /* All we have to do is schedule work. */
- schedule_work(&(rpd->app->work));
-}
-
-/**
- * This is the meat of the driver. It reads in all data sources and reports
- * them to the input subsystem. It is used for both polling and interrupt
- * driven operation.
- */
-int report_sensor_data(struct rmi_application *app)
-{
- unsigned char interruptStatus[4] = {0, 0, 0, 0};
- int touch; /* number of touch points - fingers or buttons */
- struct rmi_functions *fn;
- struct rmi_function_info *rfi;
- struct rmi_phys_driver *rpd;
- struct rmi_module_info *rmi;
- static int num_error_reports;
-
- touch = 0;
-
- /* Get the interrupt status from the function $01 control register+1 to
- find which source(s) were interrupting so we can read the data from the
- source(s) (2D sensor, buttons, etc.).
- */
- if (rmi_read_multiple(app, fn01ControlBaseAddr + 1,
- interruptStatus, interruptRegisterCount)) {
- printk(KERN_ERR "%s: Could not read interrupt status registers 0x%x\n",
- __func__, fn01ControlBaseAddr + 1);
- return 0;
- }
-
- /* check each function that has data sources and if the interrupt for
- * that triggered then call that RMI4 functions report() function to
- * gather data and report it to the input subsystem */
- rpd = app->rpd; /* get ptr to rmi_physical_driver from app */
- rmi = &(rpd->rmi); /* get ptr to rmi_module_info from physical driver */
-
- list_for_each_entry(rfi, &rmi->functions, link) {
- if (rfi->numSources) {
- if (interruptStatus[rfi->interruptRegister] &
- rfi->interruptMask) {
- bool found;
- found = false;
- fn = rmi_find_function(rfi->functionNum);
- if (fn) {
- found = true;
- if (fn->report) {
- touch = fn->report(app,
- rfi, fn->input);
- } else {
- num_error_reports++;
- if (num_error_reports < 6) {
- /* the developer did not add in the
- pointer to the report function into
- rmi4_supported_data_src_functions */
- printk(KERN_ERR "%s: no find report function for function 0x%x\n", __func__, fn->functionNum);
- }
- }
- }
-
- if (!found) {
- num_error_reports++;
- if (num_error_reports < 6) {
- /* 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.
- */
- printk(KERN_ERR "%s: could not find any support for function 0x%x\n", __func__, fn->functionNum);
- }
- }
- }
- }
- }
-
- /* return the number of touch points - fingers down and/or buttons
- * pressed, etc. */
- return touch;
-}
-
-/* This is the worker function - it simply has to call report_sensor_data. */
-static void ts_work_func(struct work_struct *work)
-{
- struct rmi_application *app = container_of(work,
- struct rmi_application, work);
-
- report_sensor_data(app);
-
- /* we only need to enable the irq if doing interrupts */
- if (!rmi_polling_required(app))
- enable_irq(app->rpd->irq);
-}
-
-/* This is the timer function for polling - it simply has to schedule work
- * and restart the timer. */
-static enum hrtimer_restart ts_poll_timer_func(struct hrtimer *timer)
-{
- struct rmi_application *app = container_of(timer,
- struct rmi_application, timer);
-
- schedule_work(&app->work);
- hrtimer_start(&app->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.
- */
-static int probe(struct rmi_application *app,
- const struct rmi_module_info *rmi)
-{
- struct rmi_function_info *rfi;
- int data_sources = 0;
- int retval = 0;
-
- if (!rmi) {
- printk(KERN_ERR "%s: Invalid module info: %p\n", __func__, rmi);
- return 0;
- }
-
- /* Check if this is a Synaptics device - report if not. */
- if (rmi->mfgid != 1) { /* Synaptics? */
- printk(KERN_INFO "%s: non-Synaptics mfg id: %d\n",
- __func__, rmi->mfgid);
- }
-
- /* for each function entry in the list accumulate it's number of data
- sources */
- list_for_each_entry(rfi, &rmi->functions, link) {
- data_sources += rfi->numSources;
- }
-
- if (data_sources) {
- retval = 1;
- /* We have detected one or more data sources such as
- 2D Sensors, buttons, etc. */
- printk(KERN_INFO "%s: Found %d data sources for : %p\n",
- __func__, data_sources, rmi);
- } else {
- /* we don't have any data sources for this sensor - oops!
- - either an un-flashed sensor or bad!! */
- printk(KERN_INFO "%s: No data sources found for : %p\n",
- __func__, rmi);
- }
-
- return retval;
-}
-
-static void config(struct rmi_application *app)
-{
- /* For each data source we had detected print info and set up interrupts
- or polling. */
- struct rmi_function_info *rfi;
- struct rmi_phys_driver *rpd;
- struct rmi_module_info *rmi;
-
- rpd = app->rpd; /* get ptr to rmi_physical_driver from app */
- rmi = &(rpd->rmi); /* get ptr to rmi_module_info from physical driver */
-
- list_for_each_entry(rfi, &rmi->functions, link) {
- if (rfi->numSources) {
- /* This function has data sources associated with it.*/
- /* Get and print some info about the data sources... */
- struct rmi_functions *fn;
- bool found = false;
- /* check if function number matches - if so call that
- config function */
- fn = rmi_find_function(rfi->functionNum);
- if (fn) {
- found = true;
- if (fn->config) {
- fn->config(app, rfi);
- } else {
- /* the developer did not add in the
- pointer to the config function into
- rmi4_supported_data_src_functions */
- printk(KERN_ERR
- "%s: no config function for "
- "function 0x%x\n",
- __func__, rfi->functionNum);
- break;
- }
- }
-
- if (!found) {
- /* 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 */
- printk(KERN_ERR"%s: could not find support "
- "for function 0x%x\n",
- __func__, rfi->functionNum);
- }
-
- /* if we are not doing polling then enable the
- interrupts for the data sources for this function */
- if (!rmi_polling_required(app)) {
- /* Turn on interrupts for this
- function's data sources. */
- rmi_write(app, fn01ControlBaseAddr + 1 +
- rfi->interruptRegister,
- rfi->interruptMask);
- printk(KERN_INFO
- "%s: Interrupt Driven - turning on "
- "interrupts for function 0x%x\n",
- __func__, rfi->functionNum);
- }
- }
- }
-
- /* if we are not polling we need to set up the interrupt worker
- thread - otherwise we need to set up the polling callback and
- worker thread. */
- if (!rmi_polling_required(app)) {
- /* We're interrupt driven, so set up packet rate and the worker
- thread function. */
- if (HZ < 500) {
- /* The default packet rate of 80 packets per
- * second is too fast (the Linux time slice for
- * sub-GHz processors is only 100 times per second).
- * So re-program it to 40 packets per second.
- */
- rmi_write(app, fn01ControlBaseAddr, RMI_REPORT_RATE_40);
- }
-
- INIT_WORK(&app->work, ts_work_func);
-
- } else {
- /* We're polling driven, so set up the polling timer
- and timer function. */
- INIT_WORK(&app->work, ts_work_func);
- hrtimer_init(&app->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- app->timer.function = ts_poll_timer_func;
- hrtimer_start(&app->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
- }
-}
-
-/**
- * The module initialization function in which we register as a RMI4
- * application driver. We also register with the input subsystem so we can
- * pass coordinates to it.
- */
-static int __init rmi_app_touchpad_init(void)
-{
- int retval;
-
- retval = 0;
-
- pr_debug("%s: RMI4 TouchPad Driver\n", __func__);
-
- /* NOTE: we are creating only one input dev file for this but
- theoretically you could create a separate one for each data
- source and store it below. This will let you put 2D sensor
- events into one dev file, button events into a separate dev file,
- other data source event like GPIOs, etc. into yet a third dev file.
- As this is being coded it will dump all events into the one dev file.
- */
- input = input_allocate_device();
- if (input == NULL) {
- printk(KERN_ERR "%s: Failed to allocate memory for a "
- "new input device.\n",
- __func__);
- return -ENOMEM;
- }
-
- input->name = "RMI4 Touchpad";
- input->phys = "rmi_app_touchpad";
-
- /* Set input device specific params for each data source...*/
- retval = rmi_functions_init(input);
-
- if (retval) {
- printk(KERN_ERR "%s: Failed rmi_functions_init.\n", __func__);
- return retval;
- }
-
- retval = input_register_device(input);
-
- if (retval) {
- printk(KERN_ERR "%s: Failed input_register_device.\n",
- __func__);
- return retval;
- }
-
- app = rmi_register_application("rmi4_touchpad",
- attention, probe, config);
-
- if (!app) {
- printk(KERN_ERR "%s: Failed to register app.\n", __func__);
- input_unregister_device(input);
- retval = -ENODEV;
- }
-
- return retval;
-}
-
-static void __exit rmi_app_touchpad_exit(void)
-{
- pr_debug("%s: RMI4 TouchPad Driver\n", __func__);
-
- /* Stop the polling timer if doing polling */
- if (rmi_polling_required(app))
- hrtimer_cancel(&app->timer);
-
- flush_scheduled_work(); /* Make sure all scheduled work is stopped */
-
- /* Unregister everything */
- printk(KERN_WARNING "%s: Unregistering app - %s\n",
- __func__, app->name);
- rmi_unregister_application(app);
- input_unregister_device(input);
-}
-
-module_init(rmi_app_touchpad_init);
-module_exit(rmi_app_touchpad_exit);
-
-MODULE_AUTHOR("Synaptics, Inc.");
-MODULE_DESCRIPTION("RMI4 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi_bus.c b/drivers/input/touchscreen/rmi_bus.c
new file mode 100755
index 0000000..289fe40
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_bus.c
@@ -0,0 +1,393 @@
+/**
+ * Synaptics Register Mapped Interface (RMI4) - RMI Bus Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ * Impliments "rmi" bus per Documentation/driver-model/bus.txt
+ *
+ * This protocol is layered as follows.
+ *
+ *
+ *
+ * +-------+ +-------+ +-------+ +--------+
+ * | Fn32 | | Fn11| | Fn19 | | Fn11 | Devices/Functions
+ * *---|---+ +--|----+ +----|--+ +----|---* (2D, cap. btns, etc.)
+ * | | | |
+ * +----------------+ +----------------+
+ * | Sensor0 | | Sensor1 | Sensors Dev/Drivers
+ * +----------------+ +----------------+ (a sensor has one or
+ * | | more functions)
+ * | |
+ * +----------------------------------------+
+ * | |
+ * | RMI4 Bus | RMI Bus Layer
+ * | (this file) |
+ * *--|-----|------|--------------|---------*
+ * | | | |
+ * | | | |
+ * +-----+-----+-------+--------------------+
+ * | I2C | SPI | SMBus | etc. | Physical Layer
+ * +-----+-----+-------+--------------------+
+ *
+ */
+/*
+ * 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/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+
+/* list of physical drivers - i2c, spi, etc. */
+static LIST_HEAD(phys_drivers);
+static DEFINE_MUTEX(phys_drivers_mutex);
+
+/* list of sensors found on a physical bus (i2c, smi, etc.)*/
+static LIST_HEAD(sensor_drivers);
+static DEFINE_MUTEX(sensor_drivers_mutex);
+static LIST_HEAD(sensor_devices);
+static DEFINE_MUTEX(sensor_devices_mutex);
+
+#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)
+{
+ return !strncmp(dev->bus->name, driver->name, strlen(driver->name));
+}
+
+/*
+ * 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_sensors(struct rmi_phys_driver *rpd)
+{
+ unsigned short fn01QueryBaseAddr; /* RMI4 device control */
+ unsigned short fn01ControlBaseAddr;
+ unsigned int interruptRegisterCount;
+ int i;
+ struct rmi_sensor_device *rmi_sensor_dev;
+ unsigned char interruptCount;
+ struct rmi_function_info *rfi;
+ 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) {
+ printk(KERN_ERR "%s: Physical driver must specify a name\n",
+ __func__);
+ return -EINVAL;
+ }
+ if (!rpd->write) {
+ printk(KERN_ERR
+ "%s: Physical driver %s must specify a writer.\n",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+ if (!rpd->read) {
+ printk(KERN_ERR
+ "%s: Physical driver %s must specify a reader.\n",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+ if (!rpd->write_multiple) {
+ printk(KERN_ERR "%s: Physical driver %s must specify a "
+ "multiple writer.\n",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+ if (!rpd->read_multiple) {
+ printk(KERN_ERR "%s: Physical driver %s must specify a "
+ "multiple reader.\n",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+
+ /* Get some information from the device */
+ {
+ pr_debug("%s: Scanning for Sensors (Fn $01):\n", __func__);
+
+ rmi_sensor_dev = NULL;
+ interruptCount = 0;
+
+ /* init the physical drivers RMI module
+ info list of functions */
+ INIT_LIST_HEAD(&rpd->rmi.functions);
+
+ /* Read the Page Descriptor Table to determine what functions
+ are present */
+ for (i = PDT_START_SCAN_LOCATION; /* Register the rmi sensor driver */
+ i >= PDT_END_SCAN_LOCATION;
+ i -= PDT_ENTRY_SIZE) {
+ retval = rpd->read_multiple(rpd, i, (char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (!retval) {
+ rfi = NULL;
+
+ if (rmi_fd.functionNum != 0x00 && rmi_fd.functionNum != 0xff) {
+ switch (rmi_fd.functionNum & 0xff) {
+ case 0x01:
+ pr_debug("%s: Fn $01 Found - RMI Device Control\n", __func__);
+ /* Save Fn $01 query and control base addresses since
+ we'll need them later to get/set properties and check
+ interrupts. There is only one Fn $01 for the device
+ that is used to control and query device specific info
+ so we only need to save it globally here for later use.
+ */
+ fn01QueryBaseAddr =
+ rmi_fd.queryBaseAddr;
+ fn01ControlBaseAddr =
+ rmi_fd.controlBaseAddr;
+
+ /* Create a sensor device and sensor driver for each Fn $01 */
+ rmi_sensor_dev = kzalloc(sizeof(*rmi_sensor_dev), GFP_KERNEL);
+ if (!rmi_sensor_dev) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_sensor_device\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Register the rmi sensor device */
+ retval = rmi_sensor_register_device(rmi_sensor_dev, index++);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: Error %d registering sensor device\n", __func__, retval);
+ goto exit_fail;
+ }
+
+ rmi_sensor_dev->driver = kzalloc(sizeof(struct rmi_sensor_driver), GFP_KERNEL);
+ if (!rmi_sensor_dev->driver) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_sensor_driver\n", __func__);
+ return -ENOMEM;
+ }
+
+ rmi_sensor_dev->driver->sensorQueryBaseAddr = rmi_fd.queryBaseAddr;
+ rmi_sensor_dev->driver->sensorControlBaseAddr = rmi_fd.controlBaseAddr;
+ rmi_sensor_dev->driver->sensorDataBaseAddr = rmi_fd.dataBaseAddr;
+ rmi_sensor_dev->driver->sensorCommandBaseAddr = rmi_fd.commandBaseAddr;
+ rmi_sensor_dev->driver->rpd = rpd;
+
+ retval = rmi_sensor_register_driver(rmi_sensor_dev->driver);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: Error %d registering sensor driver\n", __func__, retval);
+ goto exit_fail;
+ }
+
+ /* Add it into the list of sensors on the rmi bus */
+ mutex_lock(&sensor_devices_mutex);
+ list_add_tail(&rmi_sensor_dev->sensors, &sensor_devices);
+ mutex_unlock(&sensor_devices_mutex);
+
+ break;
+
+ default:
+ /* Just print out the function found for now */
+ printk(KERN_INFO "%s: Found Function %02x - Ignored.\n", __func__, rmi_fd.functionNum & 0xff);
+ break;
+ }
+
+ /* bump interrupt count */
+ interruptCount +=
+ (rmi_fd.interruptSrcCnt & 0x7);
+
+
+ } else {
+ /* A zero or 0xff in the function number
+ signals the end of the PDT */
+ pr_debug("%s: Found End of PDT\n",
+ __func__);
+ break;
+ }
+ } else {
+ /* 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. */
+ printk(KERN_ERR "%s: Read Error 0x%x when "
+ "reading next PDT entry - "
+ "ending PDT scan.\n",
+ __func__, retval);
+ break;
+ }
+ }
+
+ /* Make sure we found a sensor (Fn $01) */
+ if (rmi_sensor_dev) {
+ /* calculate the interrupt register count - used in the
+ ISR to read the correct number of interrupt registers */
+ interruptRegisterCount = (interruptCount + 7) / 8;
+ rmi_sensor_dev->driver->interruptRegisterCount = interruptRegisterCount;
+
+ /* Add physical driver struct to list */
+ mutex_lock(&phys_drivers_mutex);
+ list_add_tail(&rpd->drivers, &phys_drivers);
+ mutex_unlock(&phys_drivers_mutex);
+ }
+
+ pr_debug("%s: Registered sensor drivers.\n", __func__);
+ }
+
+ return 0;
+
+exit_fail:
+ return retval;
+}
+EXPORT_SYMBOL(rmi_register_sensors);
+
+int rmi_unregister_sensors(struct rmi_phys_driver *rpd)
+{
+ if (rpd->sensor) {
+ printk(KERN_WARNING "%s: WARNING: unregister of %s while %s still attached\n",
+ __func__, rpd->name, rpd->sensor->drv.name);
+ }
+
+ pr_debug("%s: Unregistering sensor drivers %s\n", __func__, rpd->name);
+
+ mutex_lock(&sensor_drivers_mutex);
+ list_del(&rpd->sensor->sensor_drivers);
+ mutex_unlock(&sensor_drivers_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(rmi_unregister_sensors);
+
+
+static void rmi_bus_dev_release(struct device *dev)
+{
+ printk(KERN_DEBUG "rmi bus device release\n");
+}
+
+
+int rmi_register_bus_device(struct device *rmibusdev)
+{
+ printk(KERN_DEBUG "%s: Registering 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;
+
+ /* 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)
+{
+ printk(KERN_DEBUG "%s: Unregistering bus device.\n", __func__);
+
+ device_unregister(rmibusdev);
+}
+EXPORT_SYMBOL(rmi_unregister_bus_device);
+
+static int __init rmi_bus_init(void)
+{
+ int status;
+
+ status = 0;
+
+ printk(KERN_INFO "%s: RMI Bus Driver Init\n", __func__);
+
+ /* Register the rmi bus */
+ rmi_bus_type.name = busname;
+ rmi_bus_type.match = rmi_bus_match;
+ status = bus_register(&rmi_bus_type);
+ if (status < 0) {
+ printk(KERN_ERR "%s: Error %d registering the rmi bus\n", __func__, status);
+ goto err2;
+ }
+
+ /* Register the rmi bus device - "rmi". There is only one rmi bus device. */
+ status = rmi_register_bus_device(&rmi_bus_device);
+ if (status < 0) {
+ printk(KERN_ERR "%s: Error %d registering rmi bus device\n", __func__, status);
+ goto err1;
+ }
+
+ return 0;
+err1:
+ bus_unregister(&rmi_bus_type);
+err2:
+ return status;
+}
+
+static void __exit rmi_bus_exit(void)
+{
+ printk(KERN_DEBUG "%s: RMI Bus Driver Exit\n", __func__);
+
+ /* Unregister the rmi bus device - "rmi". There is only one rmi bus device. */
+ rmi_unregister_bus_device(&rmi_bus_device);
+
+ /* Unregister the rmi bus */
+ bus_unregister(&rmi_bus_type);
+}
+
+
+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_bus.h b/drivers/input/touchscreen/rmi_bus.h
new file mode 100755
index 0000000..9a0bdf3
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_bus.h
@@ -0,0 +1,41 @@
+/**
+ *
+ * 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.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_BUS_H
+#define _RMI_BUS_H
+
+
+struct rmi_bus_device {
+ char *name;
+ struct rmi_bus_driver *driver;
+ struct device dev;
+};
+#define to_rmi_bus_device(dev) container_of(dev, struct rmi_bus_device, dev);
+
+
+extern struct bus_type rmi_bus_type;
+
+#endif
+
diff --git a/drivers/input/touchscreen/rmi_core.c b/drivers/input/touchscreen/rmi_core.c
deleted file mode 100644
index d25f982..0000000
--- a/drivers/input/touchscreen/rmi_core.c
+++ /dev/null
@@ -1,708 +0,0 @@
-/**
- * Synaptics Register Mapped Interface (RMI4) Data Layer Driver.
- * Copyright (C) 2007 - 2010, Synaptics Incorporated
- *
- *
- * This protocol is layered as follows.
- *
- *
- * +----------------------------------------+
- * | |
- * | Application |
- * | |
- * +----------------------------------------+
- * | |
- * | RMI4 Driver | Data Layer (THIS DRIVER)
- * | (this file) |
- * +-----+-----+-------+----------+---------+
- * | I2C | SPI | SMBus | etc. | Physical Layer
- * +-----+-----+-------+----------+---------+
- *
- * Each of the physical layer drivers is contained in a file called
- * rmi_phys_xxx.c. Someone compiling the kernel enables CONFIG_RMI and then
- * one or more CONFIG_RMI_xxx options in the .config file. For example, when
- * CONFIG_RMI_I2C=m is enabled, a rmi.ko and a rmi_phys_i2c.ko will be
- * compiled. rmi_phys_i2c.ko will depend on rmi.ko, so when rmi_phys_i2c.ko
- * is loaded, rmi.ko will automatically be loaded. Each of the physical
- * layer drivers is a platform_driver that may handle suspend/resume, etc.,
- * so this driver does not do so.
- *
- * The register paradigm of RMI is a "pull" rather than "push" data flow.
- * As such, it is the application driver that needs to implement either
- * polling or interrupt driven, and the physical driver merely handles
- * the register accesses. For interrupt driven, the application registers
- * an "attention" function that may be called in interrupt context by the
- * physical driver if an attention interrupt is available. The physical
- * driver notifies the application through the polling_required variable,
- * and the application driver must do one or the other based on this variable.
- *
- * At this point in time, there can only be one application driver per
- * physical driver.
- *
- */
-/*
- * 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 drvname[] = "rmi4_ts";
-
-#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 "rmi.h"
-#include "rmi_core.h"
-#include "rmi_functions.h"
-
-/* we need these to control the device and query interrupts */
-unsigned short fn01QueryBaseAddr; /* RMI4 device control */
-EXPORT_SYMBOL(fn01QueryBaseAddr);
-unsigned short fn01ControlBaseAddr;
-EXPORT_SYMBOL(fn01ControlBaseAddr);
-unsigned int interruptRegisterCount;
-EXPORT_SYMBOL(interruptRegisterCount);
-
-#define PDT_START_SCAN_LOCATION 0x00E9
-#define PDT_END_SCAN_LOCATION 0x000A
-#define PDT_ENTRY_SIZE 0x0006
-
-static LIST_HEAD(phys_drivers);
-static DEFINE_MUTEX(phys_drivers_mutex);
-static LIST_HEAD(app_drivers);
-static DEFINE_MUTEX(app_drivers_mutex);
-static DEFINE_MUTEX(rfi_mutex);
-static LIST_HEAD(fns_list);
-static DEFINE_MUTEX(fns_mutex);
-
-
-#if RMI_ALLOC_STATS
-int appallocsrmi;
-EXPORT_SYMBOL(appallocsrmi);
-int rfiallocsrmi;
-EXPORT_SYMBOL(rfiallocsrmi);
-int fnallocsrmi;
-EXPORT_SYMBOL(fnallocsrmi);
-#endif
-
-/* 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. These only need to
- be added for RMI4 functions that support data source - like 2D sensors,
- buttons, LEDs, GPIOs, etc. Refer to the RMI4 specification for
- information on these RMI4 functions and what data they report.
-*/
-
-static struct rmi_functions_data
- rmi4_supported_data_src_functions[rmi4_num_supported_data_src_fns] = {
- /* Fn $11 */
- {0x11, FN_11_report, FN_11_config, FN_11_init, FN_11_detect},
- /* Fn $19 */
- /* {0x19, FN_19_report, FN_19_config, FN_19_init, FN_19_detect), */
-};
-
-
-int rmi_read(struct rmi_application *app, unsigned short address, char *dest)
-{
- struct rmi_phys_driver *rpd = app->rpd;
- if (!app->rpd)
- return -ENODEV;
- return rpd->read(rpd, address, dest);
-}
-EXPORT_SYMBOL(rmi_read);
-
-int rmi_write(struct rmi_application *app, unsigned short address,
- unsigned char data)
-{
- struct rmi_phys_driver *rpd = app->rpd;
- if (!app->rpd)
- return -ENODEV;
- return rpd->write(rpd, address, data);
-}
-EXPORT_SYMBOL(rmi_write);
-
-int rmi_read_multiple(struct rmi_application *app, unsigned short address,
- char *dest, int length)
-{
- struct rmi_phys_driver *rpd = app->rpd;
- if (!app->rpd)
- return -ENODEV;
- return rpd->read_multiple(rpd, address, dest, length);
-}
-EXPORT_SYMBOL(rmi_read_multiple);
-
-int rmi_write_multiple(struct rmi_application *app, unsigned short address,
- unsigned char *data, int length)
-{
- struct rmi_phys_driver *rpd = app->rpd;
- if (!app->rpd)
- return -ENODEV;
- return rpd->write_multiple(rpd, address, data, length);
-}
-EXPORT_SYMBOL(rmi_write_multiple);
-
-bool rmi_polling_required(struct rmi_application *app)
-{
- return app->polling_required;
-}
-EXPORT_SYMBOL(rmi_polling_required);
-
-/* This function searches for a match between an app driver and physical
- * driver and binds them together.
- */
-static void match_and_bind(struct rmi_application *app,
- struct rmi_phys_driver *rpd)
-{
- app->polling_required = rpd->polling_required;
-
- if (app->probe(app, &rpd->rmi)) {
- /* Found a match, bind them together. */
- /* The try_module_get() makes sure that the physical
- * driver cannot be unloaded while a app driver is
- * using it.
- */
- if (try_module_get(rpd->module)) {
- app->rpd = rpd;
- rpd->app = app;
- printk(KERN_INFO "%s: %s is %s bound to %s\n",
- __func__, drvname, app->name, rpd->name);
- rpd->attention = app->attention;
- app->config(app);
- }
- } else {
- app->polling_required = false;
- }
-}
-
-/* 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_functions *rmi_find_function(int functionNum)
-{
- struct rmi_functions *fn;
- bool found = false;
-
- list_for_each_entry(fn, &fns_list, link) {
- if (functionNum == fn->functionNum) {
- found = true;
- break;
- }
- }
-
- if (!found)
- return NULL;
- else
- return fn;
-}
-EXPORT_SYMBOL(rmi_find_function);
-
-/* This function calls init for all of the functions on the functions list and
- * passes in the input_dev ptr so that each fn can store it for later use.
- */
-int rmi_functions_init(struct input_dev *inputdev)
-{
- int retval = 0;
- struct rmi_functions *fn;
-
- /* Set input device specific params for each data source...*/
- list_for_each_entry(fn, &fns_list, link) {
- if (fn->init) {
- /* store the input_dev ptr for use later */
- fn->input = inputdev;
- retval = fn->init(fn->input);
- } else {
- /* the developer did not add in the pointer to the init
- function into rmi4_supported_data_src_functions */
- printk(KERN_ERR
- "%s: No init function for function 0x%x\n",
- __func__, fn->functionNum);
- }
- }
-
- return retval;
-}
-EXPORT_SYMBOL(rmi_functions_init);
-
-int rmi_register_phys_driver(struct rmi_phys_driver *rpd)
-{
- struct rmi_application *app;
- int i;
- unsigned char std_queries[21];
- unsigned char interruptCount;
- struct rmi_function_info *rfi;
- struct rmi_function_descriptor rmi_fd;
- struct rmi_functions *fn;
- bool found;
- int retval;
-
- if (!rpd->name) {
- printk(KERN_ERR "%s: %s: Physical driver must specify a name\n",
- __func__, drvname);
- return -EINVAL;
- }
- if (!rpd->write) {
- printk(KERN_ERR
- "%s: %s: Physical driver %s must specify a writer.\n",
- __func__, drvname, rpd->name);
- return -EINVAL;
- }
- if (!rpd->read) {
- printk(KERN_ERR
- "%s: %s: Physical driver %s must specify a reader.\n",
- __func__, drvname, rpd->name);
- return -EINVAL;
- }
- if (!rpd->write_multiple) {
- printk(KERN_ERR "%s: %s: Physical driver %s must specify a "
- "multiple writer.\n",
- __func__, drvname, rpd->name);
- return -EINVAL;
- }
- if (!rpd->read_multiple) {
- printk(KERN_ERR "%s: %s: Physical driver %s must specify a "
- "multiple reader.\n",
- __func__, drvname, rpd->name);
- return -EINVAL;
- }
- if (!rpd->module) {
- printk(KERN_ERR
- "%s: %s: Physical driver %s must specify a module.\n",
- __func__, drvname, rpd->name);
- return -EINVAL;
- }
-
- pr_debug("%s: %s: Registering phys driver %s\n",
- __func__, drvname, rpd->name);
-
- rpd->attention = 0;
-
- /* Get some information from the device */
- {
- pr_debug("%s: Functions:\n", __func__);
-
- interruptCount = 0;
-
- /* init the physical drivers RMI module
- info list of functions */
- INIT_LIST_HEAD(&rpd->rmi.functions);
-
- /* Read the Page Descriptor Table to determine what functions
- are present */
- 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) {
- rfi = NULL;
-
- if (rmi_fd.functionNum != 0x00 && rmi_fd.functionNum != 0xff) {
- switch (rmi_fd.functionNum & 0xff) {
- case 0x01:
- pr_debug("%s: Fn $01 Found - RMI Device Control\n", __func__);
- /* Save Fn $01 query and control base addresses since
- we'll need them later to get/set properties and check
- interrupts. There is only one Fn $01 for the device
- that is used to control and query device specific info
- so we only need to save it globally here for later use.
- */
- fn01QueryBaseAddr =
- rmi_fd.queryBaseAddr;
- fn01ControlBaseAddr =
- rmi_fd.controlBaseAddr;
- break;
-
- default:
- if (rmi_fd.interruptSrcCnt) {
- rfi = kmalloc(sizeof(*rfi), GFP_KERNEL);
-
- if (!rfi) {
- printk(KERN_ERR "%s: %s: could not allocate memory for function 0x%x\n",
- __func__, drvname, rmi_fd.functionNum);
- retval = -ENOMEM;
- goto exit_fail;
- } else {
- INC_ALLOC_STAT(rfi);
-
- /* Get the ptr to the detect function based on
- the function number */
- found = false;
- list_for_each_entry(fn, &fns_list, link) {
- /* check if function number matches - if so
- call that detect function */
- if (fn->functionNum == rmi_fd.functionNum) {
- found = true;
- fn->detect(rpd->app, rfi, &rmi_fd,
- interruptCount);
- }
- }
-
- if (!found) {
- printk(KERN_ERR "%s: %s: could not find support for function 0x%x\n",
- __func__, drvname, rmi_fd.functionNum);
- }
- }
- } else {
- printk(KERN_INFO "%s: %s: Found Function %02x - Ignored.\n", __func__, drvname, rmi_fd.functionNum & 0xff);
- }
- break;
- }
-
- /* bump interrupt count for
- next iteration */
- interruptCount +=
- (rmi_fd.interruptSrcCnt & 0x7);
-
- /* We only want to add functions
- to the list that have
- data associated with them. */
- if (rfi && rmi_fd.interruptSrcCnt) {
- pr_debug("%s: Adding function "
- "0x%x with %d sources.\n",
- drvname, rfi->functionNum,
- rfi->numSources);
-
- /* link this function info to
- the RMI module infos list
- of functions */
- mutex_lock(&rfi_mutex);
- list_add_tail(&rfi->link,
- &rpd->rmi.functions);
- mutex_unlock(&rfi_mutex);
- }
- } else {
- /* A zero in the function number
- signals the end of the PDT */
- pr_debug("%s: Found End of PDT\n",
- __func__);
- break;
- }
- } else {
- /* 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. */
- printk(KERN_ERR "%s: %s: Read Error 0x%x when "
- "reading next PDT entry - "
- "ending PDT scan.\n",
- __func__, drvname, retval);
- break;
- }
- }
-
- /* calculate the interrupt register count - used in the
- ISR to read the correct number of interrupt registers */
- interruptRegisterCount = (interruptCount + 7) / 8;
-
- /* Function $01 will be used to query the product properties,
- and product ID so we had to read the PDT above first to get
- the Fn $01 query address and prior to filling in the product
- info. NOTE: Even an unflashed device will still have FN $01.
- */
-
- /* Load up the standard queries and get the RMI4 module info */
- retval = rpd->read_multiple(rpd, fn01QueryBaseAddr, std_queries,
- sizeof(std_queries));
- if (retval) {
- printk(KERN_ERR "%s: %s: Failed reading queries\n",
- __func__, drvname);
- retval = -EIO;
- goto exit_fail;
- }
-
- /* Currently supported RMI version is 4.0 */
- rpd->rmi.rmi_maj_ver = 4;
- rpd->rmi.rmi_min_ver = 0;
-
- /* get manufacturer id, properties, product info,
- date code, tester id, serial num and product id (name) */
- rpd->rmi.mfgid = std_queries[0];
- rpd->rmi.properties = std_queries[1];
-
- rpd->rmi.prod_info[0] = std_queries[2];
- rpd->rmi.prod_info[1] = std_queries[3];
-
- /* year - 2001-2032 */
- rpd->rmi.date_code[0] = std_queries[4] & 0x1f;
- /* month - 1-12 */
- rpd->rmi.date_code[1] = std_queries[5] & 0x0f;
- /* day - 1-31 */
- rpd->rmi.date_code[2] = std_queries[6] & 0x1f;
-
- rpd->rmi.tester_id = ((std_queries[7] & 0x7f) << 8) |
- (std_queries[8] & 0x7f);
-
- rpd->rmi.serial_num = ((std_queries[9] & 0x7f) << 8) |
- (std_queries[10] & 0x7f);
-
- memcpy(rpd->rmi.prod_id, &std_queries[11], 10);
- rpd->rmi.prod_id[10] = 0;
-
- pr_debug("%s: RMI Protocol: %d.%d\n",
- __func__, rpd->rmi.rmi_maj_ver, rpd->rmi.rmi_min_ver);
- pr_debug("%s: Manufacturer: %d", __func__,
- rpd->rmi.mfgid);
-
- if (rpd->rmi.mfgid == 1)
- pr_debug(" (Synaptics)");
- pr_debug("\n");
-
- pr_debug("%s: Properties: 0x%x\n",
- __func__, rpd->rmi.properties);
- pr_debug("%s: Product Info: 0x%x 0x%x\n",
- __func__, rpd->rmi.prod_info[0], rpd->rmi.prod_info[1]);
- pr_debug("%s: Date Code: Year : %d Month: %d Day: %d\n",
- __func__, rpd->rmi.date_code[0], rpd->rmi.date_code[1],
- rpd->rmi.date_code[2]);
- pr_debug("%s: Tester ID: %d\n", __func__, rpd->rmi.tester_id);
- pr_debug("%s: Serial Number: 0x%x\n",
- __func__, rpd->rmi.serial_num);
- pr_debug("%s: Product ID: %s\n", __func__, rpd->rmi.prod_id);
- }
-
- /* Add physical driver struct to list */
- mutex_lock(&phys_drivers_mutex);
- list_add_tail(&rpd->drivers, &phys_drivers);
- mutex_unlock(&phys_drivers_mutex);
-
- /* Do a probe for any applications that are registered and bind this
- physical driver to them */
- list_for_each_entry(app, &app_drivers, apps) {
- /* Only check apps that are not already bound */
- if (!app->rpd)
- match_and_bind(app, rpd);
- }
-
- pr_debug("%s: Registered phys driver %s\n", __func__, rpd->name);
-
- return 0;
-
-exit_fail:
- return retval;
-}
-EXPORT_SYMBOL(rmi_register_phys_driver);
-
-int rmi_unregister_phys_driver(struct rmi_phys_driver *rpd)
-{
- if (rpd->app) {
- printk(KERN_WARNING "%s: %s: WARNING: unregister of %s while %s still attached\n",
- __func__, drvname, rpd->name, rpd->app->name);
- }
-
- pr_debug("%s: Unregistering phys driver %s\n", __func__, rpd->name);
- mutex_lock(&phys_drivers_mutex);
- list_del(&rpd->drivers);
- mutex_unlock(&phys_drivers_mutex);
-
- return 0;
-}
-EXPORT_SYMBOL(rmi_unregister_phys_driver);
-
-struct rmi_application *rmi_register_application(const char *name,
- void (*attention)(struct rmi_phys_driver *pd, int instance),
- int (*probe)(struct rmi_application *app,
- const struct rmi_module_info *rmi),
- void (*config)(struct rmi_application *app))
-{
- struct rmi_application *app;
- struct rmi_phys_driver *rpd;
-
- if (!name) {
- printk(KERN_ERR "%s: %s: Application driver must specify a name\n",
- __func__, drvname);
- return 0;
- }
-
- if (!attention) {
- printk(KERN_ERR "%s: %s: Application driver %s must specify attention notifier.\n",
- __func__, drvname, name);
- return 0;
- }
-
- if (!probe) {
- printk(KERN_ERR "%s: %s: Application driver %s must specify a probe function.\n",
- __func__, drvname, name);
- return 0;
- }
-
- if (!config) {
- printk(KERN_ERR "%s: %s: Application driver %s must specify a config function.\n",
- __func__, drvname, name);
- return 0;
- }
-
- pr_debug("%s: Registering app driver %s\n", __func__, name);
-
- app = kmalloc(sizeof(*app), GFP_KERNEL);
- if (!app) {
- printk(KERN_ERR "%s: %s: Out of memory\n", __func__, drvname);
- return 0;
- }
- INC_ALLOC_STAT(app);
-
- app->name = name;
- app->attention = attention;
- app->probe = probe;
- app->config = config;
- app->rpd = 0;
-
- mutex_lock(&app_drivers_mutex);
- list_add_tail(&app->apps, &app_drivers);
- mutex_unlock(&app_drivers_mutex);
-
- /* Probe for any matches with physical drivers and bind them. */
- list_for_each_entry(rpd, &phys_drivers, drivers) {
- if (!rpd->app)
- match_and_bind(app, rpd);
- }
-
- pr_debug("%s: Registered app driver %s (%p)\n", __func__, name, app);
-
- return app;
-}
-EXPORT_SYMBOL(rmi_register_application);
-
-void rmi_unregister_application(struct rmi_application *app)
-{
- struct rmi_application *tmp;
- int found = 0;
-
- if (!app)
- return;
-
- pr_debug("%s: Unregistering app driver %s (%p)\n",
- __func__, app->name, app);
-
- list_for_each_entry(tmp, &app_drivers, apps) {
- if (tmp == app) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- printk(KERN_ERR "%s: %s: Removing rmi application %s: not found\n",
- __func__, drvname, app->name);
- return;
- }
-
- if (app->rpd) {
- /* Release the phys driver so it can be unloaded. */
- module_put(app->rpd->module);
- app->rpd->app = 0;
- }
-
- list_del(&app->apps);
- kfree(app);
- DEC_ALLOC_STAT(app);
-
- pr_debug("%s: Unregistered app driver %p\n", __func__, app);
-}
-EXPORT_SYMBOL(rmi_unregister_application);
-
-static int __init rmi_core_init(void)
-{
- int i;
- struct rmi_functions_data *rmi4_fn;
-
- pr_debug("%s: Register Mapped Interface Data Layer Driver\n", __func__);
-
- /* Initialize global list of RMI4 Functions that have data sources.
- We need to add all new functions to this list so that we will have
- pointers to the associated functions for init, config, report and
- detect. See rmi.h for more details. The developer will add a new
- RMI4 function number in the array in rmi.h, then add a new file to
- the build (called rmi_function_XX.c where XX is the hex number for
- the added RMI4 function). The rest should be automatic.
- */
-
- /* for each function number defined in rmi.h creat a new rmi_function
- struct and initialize the pointers to the servicing functions and then
- add it into the global list for function support.
- */
- for (i = 0; i < rmi4_num_supported_data_src_fns; i++) {
- /* Add new rmi4 function struct to list */
- struct rmi_functions *fn = kmalloc(sizeof(*fn), GFP_KERNEL);
- if (!fn) {
- printk(KERN_ERR "%s: %s: could not allocate memory "
- "for rmi_function struct for function 0x%x\n",
- __func__, drvname,
- rmi4_supported_data_src_functions[i].functionNumber);
- return -ENOMEM;
- } else {
- INC_ALLOC_STAT(fn);
-
- rmi4_fn = &rmi4_supported_data_src_functions[i];
- fn->functionNum = rmi4_fn->functionNumber;
- /* Fill in ptrs to functions. The functions are
- linked in from a file called rmi_function_xx.c
- where xx is the hex number of the RMI4 function
- from the RMI4 spec. Also, the function prototypes
- need to be added to rmi_function_xx.h - also where
- xx is the hex number of the RMI4 function. So
- that you don't get compile errors and that new
- header needs to be included in the rmi.h header file.
- */
- fn->report = rmi4_fn->reportFn;
- fn->config = rmi4_fn->configFn;
- fn->init = rmi4_fn->initFn;
- fn->detect = rmi4_fn->detectFn;
-
- /* Add the new fn to the global list */
- mutex_lock(&fns_mutex);
- list_add_tail(&fn->link, &fns_list);
- mutex_unlock(&fns_mutex);
- }
- }
-
- return 0;
-}
-
-static void __exit rmi_core_exit(void)
-{
- struct rmi_application *app, *apptmp;
-
- /* These lists should be empty, but just in case . . . */
- mutex_lock(&app_drivers_mutex);
- list_for_each_entry_safe(app, apptmp, &app_drivers, apps) {
- list_del(&app->apps);
- kfree(app);
- DEC_ALLOC_STAT(app);
- }
- mutex_unlock(&app_drivers_mutex);
-
- CHECK_ALLOC_STAT(app);
-}
-
-/* TODO: Investigate implimenting "rmi" bus and device and driver on that bus
- as per Documentation/driver-model/bus.txt */
-
-module_init(rmi_core_init);
-module_exit(rmi_core_exit);
-
-MODULE_AUTHOR("Synaptics, Inc.");
-MODULE_DESCRIPTION("RMI4 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi_core.h b/drivers/input/touchscreen/rmi_core.h
deleted file mode 100644
index fc93aed..0000000
--- a/drivers/input/touchscreen/rmi_core.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- *
- * Synaptics Register Mapped Interface (RMI4) Data Layer Core 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.
- *
- *#############################################################################
- */
-
-#ifndef _RMI_CORE_H
-#define _RMI_CORE_H
-
-struct rmi_application {
- const char *name;
- void (*attention)(struct rmi_phys_driver *pd, int instance);
- /* Probe Function
- * This function is called to give the application layer an
- * opportunity to claim an RMI device. The application layer cannot
- * read RMI registers at this point. Defer that to the config
- * function call which occurs immediately after a successful probe.
- */
- int (*probe)(struct rmi_application *app,
- const struct rmi_module_info *rmi);
- /* Config Function
- * This function is called after a successful probe. It gives the
- * application driver an opportunity to query and/or configure an RMI
- * device before data starts flowing.
- */
- void (*config)(struct rmi_application *app);
- /* Standard kernel linked list implementation.
- * Documentation on how to use it can be found at
- * http://isis.poly.edu/kulesh/stuff/src/klist/.
- */
- struct list_head apps;
- struct rmi_phys_driver *rpd;
- bool polling_required;
- struct hrtimer timer;
- struct work_struct work;
-};
-
-#endif
diff --git a/drivers/input/touchscreen/rmi_drvr.h b/drivers/input/touchscreen/rmi_drvr.h
new file mode 100755
index 0000000..0d50053
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_drvr.h
@@ -0,0 +1,203 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) RMI Driver Header File.
+ * 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.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_DRVR_H
+#define _RMI_DRVR_H
+
+/* RMI4 Protocol Support
+ */
+
+/* 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 queryBaseAddr;
+ unsigned char commandBaseAddr;
+ unsigned char controlBaseAddr;
+ unsigned char dataBaseAddr;
+ unsigned char interruptSrcCnt;
+ unsigned char functionNum;
+};
+
+/* For each function present on the RMI device, there will be a corresponding
+ * entry in the functions list of the rmi_module_info 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 {
+ struct rmi_function_device *function;
+ unsigned char functionNum;
+
+ /* This is the number of data sources associated with the function.*/
+ unsigned char numSources;
+
+ /* This is the number of data points supported - for example, for
+ * function $11 (2D sensor) the number of data points is equal to the
+ * number of fingers - for function $19 (buttons)it is the number of
+ * buttons.
+ */
+ unsigned char numDataPoints;
+
+ /* This is the number of data registers to read.*/
+ unsigned char dataRegBlockSize;
+
+ /* 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 interruptRegister;
+ unsigned char interruptMask;
+
+ /* This is the RMI function descriptor associated with this function.
+ * It contains the Base addresses for the functions query, command,
+ * control, and data registers.
+ */
+ struct rmi_function_descriptor funcDescriptor;
+
+ /* 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 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".
+ */
+struct rmi_module_info {
+ /* The Protocol Major Version number.*/
+ unsigned rmi_maj_ver;
+
+ /* The Protocol Minor Version number.*/
+ unsigned rmi_min_ver;
+
+ /* The manufacturer identification byte.*/
+ unsigned char mfgid;
+
+ /* The Product Properties information.*/
+ unsigned char properties;
+
+ /* The product info bytes.*/
+ unsigned char prod_info[2];
+
+ /* Date Code - Year, Month, Day.*/
+ unsigned char date_code[3];
+
+ /* 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[10];
+
+ /* A list of the function presence queries.
+ * 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 functions;
+};
+
+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, int instance);
+ bool polling_required;
+ int irq;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head drivers;
+ struct rmi_sensor_driver *sensor;
+ struct rmi_module_info rmi;
+ 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_sensors(struct rmi_phys_driver *physdrvr);
+int rmi_unregister_sensors(struct rmi_phys_driver *physdrvr);
+
+bool rmi_polling_required(struct rmi_sensor_driver *sensor);
+
+/* Set this to 1 to turn on code used in detecting buffer leaks. */
+#define RMI_ALLOC_STATS 1
+
+#if RMI_ALLOC_STATS
+extern int appallocsrmi;
+extern int rfiallocsrmi;
+extern int fnallocsrmi;
+
+#define INC_ALLOC_STAT(X) (X##allocsrmi++)
+#define DEC_ALLOC_STAT(X) \
+ do { \
+ if (X##allocsrmi) X##allocsrmi--; \
+ else printk(KERN_DEBUG "Too many " #X " frees\n"); \
+ } while (0)
+#define CHECK_ALLOC_STAT(X) \
+ do { \
+ if (X##allocsrmi) \
+ printk(KERN_DEBUG "Left over " #X " buffers: %d\n", \
+ X##allocsrmi); \
+ } while (0)
+#else
+#define INC_ALLOC_STAT(X) do { } while (0)
+#define DEC_ALLOC_STAT(X) do { } while (0)
+#define CHECK_ALLOC_STAT(X) do { } while (0)
+#endif
+
+#endif
diff --git a/drivers/input/touchscreen/rmi_f01.c b/drivers/input/touchscreen/rmi_f01.c
new file mode 100755
index 0000000..4a91951
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_f01.c
@@ -0,0 +1,169 @@
+/**
+ *
+ * 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 "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f01.h"
+
+
+#define RMI_REPORT_RATE_80 0
+#define RMI_REPORT_RATE_40 (1 << 6)
+
+/*.
+ * The interrupt handler for Fn $01 doesn't do anything (for now).
+ */
+void FN_01_inthandler(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+
+}
+EXPORT_SYMBOL(FN_01_inthandler);
+
+/*
+ * The work function for Fn $01 doesn't do anything (for now).
+ */
+void FN_01_workfn(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo)
+{
+
+}
+EXPORT_SYMBOL(FN_01_workfn);
+
+/*
+ * This reads in the function $01 source data.
+ *
+ */
+void FN_01_attention(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo)
+{
+ unsigned int interruptStatus;
+
+ if (rmi_read_multiple(sensor, sensor->sensorControlBaseAddr + 1,
+ (unsigned char *)&interruptStatus, sensor->interruptRegisterCount)) {
+ printk(KERN_ERR "%s : Could not read interrupt status registers 0x%x\n",
+ __func__, sensor->sensorControlBaseAddr + 1);
+ }
+
+ /* call down to the sensors irq dispatcher to dispatch IRQs */
+ sensor->dispatchIRQs(sensor, rmifninfo->interruptRegister, interruptStatus);
+
+}
+EXPORT_SYMBOL(FN_01_attention);
+
+int FN_01_config(struct rmi_sensor_driver *sensor, struct rmi_function_info *rmifninfo)
+{
+ /* print info and do any source specific configuration. */
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $01 config\n", __func__);
+
+ /* If doing interrupts then need to throttle back data rate. */
+ if (!rmi_polling_required(sensor)) {
+ /* We're interrupt driven, so set up packet rate and the worker
+ thread function. */
+ if (HZ < 500) {
+ /* The default packet rate of 80 packets per
+ * second is too fast (the Linux time slice for
+ * sub-GHz processors is only 100 times per second).
+ * So re-program it to 40 packets per second.
+ */
+ rmi_write(sensor, sensor->sensorControlBaseAddr, RMI_REPORT_RATE_40);
+ }
+ }
+
+ /* Disable Interrupts. It is up to the Application Driver to
+ * turn them on when it's ready for them. */
+ retval = rmi_write(sensor,
+ sensor->sensorControlBaseAddr + 1 +
+ rmifninfo->interruptRegister, 0);
+ if (!retval) {
+ printk(KERN_ERR "%s: Function $01 Interrupt Disable Fail: %d\n",
+ __func__, retval);
+ }
+
+ 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 input_dev *input)
+{
+ pr_debug("%s: RMI4 function $01 init\n", __func__);
+
+ return 0;
+}
+EXPORT_SYMBOL(FN_01_init);
+
+int FN_01_detect(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ int i;
+ int InterruptOffset;
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $01 detect\n", __func__);
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = (sensor->interruptRegisterCount + 7)/8;
+
+ /* loop through interrupts for each source and or in a bit
+ to the interrupt mask for each. */
+ InterruptOffset = interruptCount % 8;
+
+ for (i = InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + InterruptOffset);
+ i++) {
+ rmifninfo->interruptMask |= 1 << i;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_01_detect);
diff --git a/drivers/input/touchscreen/rmi_f01.h b/drivers/input/touchscreen/rmi_f01.h
new file mode 100755
index 0000000..bacce56
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_f01.h
@@ -0,0 +1,46 @@
+/**
+ *
+ * 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.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_01_H
+#define _RMI_FUNCTION_01_H
+
+void FN_01_inthandler(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_01_config(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+int FN_01_init(struct input_dev *input);
+int FN_01_detect(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+void FN_01_attention(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+void FN_01_workfn(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+#endif
diff --git a/drivers/input/touchscreen/rmi_f11.c b/drivers/input/touchscreen/rmi_f11.c
new file mode 100755
index 0000000..c763894
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_f11.c
@@ -0,0 +1,472 @@
+/**
+ *
+ * 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 "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f11.h"
+
+
+static int sensorMaxX;
+static int sensorMaxY;
+
+
+/*
+ * There is no attention function for Fn $11 - it is left NULL
+ * in the function table so it is not called.
+ *
+ */
+
+
+
+/*
+ * 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_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+ /* schedule work */
+
+ /* If this is an interrupt we will handle then do so otherwise leave */
+ if (assertedIRQs & rmifninfo->interruptMask) {
+ rmi_function_schedule_work(rmifninfo->function);
+ } else {
+ /* We shouldn't have gotten called without an irq status bit set so
+ print out a debug warning msg.
+ */
+ printk(KERN_DEBUG "%s: RMI4 function $11 inthandler: "
+ "Called with no irq being set.\n",
+ __func__);
+ }
+}
+EXPORT_SYMBOL(FN_11_inthandler);
+
+/*
+ * 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_workfn(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo)
+{
+ unsigned char values[2] = {0, 0};
+ unsigned char data[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ /* number of touch points - fingers down in this case */
+ int fingerDownCount;
+ int X, Y, Z, W, Wy, Wx;
+ int finger;
+ int fn11FingersSupported;
+ int fn11FingerRegisters;
+ unsigned short fn11DataBaseAddr;
+ unsigned char fn11DataRegBlockSize;
+ static bool wasdown;
+ struct rmi_function_device *function;
+
+ fingerDownCount = 0;
+ function = rmifninfo->function;
+
+ /* get 2D sensor finger data */
+
+ /* First get the finger status field - the size of the finger status field is
+ determined by the number of fingers supported - 2 bits per finger, so the number
+ of registers to read is : registerCount = ciel(numberOfFingers/4).
+ Read the required number of registers and check each 2 bit field to determine
+ if a finger is down (00 = finger not present, 01 = finger present and data accurate,
+ 10 = finger present but data may not be accurate, 11 = reserved for product use).
+ */
+ fn11FingersSupported = rmifninfo->numDataPoints;
+ fn11FingerRegisters = (fn11FingersSupported + 3)/4;
+
+ fn11DataBaseAddr = rmifninfo->funcDescriptor.dataBaseAddr;
+
+ if (rmi_read_multiple(sensor, fn11DataBaseAddr, values,
+ fn11FingerRegisters)) {
+ printk(KERN_ERR "%s: RMI4 function $11 work fn: "
+ "Could not read finger status registers 0x%x\n",
+ __func__, fn11DataBaseAddr);
+ return;
+ }
+
+ /* For each finger present, read the proper number of registers
+ to get absolute data. */
+ fn11DataRegBlockSize = rmifninfo->dataRegBlockSize;
+
+ for (finger = 0; finger < fn11FingersSupported; finger++) {
+ int reg;
+ int fingerShift;
+ int fingerStatus;
+
+ /* determine which data byte the finger status is in */
+ reg = finger/4;
+ /* bit shift to get finger's status */
+ fingerShift = (finger % 4) * 2;
+ fingerStatus = (values[reg] >> fingerShift) & 3;
+
+ /* if finger status indicates a finger is present then
+ read the finger data and report it */
+ if (fingerStatus == 1 || fingerStatus == 2) {
+ /* number of active touch points not same as
+ number of supported fingers */
+ fingerDownCount++;
+
+ /* Read the finger data */
+ if (rmi_read_multiple(sensor, fn11DataBaseAddr +
+ ((finger * fn11DataRegBlockSize) +
+ fn11FingerRegisters),
+ data, fn11DataRegBlockSize)) {
+ pr_debug("%s: RMI4 function $11 work fn: "
+ "Could not read finger data registers "
+ "0x%x\n", __func__,
+ fn11DataBaseAddr +
+ ((finger * fn11DataRegBlockSize) +
+ fn11FingerRegisters));
+ break; /* failed to read this finger - skip */
+ } else {
+
+ X = (data[0] << 4) & 0x0ff0;
+ X |= (data[2] & 0x0f);
+ Y = (data[1] << 4) & 0x0ff0;
+ Y |= ((data[2] & 0xf0) >> 4) & 0x0f;
+ W = data[3];
+
+ /* upper 4 bits of W are Wy,
+ lower 4 of W are Wx */
+ Wy = (W >> 4) & 0x0f;
+ Wx = W & 0x0f;
+
+ Z = data[4];
+
+ /* 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 (fingerDownCount == 1) {
+ input_report_abs(function->rmi_funcs.input, ABS_X, X);
+ input_report_abs(function->rmi_funcs.input, ABS_Y, Y);
+ input_report_abs(function->rmi_funcs.input, ABS_PRESSURE, Z);
+ input_report_abs(function->rmi_funcs.input, ABS_TOOL_WIDTH,
+ max(Wx, Wy));
+ input_report_key(function->rmi_funcs.input, BTN_TOUCH, 1);
+ wasdown = true;
+ }
+
+#ifdef CONFIG_SYNA_MULTI_TOUCH
+ /* Report Multi-Touch events for each finger */
+ /* major axis of touch area ellipse */
+ input_report_abs(function->rmi_funcs.input, ABS_MT_TOUCH_MAJOR,
+ max(Wx, Wy));
+ /* minor axis of touch area ellipse */
+ input_report_abs(function->rmi_funcs.input, ABS_MT_TOUCH_MINOR,
+ min(Wx, Wy));
+ /* Currently only 2 supported - 1 or 0 */
+ input_report_abs(function->rmi_funcs.input, ABS_MT_ORIENTATION,
+ (Wx > Wy ? 1 : 0));
+ input_report_abs(function->rmi_funcs.input, ABS_MT_POSITION_X, X);
+ input_report_abs(function->rmi_funcs.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 fingerStatus changes for that position.*/
+ input_report_abs(function->rmi_funcs.input, ABS_MT_TRACKING_ID,
+ finger+1);
+
+ /* MT sync between fingers */
+ input_mt_sync(function->rmi_funcs.input);
+#endif
+ }
+ }
+ }
+
+ /* if we had a finger down before and now we don't have any send a button up. */
+ if ((fingerDownCount == 0) && wasdown) {
+ wasdown = false;
+ input_report_key(function->rmi_funcs.input, BTN_TOUCH, 0);
+ }
+
+ input_sync(function->rmi_funcs.input); /* sync after groups of events */
+
+}
+EXPORT_SYMBOL(FN_11_workfn);
+
+int FN_11_config(struct rmi_sensor_driver *sensor, struct rmi_function_info *rmifninfo)
+{
+ /* For the data source - print info and do any
+ source specific configuration. */
+ unsigned char data[14];
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $11 config\n", __func__);
+
+ /* Get and print some info about the data source... */
+
+ /* To Query 2D devices we need to read from the address obtained
+ * from the function descriptor stored in the RMI function info.
+ */
+ retval = rmi_read_multiple(sensor, rmifninfo->funcDescriptor.queryBaseAddr,
+ data, 9);
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 function $11 config:"
+ "Could not read function query registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr);
+ } else {
+ pr_debug("%s: Number of Fingers: %d\n",
+ __func__, data[1] & 7);
+ pr_debug("%s: Is Configurable: %d\n",
+ __func__, data[1] & (1 << 7) ? 1 : 0);
+ pr_debug("%s: Has Gestures: %d\n",
+ __func__, data[1] & (1 << 5) ? 1 : 0);
+ pr_debug("%s: Has Absolute: %d\n",
+ __func__, data[1] & (1 << 4) ? 1 : 0);
+ pr_debug("%s: Has Relative: %d\n",
+ __func__, data[1] & (1 << 3) ? 1 : 0);
+
+ pr_debug("%s: Number X Electrodes: %d\n",
+ __func__, data[2] & 0x1f);
+ pr_debug("%s: Number Y Electrodes: %d\n",
+ __func__, data[3] & 0x1f);
+ pr_debug("%s: Maximum Electrodes: %d\n",
+ __func__, data[4] & 0x1f);
+
+ pr_debug("%s: Absolute Data Size: %d\n",
+ __func__, data[5] & 3);
+
+ pr_debug("%s: Has XY Dist: %d\n",
+ __func__, data[7] & (1 << 7) ? 1 : 0);
+ pr_debug("%s: Has Pinch: %d\n",
+ __func__, data[7] & (1 << 6) ? 1 : 0);
+ pr_debug("%s: Has Press: %d\n",
+ __func__, data[7] & (1 << 5) ? 1 : 0);
+ pr_debug("%s: Has Flick: %d\n",
+ __func__, data[7] & (1 << 4) ? 1 : 0);
+ pr_debug("%s: Has Early Tap: %d\n",
+ __func__, data[7] & (1 << 3) ? 1 : 0);
+ pr_debug("%s: Has Double Tap: %d\n",
+ __func__, data[7] & (1 << 2) ? 1 : 0);
+ pr_debug("%s: Has Tap and Hold: %d\n",
+ __func__, data[7] & (1 << 1) ? 1 : 0);
+ pr_debug("%s: Has Tap: %d\n",
+ __func__, data[7] & 1 ? 1 : 0);
+ pr_debug("%s: Has Palm Detect: %d\n",
+ __func__, data[8] & 1 ? 1 : 0);
+ pr_debug("%s: Has Rotate: %d\n",
+ __func__, data[8] & (1 << 1) ? 1 : 0);
+
+ retval = rmi_read_multiple(sensor,
+ rmifninfo->funcDescriptor.controlBaseAddr, data, 14);
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 function $11 config:"
+ "Could not read control registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.controlBaseAddr);
+ return retval;
+ }
+
+ /* Store these for use later...*/
+ sensorMaxX = ((data[6] & 0x1f) << 8) | ((data[7] & 0xff) << 0);
+ sensorMaxY = ((data[8] & 0x1f) << 8) | ((data[9] & 0xff) << 0);
+
+ pr_debug("%s: Sensor Max X: %d\n", __func__, sensorMaxX);
+ pr_debug("%s: Sensor Max Y: %d\n", __func__, sensorMaxY);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_11_config);
+
+/* Initialize any function $11 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_11_init(struct input_dev *input)
+{
+ pr_debug("%s: RMI4 function $11 init\n", __func__);
+
+ /* need to init the input abs params for the 2D */
+ set_bit(EV_ABS, input->evbit);
+ set_bit(EV_SYN, input->evbit);
+ set_bit(EV_KEY, input->evbit);
+
+ /* Use the max X and max Y read from the device...*/
+ input_set_abs_params(input, ABS_X, 0, sensorMaxX, 0, 0);
+ input_set_abs_params(input, ABS_Y, 0, sensorMaxY, 0, 0);
+ input_set_abs_params(input, ABS_PRESSURE, 0, 255, 0, 0);
+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 15, 0, 0);
+
+#ifdef CONFIG_SYNA_MULTI_TOUCH
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 15, 0, 0);
+ input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+ input_set_abs_params(input, ABS_MT_TRACKING_ID, 1, 10, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensorMaxX, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensorMaxY, 0, 0);
+#endif
+
+ return 0;
+}
+EXPORT_SYMBOL(FN_11_init);
+
+int FN_11_detect(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ char fn11Queries[9];
+ int i;
+ unsigned short fn11InterruptOffset;
+ unsigned char fn11AbsDataSize;
+ unsigned char fn11AbsDataBlockSize;
+ int fn11HasPinch, fn11HasFlick, fn11HasTap;
+ int fn11HasTapAndHold, fn11HasDoubleTap;
+ int fn11HasEarlyTap, fn11HasPress;
+ int fn11HasPalmDetect, fn11HasRotate;
+ int fn11HasRel;
+ unsigned char f11_egr_0, f11_egr_1;
+ unsigned int fn11AllDataBlockSize;
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $11 detect\n", __func__);
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* 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(sensor, fndescr->queryBaseAddr, fn11Queries,
+ sizeof(fn11Queries));
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 function $11 detect: "
+ "Could not read function query registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr);
+ return retval;
+ }
+
+ /* 2D data sources have only 3 bits for the number of fingers
+ supported - so the encoding is a bit wierd. */
+ rmifninfo->numDataPoints = 2; /* default number of fingers supported */
+ if ((fn11Queries[1] & 0x7) <= 4)
+ /* add 1 since zero based */
+ rmifninfo->numDataPoints = (fn11Queries[1] & 0x7) + 1;
+ else {
+ /* a value of 5 is up to 10 fingers - 6 and 7 are reserved
+ (shouldn't get these i int retval;n a normal 2D source). */
+ if ((fn11Queries[1] & 0x7) == 5)
+ rmifninfo->numDataPoints = 10;
+ }
+
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = (interruptCount + 7)/8;
+
+ /* loop through interrupts for each source in fn $11 and or in a bit
+ to the interrupt mask for each. */
+ fn11InterruptOffset = interruptCount % 8;
+
+ for (i = fn11InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + fn11InterruptOffset);
+ i++)
+ rmifninfo->interruptMask |= 1 << i;
+
+ /* Size of just the absolute data for one finger */
+ fn11AbsDataSize = fn11Queries[5] & 0x03;
+ /* One each for X and Y, one for LSB for X & Y, one for W, one for Z */
+ fn11AbsDataBlockSize = 3 + (2 * (fn11AbsDataSize == 0 ? 1 : 0));
+ rmifninfo->dataRegBlockSize = fn11AbsDataBlockSize;
+
+ /* need to determine the size of data to read - this depends on
+ conditions such as whether Relative data is reported and if Gesture
+ data is reported. */
+ f11_egr_0 = fn11Queries[7];
+ f11_egr_1 = fn11Queries[8];
+
+ /* Get info about what EGR data is supported, whether it has
+ Relative data supported, etc. */
+ fn11HasPinch = f11_egr_0 & 0x40;
+ fn11HasFlick = f11_egr_0 & 0x10;
+ fn11HasTap = f11_egr_0 & 0x01;
+ fn11HasTapAndHold = f11_egr_0 & 0x02;
+ fn11HasDoubleTap = f11_egr_0 & 0x04;
+ fn11HasEarlyTap = f11_egr_0 & 0x08;
+ fn11HasPress = f11_egr_0 & 0x20;
+ fn11HasPalmDetect = f11_egr_1 & 0x01;
+ fn11HasRotate = f11_egr_1 & 0x02;
+ fn11HasRel = fn11Queries[1] & 0x08;
+
+ /* Size of all data including finger status, absolute data for each
+ finger, relative data and EGR data */
+ fn11AllDataBlockSize =
+ /* finger status, four fingers per register */
+ ((rmifninfo->numDataPoints + 3) / 4) +
+ /* absolute data, per finger times number of fingers */
+ (fn11AbsDataBlockSize * rmifninfo->numDataPoints) +
+ /* two relative registers (if relative is being reported) */
+ 2 * fn11HasRel +
+ /* F11_2D_Data8 is only present if the egr_0
+ register is non-zero. */
+ !!(f11_egr_0) +
+ /* F11_2D_Data9 is only present if either egr_0 or
+ egr_1 registers are non-zero. */
+ (f11_egr_0 || f11_egr_1) +
+ /* F11_2D_Data10 is only present if EGR_PINCH or EGR_FLICK of
+ egr_0 reports as 1. */
+ !!(fn11HasPinch | fn11HasFlick) +
+ /* F11_2D_Data11 and F11_2D_Data12 are only present if
+ EGR_FLICK of egr_0 reports as 1. */
+ 2 * !!(fn11HasFlick);
+
+ /* Disable Interrupts. It is up to the Application Driver to
+ * turn them on when it's ready for them. */
+ retval = rmi_write(sensor,
+ sensor->sensorControlBaseAddr + 1 +
+ rmifninfo->interruptRegister, 0);
+ if (!retval) {
+ printk(KERN_ERR "%s: Function $11 Interrupt Disable Fail: %d\n",
+ __func__, retval);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_11_detect);
diff --git a/drivers/input/touchscreen/rmi_f11.h b/drivers/input/touchscreen/rmi_f11.h
new file mode 100755
index 0000000..44a5f0f
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_f11.h
@@ -0,0 +1,47 @@
+/**
+ *
+ * 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.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_11_H
+#define _RMI_FUNCTION_11_H
+
+
+void FN_11_inthandler(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_11_config(struct rmi_sensor_driver *sensor, struct rmi_function_info *rmifninfo);
+int FN_11_init(struct input_dev *input);
+int FN_11_detect(struct rmi_sensor_driver *sensor, struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+/* No attention function for Fn $11 */
+void FN_11_workfn(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+#endif
diff --git a/drivers/input/touchscreen/rmi_f34.c b/drivers/input/touchscreen/rmi_f34.c
new file mode 100755
index 0000000..e9a470b
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_f34.c
@@ -0,0 +1,556 @@
+/**
+ *
+ * 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;
+};
+
+
+static ssize_t rmi_fn_34_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_status_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+
+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 kobject *kobj,
+ char *buf, loff_t pos, size_t count);
+
+static ssize_t rmi_fn_34_data_write(struct kobject *kobj,
+ const 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_blocksize_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+/* define the device attributes using DEVICE_ATTR macros */
+DEVICE_ATTR(status, 0444, rmi_fn_34_status_show, rmi_fn_34_status_store); /* RO attr */
+DEVICE_ATTR(cmd, 0664, rmi_fn_34_cmd_show, rmi_fn_34_cmd_store); /* RW attr */
+DEVICE_ATTR(bootloaderid, 0644, rmi_fn_34_bootloaderid_show, rmi_fn_34_bootloaderid_store); /* RW attr */
+DEVICE_ATTR(blocksize, 0444, rmi_fn_34_blocksize_show, rmi_fn_34_blocksize_store); /* RO attr */
+
+struct bin_attribute dev_attr_data = {
+ .attr = {
+ .name = "data",
+ .owner = THIS_MODULE,
+ .mode = 0644
+ },
+ .size = 0,
+ .read = rmi_fn_34_data_read,
+ .write = rmi_fn_34_data_write,
+};
+
+/*
+ helper fn to convert from processor specific data to our firmware specific endianness.
+*/
+void copyEndianAgnostic(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_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+ unsigned int status;
+ struct rmi_function_device *fn = rmifninfo->function;
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_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(sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&status, 1)) {
+ printk(KERN_ERR "%s : Could not read status from 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ status = 0xff; /* failure */
+ }
+
+ /* set a sysfs value that the user mode can read - only upper 4 bits are the status */
+ fn34data->status = status & 0xf0; /* successful is $80, anything else is failure */
+
+}
+EXPORT_SYMBOL(FN_34_inthandler);
+
+void FN_34_workfn(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo)
+{
+
+}
+EXPORT_SYMBOL(FN_34_workfn);
+
+void FN_34_attention(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo)
+{
+
+}
+EXPORT_SYMBOL(FN_34_attention);
+
+int FN_34_config(struct rmi_sensor_driver *sensor, struct rmi_function_info *rmifninfo)
+{
+ int retval = 0;
+ unsigned char uData[2];
+ struct rmi_function_device *fn = rmifninfo->function;
+ struct rmi_fn_34_data *fn34data;
+
+ pr_debug("%s: RMI4 function $34 config\n", __func__);
+
+ /* Here we will need to set up sysfs files for Bootloader ID and Block size */
+ fn34data = (struct rmi_fn_34_data *)kzalloc(sizeof(struct rmi_fn_34_data), GFP_KERNEL);
+ if (!rmifninfo->fndata) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_fn_34_data.\n", __func__);
+ return -ENOMEM;
+ }
+ rmifninfo->fndata = (void *)fn34data;
+
+ /* set up sysfs file for Bootloader ID. */
+ if (sysfs_create_file(&fn->dev.kobj, &dev_attr_bootloaderid.attr) < 0) {
+ printk("Failed to create sysfs file for fn 34 bootloaderid.\n");
+ return -ENODEV;
+ }
+
+ /* set up sysfs file for Block Size. */
+ if (sysfs_create_file(&fn->dev.kobj, &dev_attr_blocksize.attr) < 0) {
+ printk("Failed to create sysfs file for fn 34 blocksize.\n");
+ return -ENODEV;
+ }
+
+ /* get the Bootloader ID and Block Size and store in the sysfs attributes. */
+ retval = rmi_read_multiple(sensor, fn->function->functionQueryBaseAddr,
+ uData, 2);
+ if (retval) {
+ printk(KERN_ERR "%s : Could not read bootloaderid from 0x%x\n",
+ __func__, fn->function->functionQueryBaseAddr);
+ return retval;
+ }
+ /* need to convert from our firmware storage to processore specific data */
+ fn34data->bootloaderid = (unsigned int)uData[0] + (unsigned int)uData[1]*0x100;
+
+ retval = rmi_read_multiple(sensor, fn->function->functionQueryBaseAddr+3,
+ uData, 2);
+ if (retval) {
+ printk(KERN_ERR "%s : Could not read block size from 0x%x\n",
+ __func__, fn->function->functionQueryBaseAddr+3);
+ return retval;
+ }
+ /* need to convert from our firmware storage to processor specific data */
+ fn34data->blocksize = (unsigned int)uData[0] + (unsigned int)uData[1]*0x100;
+
+ /* set up sysfs file for status. */
+ if (sysfs_create_file(&fn->dev.kobj, &dev_attr_status.attr) < 0) {
+ printk("Failed to create sysfs file for fn 34 status.\n");
+ return -ENODEV;
+ }
+
+ /* Also, sysfs will need to have a file set up to distinguish between commands - like
+ Config write/read, Image write/verify.*/
+ /* set up sysfs file for command code. */
+ if (sysfs_create_file(&fn->dev.kobj, &dev_attr_cmd.attr) < 0) {
+ printk("Failed to create sysfs file for fn 34 cmd.\n");
+ return -ENODEV;
+ }
+
+ /* We will also 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. */
+ if (sysfs_create_bin_file(&fn->dev.kobj, &dev_attr_data) < 0) {
+ printk("Failed to create sysfs file for fn 34 data.\n");
+ return -ENODEV;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_34_config);
+
+
+int FN_34_init(struct input_dev *input)
+{
+ pr_debug("%s: RMI4 function $34 init\n", __func__);
+ return 0;
+}
+EXPORT_SYMBOL(FN_34_init);
+
+int FN_34_detect(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ int i;
+ int InterruptOffset;
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $34 detect\n", __func__);
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = (sensor->interruptRegisterCount + 7)/8;
+
+ /* loop through interrupts for each source and or in a bit
+ to the interrupt mask for each. */
+ InterruptOffset = interruptCount % 8;
+
+ for (i = InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + InterruptOffset);
+ i++) {
+ rmifninfo->interruptMask |= 1 << i;
+ }
+
+ 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 *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->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 uData[2];
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ /* need to convert the string data to an actual value */
+ error = strict_strtoul(buf, 10, &val);
+
+ if (error)
+ return error;
+
+ fn34data->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).*/
+ copyEndianAgnostic(uData, (unsigned short)val);
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr,
+ uData, 2);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write bootloader id to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr);
+ 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 *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->blocksize);
+}
+
+static ssize_t rmi_fn_34_blocksize_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /* Block Size is RO so we shouldn't do anything if the
+ user space writes to the sysfs file. */
+
+ return -EPERM;
+}
+
+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 *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->status);
+}
+
+static ssize_t rmi_fn_34_status_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /* Status is RO so we shouldn't do anything if the user
+ app writes to the sysfs file. */
+ return -EPERM;
+}
+
+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 *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->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 *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+ unsigned long val;
+ unsigned char cmd;
+ int error;
+
+ /* need to convert the string data to an actual value */
+ error = strict_strtoul(buf, 10, &val);
+
+ if (error)
+ return error;
+
+ fn34data->cmd = val;
+
+ /* determine the proper command to issue.
+ */
+ switch (val) {
+ case ENABLE_FLASH_PROG:
+ /* Issue a Flash Program Enable ($0F) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x0F;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Flash Program Enable cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case ERASE_ALL:
+ /* Issue a Erase All ($03) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x03;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Erase All cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case ERASE_CONFIG:
+ /* Issue a Erase Configuration ($07) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x07;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Erase Configuration cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case WRITE_FW_BLOCK:
+ /* Issue a Write Firmware Block ($02) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x02;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Write Firmware Block cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case WRITE_CONFIG_BLOCK:
+ /* Issue a Write Config Block ($06) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x06;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Write Config Block cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case READ_CONFIG_BLOCK:
+ /* Issue a Read Config Block ($05) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x05;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Read Config Block cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case DISABLE_FLASH_PROG:
+ /* Issue a reset command ($01) - this will reboot the sensor and ATTN will now go to
+ the Fn $01 instead of the Fn $34 since the sensor will no longer be in Flash mode. */
+ cmd = 0x01;
+ /*if ((error = rmi_write_multiple(fn->sensor, fn->sensor->sensorCommandBaseAddr,
+ (unsigned char *)&cmd, 1))) {
+ printk(KERN_ERR "%s : Could not write Reset cmd to 0x%x\n",
+ __func__, fn->sensor->sensorCommandBaseAddr);
+ return error;
+ }*/
+ break;
+
+ default:
+ pr_debug("%s: RMI4 function $34 - unknown command.\n", __func__);
+ break;
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_34_data_read(struct kobject *kobj,
+ 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);
+ int error;
+
+ /* TODO: add check for count to verify it's the correct blocksize */
+
+ /* 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->function->functionDataBaseAddr+pos,
+ (unsigned char *)buf, count);
+ if (error) {
+ printk(KERN_ERR "%s : Could not read data from 0x%llx\n",
+ __func__, fn->function->functionDataBaseAddr+pos);
+ return error;
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_34_data_write(struct kobject *kobj,
+ const 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 *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+ unsigned int blocknum;
+ int error;
+
+ /* 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. */
+
+ /* TODO: Add check on count - if non-zero veriy it's the correct blocksize */
+
+ /* 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 % fn34data->blocksize) because of a gcc
+ bug that results in undefined symbols. So we have to compute it the hard
+ way. Grumble. */
+ unsigned int remainder;
+ div_u64_rem(pos, fn34data->blocksize, &remainder);
+ if (remainder) {
+ printk(KERN_ERR "%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, fn34data->blocksize);
+
+ /* Write the block number first */
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr,
+ (unsigned char *)&blocknum, 2);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write block number to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr);
+ return error;
+ }
+
+ /* Write the data block - only if the count is non-zero */
+ if (count) {
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+2,
+ (unsigned char *)buf, count);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write block data to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+2);
+ return error;
+ }
+ }
+
+ return count;
+}
diff --git a/drivers/input/touchscreen/rmi_f34.h b/drivers/input/touchscreen/rmi_f34.h
new file mode 100755
index 0000000..b6500b8
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_f34.h
@@ -0,0 +1,56 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $34 header.
+ * Copyright (c) 2007 - 2010, 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.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_34_H
+#define _RMI_FUNCTION_34_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
+#define DISABLE_FLASH_PROG 16
+
+void FN_34_inthandler(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_34_config(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+int FN_34_init(struct input_dev *input);
+int FN_34_detect(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+void FN_34_attention(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+void FN_34_workfn(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+
+#endif
diff --git a/drivers/input/touchscreen/rmi_function.c b/drivers/input/touchscreen/rmi_function.c
new file mode 100755
index 0000000..cddf601
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_function.c
@@ -0,0 +1,352 @@
+/**
+ * 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.
+ *
+ *#############################################################################
+ */
+
+
+static const char functionname[10] = "fn";
+
+#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"
+
+extern long polltime;
+
+/* supported RMI4 functions list - controls what we
+will provide support for - if it's not in the list then
+the developer needs to add support functions for it.*/
+static LIST_HEAD(fns_list);
+static DEFINE_MUTEX(fns_mutex);
+
+/* 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.
+*/
+
+static struct rmi_functions_data
+ rmi4_supported_data_src_functions[rmi4_num_supported_data_src_fns] = {
+ /* Fn $11 */
+ {0x11, FN_11_inthandler, FN_11_config, FN_11_init, FN_11_detect, FN_11_workfn, NULL},
+ /* Fn $01 */
+ {0x01, FN_01_inthandler, FN_01_config, FN_01_init, FN_01_detect, FN_01_workfn, FN_01_attention},
+ /* Fn $34 */
+ {0x34, FN_34_inthandler, FN_34_config, FN_34_init, FN_34_detect, FN_34_workfn, FN_34_attention},
+};
+
+
+/* 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_functions *rmi_find_function(int functionNum)
+{
+ struct rmi_functions *fn;
+ bool found = false;
+
+ list_for_each_entry(fn, &fns_list, link) {
+ if (functionNum == fn->functionNum) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return NULL;
+ else
+ return fn;
+}
+EXPORT_SYMBOL(rmi_find_function);
+
+void rmi_function_schedule_work(struct rmi_function_device *function)
+{
+ /* All we have to do is schedule work. */
+ schedule_work(&(function->work));
+}
+EXPORT_SYMBOL(rmi_function_schedule_work);
+
+
+/* This is the worker function - it simply has to call this functions report. */
+static void fn_work_func(struct work_struct *work)
+{
+ struct rmi_function_device *function = container_of(work,
+ struct rmi_function_device, work);
+
+ function->rmi_funcs.workfn(function->sensor,
+ function->rfi);
+}
+
+/* This is the timer function for polling - it simply has to schedule work
+ * and restart the timer. */
+static enum hrtimer_restart fn_poll_timer_func(struct hrtimer *timer)
+{
+ struct rmi_function_device *function = container_of(timer,
+ struct rmi_function_device, timer);
+
+ schedule_work(&function->work);
+ hrtimer_start(&function->timer, ktime_set(0, polltime), HRTIMER_MODE_REL);
+ return HRTIMER_NORESTART;
+}
+
+static void rmi_function_config(struct rmi_function_device *function)
+{
+ printk(KERN_DEBUG "%s: rmi_function_config \n", __func__);
+
+ /* if we are not polling we need to set up the interrupt worker
+ thread - otherwise we need to set up the polling callback and
+ worker thread. */
+ if (!rmi_polling_required(function->sensor)) {
+ INIT_WORK(&function->work, fn_work_func);
+ } else {
+ /* We're polling driven, so set up the polling timer
+ and timer function. */
+ INIT_WORK(&function->work, fn_work_func);
+ hrtimer_init(&function->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ function->timer.function = fn_poll_timer_func;
+ hrtimer_start(&function->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+}
+
+/**
+ * This is the probe function passed to the RMI4 subsystem that gives us a
+ * chance to recognize an RMI4 function.
+ */
+static int rmi_function_probe(struct rmi_function_driver *function)
+{
+ struct rmi_phys_driver *rpd;
+ struct rmi_function_info *rfi;
+ struct rmi_module_info *rmi;
+ int data_sources;
+
+
+ rpd = function->rpd;
+ rmi = &(rpd->rmi);
+
+ if (!rpd) {
+ printk(KERN_ERR "%s: Invalid rmi physical driver - null ptr: %p\n", __func__, rpd);
+ return 0;
+ }
+
+ return 1;
+}
+
+int rmi_function_register_driver(struct rmi_function_driver *drv, int fnNumber)
+{
+ int retval;
+ char *drvrname;
+
+ printk(KERN_INFO "%s: Registering function device.\n", __func__);
+
+ retval = 0;
+
+ /* assign the bus type for this driver to be rmi bus */
+ drv->drv.bus = &rmi_bus_type;
+ /* Create a function device and function driver for this Fn */
+ drvrname = kzalloc(sizeof(functionname) + 4, GFP_KERNEL);
+ if (!drvrname) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_function_driver name.\n", __func__);
+ return -ENOMEM;
+ }
+ sprintf(drvrname, "fn%02x", fnNumber);
+
+ drv->drv.name = drvrname;
+ drv->module = drv->drv.owner;
+
+ /* register the sensor driver */
+ retval = driver_register(&drv->drv);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed driver_register %d\n",
+ __func__, retval);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(rmi_function_register_driver);
+
+void rmi_function_unregister_driver(struct rmi_function_driver *drv)
+{
+ printk(KERN_INFO "%s: Unregistering function driver.\n", __func__);
+
+ driver_unregister(&drv->drv);
+}
+EXPORT_SYMBOL(rmi_function_unregister_driver);
+
+int rmi_function_register_device(struct rmi_function_device *dev, int fnNumber)
+{
+ struct input_dev *input;
+ struct rmi_functions *fn;
+ int retval;
+
+ printk(KERN_INFO "%s: Registering function device.\n", __func__);
+
+ retval = 0;
+
+ /* make name - fn11, fn19, etc. */
+ dev_set_name(&dev->dev, "fn%02x", fnNumber);
+ retval = device_register(&dev->dev);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed device_register for function device.\n",
+ __func__);
+ return retval;
+ }
+
+ input = input_allocate_device();
+ if (input == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate memory for a "
+ "new input device.\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ input->name = dev_name(&dev->dev);
+ input->phys = "rmi_function";
+
+ /* Set input device specific params for each data source...*/
+ fn = rmi_find_function(fnNumber);
+
+ if (!fn) {
+ printk(KERN_ERR "%s: Failed rmi_find_function - function not supported.\n", __func__);
+ return -ENODEV;
+ }
+
+ /* init any input specific params for this function */
+ fn->init(input);
+
+ retval = input_register_device(input);
+
+ if (retval) {
+ printk(KERN_ERR "%s: Failed input_register_device.\n",
+ __func__);
+ return retval;
+ }
+
+ dev->rmi_funcs.input = input;
+ dev->rmi_funcs.functionNum = fnNumber;
+
+ rmi_function_config(dev);
+
+ return retval;
+}
+EXPORT_SYMBOL(rmi_function_register_device);
+
+void rmi_function_unregister_device(struct rmi_function_device *dev)
+{
+ printk(KERN_INFO "%s: Unregistering function device.n", __func__);
+
+ /* Stop the polling timer if doing polling */
+ if (rmi_polling_required(dev->sensor))
+ hrtimer_cancel(&dev->timer);
+
+ flush_scheduled_work(); /* Make sure all scheduled work is stopped */
+
+ input_unregister_device(dev->rmi_funcs.input);
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(rmi_function_unregister_device);
+
+static int __init rmi_function_init(void)
+{
+ struct rmi_functions_data *rmi4_fn;
+ int i;
+
+ printk(KERN_DEBUG "%s: RMI Function Init\n", __func__);
+
+ /* Initialize global list of RMI4 Functions.
+ We need to add the supported RMI4 funcions so that we will have
+ pointers to the associated functions for init, config, report and
+ detect. See rmi.h for more details. The developer will add a new
+ RMI4 function number in the array in rmi_drvr.h, then add a new file to
+ the build (called rmi_fXX.c where XX is the hex number for
+ the added RMI4 function). The rest should be automatic.
+ */
+
+ /* for each function number defined in rmi.h creat a new rmi_function
+ struct and initialize the pointers to the servicing functions and then
+ add it into the global list for function support.
+ */
+ for (i = 0; i < rmi4_num_supported_data_src_fns; i++) {
+ /* Add new rmi4 function struct to list */
+ struct rmi_functions *fn = kmalloc(sizeof(*fn), GFP_KERNEL);
+ if (!fn) {
+ printk(KERN_ERR "%s: could not allocate memory "
+ "for rmi_function struct for function 0x%x\n",
+ __func__,
+ rmi4_supported_data_src_functions[i].functionNumber);
+ return -ENOMEM;
+ } else {
+
+ rmi4_fn = &rmi4_supported_data_src_functions[i];
+ fn->functionNum = rmi4_fn->functionNumber;
+ /* Fill in ptrs to functions. The functions are
+ linked in from a file called rmi_fxx.c
+ where xx is the hex number of the RMI4 function
+ from the RMI4 spec. Also, the function prototypes
+ need to be added to rmi_fxx.h - also where
+ xx is the hex number of the RMI4 function. So
+ that you don't get compile errors and that new
+ header needs to be included in the rmi_function.h
+ */
+ fn->inthandler = rmi4_fn->inthandlerFn;
+ fn->config = rmi4_fn->configFn;
+ fn->init = rmi4_fn->initFn;
+ fn->detect = rmi4_fn->detectFn;
+ fn->attention = rmi4_fn->attnFn;
+ fn->workfn = rmi4_fn->workFn;
+
+ /* Add the new fn to the global list */
+ mutex_lock(&fns_mutex);
+ list_add_tail(&fn->link, &fns_list);
+ mutex_unlock(&fns_mutex);
+ }
+ }
+
+ return 0;
+}
+
+static void __exit rmi_function_exit(void)
+{
+ printk(KERN_DEBUG "%s: RMI Function Exit\n", __func__);
+ flush_scheduled_work(); /* Make sure all scheduled work is stopped */
+}
+
+
+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_function.h b/drivers/input/touchscreen/rmi_function.h
new file mode 100755
index 0000000..819ee20
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_function.h
@@ -0,0 +1,199 @@
+/**
+ *
+ * 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.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_FUNCTION_H
+#define _RMI_FUNCTION_H
+
+/* 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_functions {
+ unsigned char functionNum;
+
+ struct input_dev *input;
+
+ /* 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_sensor_driver *sensor,
+ struct rmi_function_info *rfi, unsigned int assertedIRQs);
+
+ int (*config)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+ int (*init)(struct input_dev *input);
+ int (*detect)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+ /** If this is non-null, the sensor implemenation will call this
+ * whenever the ATTN line is asserted.
+ */
+ void (*attention)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+ void (*workfn)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rfi);
+
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head link;
+};
+
+
+/* Each time a new RMI4 function support is added the developer needs to
+ bump the number of supported functions and add the info for
+ that RMI4 function to the array along with pointers to the report,
+ config, init and detect functions that they coded in rmi_fxx.c
+ and rmi_fxx.h - where xx is the RMI4 function number in hex for the new
+ RMI4 data source function. The information for the RMI4 functions is
+ obtained from the RMI4 specification document.
+*/
+#define rmi4_num_supported_data_src_fns 3
+
+/* add hdr files for all prototypes for RMI4 data source
+ functions being supported. */
+#include "rmi_f01.h"
+#include "rmi_f11.h"
+#include "rmi_f34.h"
+
+typedef void(*inthandlerFuncPtr)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rfi, unsigned int assertedIRQs);
+typedef int(*configFuncPtr)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+typedef int(*initFuncPtr)(struct input_dev *input);
+typedef int(*detectFuncPtr)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo, struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+typedef void (*attnFuncPtr)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rmifninfo);
+typedef void(*workFuncPtr)(struct rmi_sensor_driver *sensor,
+ struct rmi_function_info *rfi);
+
+struct rmi_functions_data {
+ int functionNumber;
+ inthandlerFuncPtr inthandlerFn;
+ configFuncPtr configFn;
+ initFuncPtr initFn;
+ detectFuncPtr detectFn;
+ attnFuncPtr attnFn;
+ workFuncPtr workFn;
+};
+
+
+struct rmi_functions *rmi_find_function(int functionNum);
+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 functionQueryBaseAddr; /* RMI4 function control */
+ unsigned short functionControlBaseAddr;
+ unsigned short functionCommandBaseAddr;
+ unsigned short functionDataBaseAddr;
+ unsigned int interruptRegisterOffset; /* offset from start of interrupt registers */
+ unsigned int interruptMask;
+
+ /* 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 hrtimer timer;
+ struct work_struct work;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head function_drivers; /* link function drivers into list */
+};
+
+struct rmi_function_device {
+ struct rmi_function_driver *function;
+ struct device dev;
+ struct rmi_sensor_driver *sensor; /* need this to be bound to phys driver layer */
+
+ /* the function ptrs to the config, init, detect and
+ report fns for this rmi function device. */
+ struct rmi_functions rmi_funcs;
+ struct rmi_function_info *rfi;
+
+ struct hrtimer timer;
+ struct work_struct work;
+
+ /** An RMI sensor might actually have several IRQ registers -
+ * this tells us which IRQ register this function is interested in.
+ */
+ unsigned int irqRegisterSet;
+
+ /** This is a mask of the IRQs the function is interested in.
+ */
+ unsigned int irqMask;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head functions; /* link functions into list */
+};
+
+void rmi_function_attn(struct rmi_function_device *function);
+int rmi_function_register_device(struct rmi_function_device *dev, int fnNumber);
+void rmi_function_schedule_work(struct rmi_function_device *function);
+
+#endif
diff --git a/drivers/input/touchscreen/rmi_function_11.c b/drivers/input/touchscreen/rmi_function_11.c
deleted file mode 100644
index ab63f4c..0000000
--- a/drivers/input/touchscreen/rmi_function_11.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/**
- *
- * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
- * 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.
- *
- *#############################################################################
- */
-
-#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 "rmi.h"
-#include "rmi_core.h"
-#include "rmi_functions.h"
-
-extern unsigned short fn01ControlBaseAddr; /* RMI4 device control == function 0x01 */
-
-static int sensorMaxX;
-static int sensorMaxY;
-
-/*
- * 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!
- */
-int FN_11_report(struct rmi_application *app,
- struct rmi_function_info *rfi, struct input_dev *input)
-{
- unsigned char values[2] = {0, 0};
- unsigned char data[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- /* number of touch points - fingers down in this case */
- int fingerDownCount;
- int X, Y, Z, W, Wy, Wx;
- int finger;
- int ret;
- int fn11FingersSupported;
- int fn11FingerRegisters;
- unsigned short fn11DataBaseAddr;
- unsigned char fn11DataRegBlockSize;
- static bool wasdown = false;
-
- ret = 0;
- fingerDownCount = 0;
-
- /* get 2D sensor finger data */
-
- /* First get the finger status field - the size of the finger status field is
- determined by the number of fingers supported - 2 bits per finger, so the number
- of registers to read is : registerCount = ciel(numberOfFingers/4).
- Read the required number of registers and check each 2 bit field to determine
- if a finger is down (00 = finger not present, 01 = finger present and data accurate,
- 10 = finger present but data may not be accurate, 11 = reserved for product use).
- */
- fn11FingersSupported = rfi->numDataPoints;
- fn11FingerRegisters = (fn11FingersSupported + 3)/4;
-
- fn11DataBaseAddr = rfi->funcDescriptor.dataBaseAddr;
-
- if (rmi_read_multiple(app, fn11DataBaseAddr, values,
- fn11FingerRegisters)) {
- printk(KERN_ERR "%s: RMI4 function $11 report: "
- "Could not read finger status registers 0x%x\n",
- __func__, fn11DataBaseAddr);
- ret = -ENODEV;
- goto err_ret;
- }
-
- /* For each finger present, read the proper number of registers
- to get absolute data. */
- fn11DataRegBlockSize = rfi->dataRegBlockSize;
-
- for (finger = 0; finger < fn11FingersSupported; finger++) {
- int reg;
- int fingerShift;
- int fingerStatus;
-
- /* determine which data byte the finger status is in */
- reg = finger/4;
- /* bit shift to get finger's status */
- fingerShift = (finger % 4) * 2;
- fingerStatus = (values[reg] >> fingerShift) & 3;
-
- /* if finger status indicates a finger is present then
- read the finger data and report it */
- if (fingerStatus == 1 || fingerStatus == 2) {
- /* number of active touch points not same as
- number of supported fingers */
- fingerDownCount++;
-
- /* Read the finger data */
- if (rmi_read_multiple(app, fn11DataBaseAddr +
- ((finger * fn11DataRegBlockSize) +
- fn11FingerRegisters),
- data, fn11DataRegBlockSize)) {
- pr_debug("%s: RMI4 function $11 report: "
- "Could not read finger data registers "
- "0x%x\n", __func__,
- fn11DataBaseAddr +
- ((finger * fn11DataRegBlockSize) +
- fn11FingerRegisters));
- break; /* failed to read this finger - skip */
- } else {
- X = (data[0] & 0x1f) << 4;
- X |= data[2] & 0xf;
- Y = (data[1] & 0x1f) << 4;
- Y |= (data[2] >> 4) & 0xf;
- W = data[3];
-
- /* upper 4 bits of W are Wy,
- lower 4 of W are Wx */
- Wy = (W >> 4) & 0x0f;
- Wx = W & 0x0f;
-
- Z = data[4];
-
- /* 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 (fingerDownCount == 1) {
- input_report_abs(input, ABS_X, X);
- input_report_abs(input, ABS_Y, Y);
- input_report_abs(input, ABS_PRESSURE, Z);
- input_report_abs(input, ABS_TOOL_WIDTH,
- max(Wx, Wy));
- input_report_key(input, BTN_TOUCH, 1);
- wasdown = true;
- }
-
-#ifdef CONFIG_SYNA_MULTI_TOUCH
- /* Report Multi-Touch events for each finger */
- /* major axis of touch area ellipse */
- input_report_abs(input, ABS_MT_TOUCH_MAJOR,
- max(Wx, Wy));
- /* minor axis of touch area ellipse */
- input_report_abs(input, ABS_MT_TOUCH_MINOR,
- min(Wx, Wy));
- /* Currently only 2 supported - 1 or 0 */
- input_report_abs(input, ABS_MT_ORIENTATION,
- (Wx > Wy ? 1 : 0));
- input_report_abs(input, ABS_MT_POSITION_X, X);
- input_report_abs(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 fingerStatus changes for that position.*/
- input_report_abs(input, ABS_MT_TRACKING_ID,
- finger+1);
-
- /* MT sync between fingers */
- input_mt_sync(input);
-#endif
- }
- }
- }
-
- /* if we had a finger down before and now we don't have any send a button up. */
- if ((fingerDownCount == 0) && wasdown) {
- wasdown = false;
- input_report_key(input, BTN_TOUCH, 0);
- }
-
- input_sync(input); /* sync after groups of events */
-
-err_ret:
-
- return ret;
-}
-
-int FN_11_config(struct rmi_application *app, struct rmi_function_info *rfi)
-{
- /* For the data source - print info and do any
- source specific configuration. */
- unsigned char data[14];
- int retval = 0;
-
- pr_debug("%s: RMI4 function $11 config\n", __func__);
-
- /* Get and print some info about the data source... */
-
- /* To Query 2D devices we need to read from the address obtained
- * from the function descriptor stored in the RMI function info.
- */
- retval = rmi_read_multiple(app, rfi->funcDescriptor.queryBaseAddr,
- data, 9);
- if (retval) {
- printk(KERN_ERR "%s: RMI4 function $11 config:"
- "Could not read function query registers 0x%x\n",
- __func__, rfi->funcDescriptor.queryBaseAddr);
- } else {
- pr_debug("%s: Number of Fingers: %d\n",
- __func__, data[1] & 7);
- pr_debug("%s: Is Configurable: %d\n",
- __func__, data[1] & (1 << 7) ? 1 : 0);
- pr_debug("%s: Has Gestures: %d\n",
- __func__, data[1] & (1 << 5) ? 1 : 0);
- pr_debug("%s: Has Absolute: %d\n",
- __func__, data[1] & (1 << 4) ? 1 : 0);
- pr_debug("%s: Has Relative: %d\n",
- __func__, data[1] & (1 << 3) ? 1 : 0);
-
- pr_debug("%s: Number X Electrodes: %d\n",
- __func__, data[2] & 0x1f);
- pr_debug("%s: Number Y Electrodes: %d\n",
- __func__, data[3] & 0x1f);
- pr_debug("%s: Maximum Electrodes: %d\n",
- __func__, data[4] & 0x1f);
-
- pr_debug("%s: Absolute Data Size: %d\n",
- __func__, data[5] & 3);
-
- pr_debug("%s: Has XY Dist: %d\n",
- __func__, data[7] & (1 << 7) ? 1 : 0);
- pr_debug("%s: Has Pinch: %d\n",
- __func__, data[7] & (1 << 6) ? 1 : 0);
- pr_debug("%s: Has Press: %d\n",
- __func__, data[7] & (1 << 5) ? 1 : 0);
- pr_debug("%s: Has Flick: %d\n",
- __func__, data[7] & (1 << 4) ? 1 : 0);
- pr_debug("%s: Has Early Tap: %d\n",
- __func__, data[7] & (1 << 3) ? 1 : 0);
- pr_debug("%s: Has Double Tap: %d\n",
- __func__, data[7] & (1 << 2) ? 1 : 0);
- pr_debug("%s: Has Tap and Hold: %d\n",
- __func__, data[7] & (1 << 1) ? 1 : 0);
- pr_debug("%s: Has Tap: %d\n",
- __func__, data[7] & 1 ? 1 : 0);
- pr_debug("%s: Has Palm Detect: %d\n",
- __func__, data[8] & 1 ? 1 : 0);
- pr_debug("%s: Has Rotate: %d\n",
- __func__, data[8] & (1 << 1) ? 1 : 0);
-
- retval = rmi_read_multiple(app,
- rfi->funcDescriptor.controlBaseAddr, data, 14);
- if (retval) {
- printk(KERN_ERR "%s: RMI4 function $11 config:"
- "Could not read control registers 0x%x\n",
- __func__, rfi->funcDescriptor.controlBaseAddr);
- return retval;
- }
-
- /* Store these for use later...*/
- sensorMaxX = ((data[6] & 0x1f) << 8) | ((data[7] & 0xff) << 0);
- sensorMaxY = ((data[8] & 0x1f) << 8) | ((data[9] & 0xff) << 0);
-
- pr_debug("%s: Sensor Max X: %d\n", __func__, sensorMaxX);
- pr_debug("%s: Sensor Max Y: %d\n", __func__, sensorMaxY);
- }
-
- return retval;
-}
-
-/* Initialize any function $11 specific params and settings - input
- * settings, device settings, etc.
- */
-int FN_11_init(struct input_dev *input)
-{
- pr_debug("%s: RMI4 function $11 init\n", __func__);
-
- /* need to init the input abs params for the 2D */
- input->evbit[0] = BIT(EV_ABS);
-
- /* Use the max X and max Y read from the device...*/
- input_set_abs_params(input, ABS_X, 0, sensorMaxX, 0, 0);
- input_set_abs_params(input, ABS_Y, 0, sensorMaxY, 0, 0);
- input_set_abs_params(input, ABS_PRESSURE, 0, 255, 0, 0);
- input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 15, 0, 0);
-
-#ifdef CONFIG_SYNA_MULTI_TOUCH
- input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);
- input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 15, 0, 0);
- input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
- input_set_abs_params(input, ABS_MT_TRACKING_ID, 1, 10, 0, 0);
- input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensorMaxX, 0, 0);
- input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensorMaxY, 0, 0);
-#endif
-
- return 0;
-}
-
-int FN_11_detect(struct rmi_application *app, struct rmi_function_info *rfi,
- struct rmi_function_descriptor *fd, unsigned int interruptCount)
-{
- char fn11Queries[9];
- int i;
- unsigned short fn11InterruptOffset;
- unsigned char fn11AbsDataSize;
- unsigned char fn11AbsDataBlockSize;
- int fn11HasPinch, fn11HasFlick, fn11HasTap;
- int fn11HasTapAndHold, fn11HasDoubleTap;
- int fn11HasEarlyTap, fn11HasPress;
- int fn11HasPalmDetect, fn11HasRotate;
- int fn11HasRel;
- unsigned char f11_egr_0, f11_egr_1;
- unsigned int fn11AllDataBlockSize;
- int retval = 0;
-
- pr_debug("%s: RMI4 function $11 detect\n", __func__);
-
- /* Store addresses - used elsewhere to read data,
- * control, query, etc. */
- rfi->funcDescriptor.queryBaseAddr = fd->queryBaseAddr;
- rfi->funcDescriptor.commandBaseAddr = fd->commandBaseAddr;
- rfi->funcDescriptor.controlBaseAddr = fd->controlBaseAddr;
- rfi->funcDescriptor.dataBaseAddr = fd->dataBaseAddr;
- rfi->funcDescriptor.interruptSrcCnt = fd->interruptSrcCnt;
- rfi->funcDescriptor.functionNum = fd->functionNum;
-
- rfi->numSources = fd->interruptSrcCnt;
-
- /* 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(app, fd->queryBaseAddr, fn11Queries,
- sizeof(fn11Queries));
- if (retval) {
- printk(KERN_ERR "%s: RMI4 function $11 detect: "
- "Could not read function query registers 0x%x\n",
- __func__, rfi->funcDescriptor.queryBaseAddr);
- return retval;
- }
-
- /* 2D data sources have only 3 bits for the number of fingers
- supported - so the encoding is a bit wierd. */
- rfi->numDataPoints = 2; /* default number of fingers supported */
- if ((fn11Queries[1] & 0x7) <= 4)
- /* add 1 since zero based */
- rfi->numDataPoints = (fn11Queries[1] & 0x7) + 1;
- else {
- /* a value of 5 is up to 10 fingers - 6 and 7 are reserved
- (shouldn't get these i int retval;n a normal 2D source). */
- if ((fn11Queries[1] & 0x7) == 5)
- rfi->numDataPoints = 10;
- }
-
- /* Need to get interrupt info to be used later when handling
- interrupts. */
- rfi->interruptRegister = (interruptCount + 7)/8;
-
- /* loop through interrupts for each source in fn $11 and or in a bit
- to the interrupt mask for each. */
- fn11InterruptOffset = interruptCount % 8;
-
- for (i = fn11InterruptOffset;
- i < ((fd->interruptSrcCnt & 0x7) + fn11InterruptOffset);
- i++)
- rfi->interruptMask |= 1 << i;
-
- /* Size of just the absolute data for one finger */
- fn11AbsDataSize = fn11Queries[5] & 0x03;
- /* One each for X and Y, one for LSB for X & Y, one for W, one for Z */
- fn11AbsDataBlockSize = 3 + (2 * (fn11AbsDataSize == 0 ? 1 : 0));
- rfi->dataRegBlockSize = fn11AbsDataBlockSize;
-
- /* need to determine the size of data to read - this depends on
- conditions such as whether Relative data is reported and if Gesture
- data is reported. */
- f11_egr_0 = fn11Queries[7];
- f11_egr_1 = fn11Queries[8];
-
- /* Get info about what EGR data is supported, whether it has
- Relative data supported, etc. */
- fn11HasPinch = f11_egr_0 & 0x40;
- fn11HasFlick = f11_egr_0 & 0x10;
- fn11HasTap = f11_egr_0 & 0x01;
- fn11HasTapAndHold = f11_egr_0 & 0x02;
- fn11HasDoubleTap = f11_egr_0 & 0x04;
- fn11HasEarlyTap = f11_egr_0 & 0x08;
- fn11HasPress = f11_egr_0 & 0x20;
- fn11HasPalmDetect = f11_egr_1 & 0x01;
- fn11HasRotate = f11_egr_1 & 0x02;
- fn11HasRel = fn11Queries[1] & 0x08;
-
- /* Size of all data including finger status, absolute data for each
- finger, relative data and EGR data */
- fn11AllDataBlockSize =
- /* finger status, four fingers per register */
- ((rfi->numDataPoints + 3) / 4) +
- /* absolute data, per finger times number of fingers */
- (fn11AbsDataBlockSize * rfi->numDataPoints) +
- /* two relative registers (if relative is being reported) */
- 2 * fn11HasRel +
- /* F11_2D_Data8 is only present if the egr_0
- register is non-zero. */
- !!(f11_egr_0) +
- /* F11_2D_Data9 is only present if either egr_0 or
- egr_1 registers are non-zero. */
- (f11_egr_0 || f11_egr_1) +
- /* F11_2D_Data10 is only present if EGR_PINCH or EGR_FLICK of
- egr_0 reports as 1. */
- !!(fn11HasPinch | fn11HasFlick) +
- /* F11_2D_Data11 and F11_2D_Data12 are only present if
- EGR_FLICK of egr_0 reports as 1. */
- 2 * !!(fn11HasFlick);
-
- /* Disable Interrupts. It is up to the Application Driver to
- * turn them on when it's ready for them. */
- retval = rmi_write(app,
- fn01ControlBaseAddr + 1 + rfi->interruptRegister, 0);
- if (!retval) {
- printk(KERN_ERR "%s: Function $11 Interrupt Disable Fail: %d\n",
- __func__, retval);
- }
-
- return retval;
-}
diff --git a/drivers/input/touchscreen/rmi_function_11.h b/drivers/input/touchscreen/rmi_function_11.h
deleted file mode 100644
index e90d889..0000000
--- a/drivers/input/touchscreen/rmi_function_11.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- *
- * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
- * 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.
- *
- *#############################################################################
- */
-#ifndef _RMI_FUNCTION_11_H
-#define _RMI_FUNCTION_11_H
-
-int FN_11_report(struct rmi_application *app, struct rmi_function_info *rfi,
- struct input_dev *input);
-int FN_11_config(struct rmi_application *app, struct rmi_function_info *rfi);
-int FN_11_init(struct input_dev *input);
-int FN_11_detect(struct rmi_application *app, struct rmi_function_info *rfi,
- struct rmi_function_descriptor *fd,
- unsigned int interruptCount);
-
-#endif
diff --git a/drivers/input/touchscreen/rmi_functions.h b/drivers/input/touchscreen/rmi_functions.h
deleted file mode 100644
index 75f1ded..0000000
--- a/drivers/input/touchscreen/rmi_functions.h
+++ /dev/null
@@ -1,111 +0,0 @@
-
-/**
- *
- * Synaptics Register Mapped Interface (RMI4) Functions Definition Header File.
- * 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.
- *
- *#############################################################################
- */
-
-#ifndef _RMI_FUNCTIONS_H
-#define _RMI_FUNCTIONS_H
-
-/* 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_functions {
- unsigned char functionNum;
-
- struct input_dev *input;
-
- /* Pointers to function specific functions for report, config, init
- and detect. */
- /* 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.
- */
- int (*report)(struct rmi_application *app,
- struct rmi_function_info *rfi, struct input_dev *input);
- int (*config)(struct rmi_application *app,
- struct rmi_function_info *rfi);
- int (*init)(struct input_dev *input);
- int (*detect)(struct rmi_application *app,
- struct rmi_function_info *rfi,
- struct rmi_function_descriptor *fd,
- unsigned int interruptCount);
-
- /* Standard kernel linked list implementation.
- * Documentation on how to use it can be found at
- * http://isis.poly.edu/kulesh/stuff/src/klist/.
- */
- struct list_head link;
-};
-
-
-/* Each time a new RMI4 function support is added the developer needs to
- bump the number of supported data src functions and add the info for
- that RMI4 function to the array along with pointers to the report,
- config, init and detect functions that they coded in rmi_function_xx.c
- and rmi_function_xx.h - where xx is the RMI4 function number for the new
- RMI4 data source function. The information for the RMI4 functions is
- obtained from the RMI4 specification document.
-*/
-#define rmi4_num_supported_data_src_fns 1
-
-/* add hdr files for all prototypes for RMI4 data source
- functions being supported. */
-#include "rmi_function_11.h"
-/* #include "rmi_function_19.h" */
-
-typedef int(*reportFuncPtr)(struct rmi_application *app,
- struct rmi_function_info *rfi, struct input_dev *input);
-typedef int(*configFuncPtr)(struct rmi_application *app,
- struct rmi_function_info *rfi);
-typedef int(*initFuncPtr)(struct input_dev *input);
-typedef int(*detectFuncPtr)(struct rmi_application *app,
- struct rmi_function_info *rfi, struct rmi_function_descriptor *fd,
- unsigned int interruptCount);
-
-struct rmi_functions_data {
- int functionNumber;
- reportFuncPtr reportFn;
- configFuncPtr configFn;
- initFuncPtr initFn;
- detectFuncPtr detectFn;
-};
-
-
-struct rmi_functions *rmi_find_function(int functionNum);
-int rmi_functions_init(struct input_dev *inputdev);
-
-#endif
diff --git a/drivers/input/touchscreen/rmi_i2c.c b/drivers/input/touchscreen/rmi_i2c.c
new file mode 100755
index 0000000..c531767
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_i2c.c
@@ -0,0 +1,588 @@
+/**
+ *
+ * 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.
+ *
+ *#############################################################################
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include "rmi_i2c.h"
+#include "rmi_drvr.h"
+
+
+#define DRIVER_NAME "rmi4_ts"
+
+#define DEVICE_NAME "rmi4_ts"
+
+/* Used to lock access to the page address.*/
+/* TODO: for multiple device support will need a per-device mutex */
+static DEFINE_MUTEX(page_mutex);
+
+
+static const struct i2c_device_id rmi_i2c_id_table[] = {
+ { DEVICE_NAME, 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;
+ struct rmi_phys_driver rmiphysdrvr;
+ struct i2c_client *i2cclient; /* pointer to i2c_client for later use in
+ read, write, read_multiple, etc. */
+ int page;
+};
+
+/*
+ * 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.
+ */
+int
+rmi_set_page(struct instance_data *instancedata, unsigned int page)
+{
+ char txbuf[2];
+ int retval;
+ txbuf[0] = 0xff;
+ txbuf[1] = page;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 2);
+ if (retval != 2) {
+ dev_err(&instancedata->i2cclient->dev,
+ "%s: Set page fail: %d\n", __func__, retval);
+ } else {
+ retval = 0;
+ instancedata->page = page;
+ }
+ 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 xero 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)
+{
+ struct instance_data *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ char txbuf[2];
+ int retval = 0;
+ int retry_count = 0;
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+retry:
+ txbuf[0] = address & 0xff;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 1);
+
+ if (retval != 1) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit;
+ }
+ retval = i2c_master_recv(instancedata->i2cclient, txbuf, 1);
+
+ if (retval != 1) {
+ if (++retry_count == 5) {
+ dev_err(&instancedata->i2cclient->dev,
+ "%s: Read of 0x%04x fail: %d\n",
+ __func__, address, retval);
+ } else {
+ mdelay(10);
+ rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ goto retry;
+ }
+ } else {
+ retval = 0;
+ *valp = txbuf[0];
+ }
+exit:
+ mutex_unlock(&page_mutex);
+ return retval;
+}
+
+/*
+ * 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 *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ char txbuf[2];
+ int retval = 0;
+ int retry_count = 0;
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+retry:
+ txbuf[0] = address & 0xff;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 1);
+
+ if (retval != 1) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit;
+ }
+ retval = i2c_master_recv(instancedata->i2cclient, valp, size);
+
+ if (retval != size) {
+ if (++retry_count == 5) {
+ dev_err(&instancedata->i2cclient->dev,
+ "%s: Read of 0x%04x size %d fail: %d\n",
+ __func__, address, size, retval);
+ } else {
+ mdelay(10);
+ rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ goto retry;
+ }
+ } else {
+ retval = 0;
+ }
+exit:
+ mutex_unlock(&page_mutex);
+ return retval;
+}
+
+
+/*
+ * Write a single register through i2c.
+ * 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 - The pointer to the rmi_phys_driver struct
+ * 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)
+{
+ struct instance_data *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ unsigned char txbuf[2];
+ int retval = 0;
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+ txbuf[0] = address & 0xff;
+ txbuf[1] = data;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 2);
+
+ /* TODO: Add in retry on writes only in certian error return values */
+ if (retval != 2) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit; /* Leave this in case we add code below */
+ }
+exit:
+ mutex_unlock(&page_mutex);
+ return retval;
+}
+
+/*
+ * Write multiple registers.
+ *
+ * For fast writes of 16 bytes of less we will re-use a buffer on the stack.
+ * For larger writes (like for RMI reflashing) we will need to allocate a
+ * temp buffer.
+ *
+ * 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 *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ unsigned char *txbuf;
+ unsigned char txbuf_most[17]; /* Use this buffer for fast writes of 16
+ bytes or less. The first byte will
+ contain the address at which to start
+ the write. */
+ int retval = 0;
+ int i;
+
+ if (size < sizeof(txbuf_most)) {
+ /* Avoid an allocation if we can help it. */
+ txbuf = txbuf_most;
+ } else {
+ /* over 16 bytes write we'll need to allocate a temp buffer */
+ txbuf = kmalloc(size + 1, GFP_KERNEL);
+ if (!txbuf)
+ return -ENOMEM;
+ }
+
+ /* Yes, it stinks here that we have to copy the buffer */
+ /* We copy from valp to txbuf leaving
+ the first location open for the address */
+ for (i = 0; i < size; i++)
+ txbuf[i + 1] = valp[i];
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+ txbuf[0] = address & 0xff; /* put the address in the first byte */
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, size + 1);
+
+ /* TODO: Add in retyr on writes only in certian error return values */
+ if (retval != 1) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit;
+ }
+exit:
+ mutex_unlock(&page_mutex);
+ if (txbuf != txbuf_most)
+ kfree(txbuf);
+ return retval;
+}
+
+/*
+ * 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 *instancedata = info;
+ disable_irq(instancedata->irq);
+ if (instancedata->rmiphysdrvr.attention)
+ instancedata->rmiphysdrvr.attention(&instancedata->rmiphysdrvr,
+ instancedata->instance_no);
+ return IRQ_HANDLED;
+}
+
+/* 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 *instancedata;
+ int retval = 0;
+ int i;
+ bool found = false;
+
+ struct rmi_i2c_data *rmii2cdata;
+ struct rmi_i2c_platformdata *platformdata;
+
+ dev_dbg(&client->dev, "Probing i2c RMI device\n");
+
+ /* Allocate and initialize the instance data for this client */
+ instancedata = kzalloc(sizeof(*instancedata), GFP_KERNEL);
+ if (!instancedata) {
+ dev_err(&client->dev,
+ "%s: Out of memory trying to allocate instance_data.\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ instancedata->rmiphysdrvr.name = DRIVER_NAME;
+ instancedata->rmiphysdrvr.write = rmi_i2c_write;
+ instancedata->rmiphysdrvr.read = rmi_i2c_read;
+ instancedata->rmiphysdrvr.write_multiple = rmi_i2c_write_multiple;
+ instancedata->rmiphysdrvr.read_multiple = rmi_i2c_read_multiple;
+ instancedata->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 */
+ instancedata->rmiphysdrvr.polling_required = true;
+
+ instancedata->page = 0xffff; /* Force a set page the first time */
+
+ /* cast to our struct rmi_i2c_data so we know
+ the fields (see rmi_ic2.h) */
+ rmii2cdata = client->dev.platform_data;
+
+ /* Loop through the platform data and locate the one that matches
+ the i2c_client I2C address */
+ for (i = 0; i < rmii2cdata->num_clients; i++) {
+ platformdata = &(rmii2cdata->platformdata[i]);
+ if (client->addr == platformdata->i2c_address) {
+ instancedata->instance_no = i;
+ found = true;
+ /* set the device name using the instance_no appended
+ to DEVICE_NAME to make a unique name */
+ dev_set_name(&client->dev,
+ "rmi4-i2c%d", instancedata->instance_no);
+
+ /* Determine if we need to poll (inefficient) or
+ use interrupts.
+ */
+ if (platformdata->irq) {
+ int irqtype;
+
+ instancedata->irq = platformdata->irq;
+ switch (platformdata->irq_type) {
+ case IORESOURCE_IRQ_HIGHEDGE:
+ irqtype = IRQF_TRIGGER_RISING;
+ break;
+ case IORESOURCE_IRQ_LOWEDGE:
+ irqtype = IRQF_TRIGGER_FALLING;
+ break;
+ case IORESOURCE_IRQ_HIGHLEVEL:
+ irqtype = IRQF_TRIGGER_HIGH;
+ break;
+ case IORESOURCE_IRQ_LOWLEVEL:
+ irqtype = IRQF_TRIGGER_LOW;
+ break;
+ default:
+ dev_warn(&client->dev,
+ "%s: Invalid IRQ flags in "
+ "platform data.\n",
+ __func__);
+ kfree(instancedata);
+ return -ENXIO;
+ }
+
+ retval = request_irq(instancedata->irq, i2c_attn_isr,
+ irqtype, "rmi_i2c", instancedata);
+ if (retval) {
+ dev_info(&client->dev,
+ "%s: Unable to get attn irq %d."
+ " Reverting to polling.\n",
+ __func__, instancedata->irq);
+ instancedata->rmiphysdrvr.polling_required = true;
+ } else {
+ dev_dbg(&client->dev,
+ "rmi_i2c_probe: got irq.\n");
+ instancedata->rmiphysdrvr.polling_required = false;
+ instancedata->rmiphysdrvr.irq = instancedata->irq;
+ }
+ } else {
+ instancedata->rmiphysdrvr.polling_required = true;
+ dev_info(&client->dev,
+ "%s: No IRQ info given. "
+ "Polling required.\n",
+ __func__);
+ }
+ }
+ }
+
+ /* if went through all the platform data list and didn't find a match
+ then notify that we are defaulting to polling */
+ if (!found) {
+ dev_info(&client->dev,
+ "%s: No platform data match found. "
+ "Defaulting to use polling.\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, instancedata);
+
+ /* Copy i2c_client pointer into instance_data's i2c_client pointer for
+ later use in rmi4_read, rmi4_write, etc. */
+ instancedata->i2cclient = client;
+
+ /* 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_sensors(&instancedata->rmiphysdrvr);
+ if (retval) {
+ dev_err(&client->dev, "%s: Failed to Register %s sensor drivers\n",
+ __func__, instancedata->rmiphysdrvr.name);
+ i2c_set_clientdata(client, NULL);
+ /* only free irq if we have an irq - otherwise the instance_data
+ will be 0 for that field since kzalloc was used to alloc id */
+ if (instancedata->irq)
+ free_irq(instancedata->irq, instancedata);
+ kfree(instancedata);
+ return retval;
+ }
+
+ dev_dbg(&client->dev, "%s: Successfully Registered %s sensor drivers\n",
+ __func__, instancedata->rmiphysdrvr.name);
+
+ return retval;
+}
+
+/* The Driver remove function. We tear down the instance data and unregister
+ * the phys driver in this call.
+ */
+static int
+rmi_i2c_remove(struct i2c_client *client)
+{
+ struct instance_data *instancedata =
+ i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s: Unregistering phys driver %s\n", __func__,
+ instancedata->rmiphysdrvr.name);
+
+ rmi_unregister_sensors(&instancedata->rmiphysdrvr);
+
+ dev_dbg(&client->dev, "%s: Unregistered phys driver %s\n",
+ __func__, instancedata->rmiphysdrvr.name);
+
+ /* only free irq if we have an irq - otherwise the instance_data
+ will be 0 for that field */
+ if (instancedata->irq)
+ free_irq(instancedata->irq, instancedata);
+
+ kfree(instancedata);
+ 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 = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .id_table = rmi_i2c_id_table,
+};
+
+/*
+ * Register ourselves with i2c Chip Driver.
+ *
+ */
+static int __init rmi_phys_i2c_init(void)
+{
+ return i2c_add_driver(&rmi_i2c_driver);
+}
+
+/*
+ * Un-register ourselves from the i2c Chip 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_i2c.h b/drivers/input/touchscreen/rmi_i2c.h
old mode 100644
new mode 100755
diff --git a/drivers/input/touchscreen/rmi_phys_i2c.c b/drivers/input/touchscreen/rmi_phys_i2c.c
deleted file mode 100644
index 397c717..0000000
--- a/drivers/input/touchscreen/rmi_phys_i2c.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/**
- *
- * Synaptics Register Mapped Interface (RMI4) I2C Physical Layer Driver.
- * 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.
- *
- *#############################################################################
- */
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include "rmi_i2c.h"
-#include "rmi.h"
-
-
-#define DRIVER_NAME "rmi4_ts"
-
-#define DEVICE_NAME "rmi4_ts"
-
-/* Used to lock access to the page address.*/
-/* TODO: for multiple device support will need a per-device mutex */
-static DEFINE_MUTEX(page_mutex);
-
-
-static const struct i2c_device_id rmi_i2c_id_table[] = {
- { DEVICE_NAME, 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;
- struct rmi_phys_driver rpd;
- struct i2c_client *i2cclient; /* pointer to i2c_client for later use in
- read, write, read_multiple, etc. */
- int page;
-};
-
-/*
- * 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.
- */
-int
-rmi_set_page(struct instance_data *id, unsigned int page)
-{
- char txbuf[2];
- int retval;
- txbuf[0] = 0xff;
- txbuf[1] = page;
- retval = i2c_master_send(id->i2cclient, txbuf, 2);
- if (retval != 2) {
- dev_err(&id->i2cclient->dev,
- "%s: Set page fail: %d\n", __func__, retval);
- } else {
- retval = 0;
- id->page = page;
- }
- 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 xero upon success (with the byte read in valp), non-zero upon error.
- */
-static int
-rmi_i2c_read(struct rmi_phys_driver *pd, unsigned short address, char *valp)
-{
- struct instance_data *id = container_of(pd, struct instance_data, rpd);
- char txbuf[2];
- int retval = 0;
- int retry_count = 0;
-
- /* Can't have anyone else changing the page behind our backs */
- mutex_lock(&page_mutex);
-
- if (((address >> 8) & 0xff) != id->page) {
- /* Switch pages */
- retval = rmi_set_page(id, ((address >> 8) & 0xff));
- if (retval)
- goto exit;
- }
-
-retry:
- txbuf[0] = address & 0xff;
- retval = i2c_master_send(id->i2cclient, txbuf, 1);
-
- if (retval != 1) {
- dev_err(&id->i2cclient->dev, "%s: Write fail: %d\n",
- __func__, retval);
- goto exit;
- }
- retval = i2c_master_recv(id->i2cclient, txbuf, 1);
-
- if (retval != 1) {
- if (++retry_count == 5) {
- dev_err(&id->i2cclient->dev,
- "%s: Read of 0x%04x fail: %d\n",
- __func__, address, retval);
- } else {
- mdelay(10);
- rmi_set_page(id, ((address >> 8) & 0xff));
- goto retry;
- }
- } else {
- retval = 0;
- *valp = txbuf[0];
- }
-exit:
- mutex_unlock(&page_mutex);
- return retval;
-}
-
-/*
- * 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 *pd, unsigned short address,
- char *valp, int size)
-{
- struct instance_data *id = container_of(pd, struct instance_data, rpd);
- char txbuf[2];
- int retval = 0;
- int retry_count = 0;
-
- /* Can't have anyone else changing the page behind our backs */
- mutex_lock(&page_mutex);
-
- if (((address >> 8) & 0xff) != id->page) {
- /* Switch pages */
- retval = rmi_set_page(id, ((address >> 8) & 0xff));
- if (retval)
- goto exit;
- }
-
-retry:
- txbuf[0] = address & 0xff;
- retval = i2c_master_send(id->i2cclient, txbuf, 1);
-
- if (retval != 1) {
- dev_err(&id->i2cclient->dev, "%s: Write fail: %d\n",
- __func__, retval);
- goto exit;
- }
- retval = i2c_master_recv(id->i2cclient, valp, size);
-
- if (retval != size) {
- if (++retry_count == 5) {
- dev_err(&id->i2cclient->dev,
- "%s: Read of 0x%04x size %d fail: %d\n",
- __func__, address, size, retval);
- } else {
- mdelay(10);
- rmi_set_page(id, ((address >> 8) & 0xff));
- goto retry;
- }
- } else {
- retval = 0;
- }
-exit:
- mutex_unlock(&page_mutex);
- return retval;
-}
-
-
-/*
- * Write a single register through i2c.
- * 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 - The pointer to the rmi_phys_driver struct
- * 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 *pd, unsigned short address, char data)
-{
- struct instance_data *id = container_of(pd, struct instance_data, rpd);
- unsigned char txbuf[2];
- int retval = 0;
-
- /* Can't have anyone else changing the page behind our backs */
- mutex_lock(&page_mutex);
-
- if (((address >> 8) & 0xff) != id->page) {
- /* Switch pages */
- retval = rmi_set_page(id, ((address >> 8) & 0xff));
- if (retval)
- goto exit;
- }
-
- txbuf[0] = address & 0xff;
- txbuf[1] = data;
- retval = i2c_master_send(id->i2cclient, txbuf, 2);
-
- /* TODO: Add in retry on writes only in certian error return values */
- if (retval != 2) {
- dev_err(&id->i2cclient->dev, "%s: Write fail: %d\n",
- __func__, retval);
- goto exit; /* Leave this in case we add code below */
- }
-exit:
- mutex_unlock(&page_mutex);
- return retval;
-}
-
-/*
- * Write multiple registers.
- *
- * For fast writes of 16 bytes of less we will re-use a buffer on the stack.
- * For larger writes (like for RMI reflashing) we will need to allocate a
- * temp buffer.
- *
- * 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 *pd, unsigned short address,
- char *valp, int size)
-{
- struct instance_data *id = container_of(pd, struct instance_data, rpd);
- unsigned char *txbuf;
- unsigned char txbuf_most[17]; /* Use this buffer for fast writes of 16
- bytes or less. The first byte will
- contain the address at which to start
- the write. */
- int retval = 0;
- int i;
-
- if (size < sizeof(txbuf_most)) {
- /* Avoid an allocation if we can help it. */
- txbuf = txbuf_most;
- } else {
- /* over 16 bytes write we'll need to allocate a temp buffer */
- txbuf = kmalloc(size + 1, GFP_KERNEL);
- if (!txbuf)
- return -ENOMEM;
- }
-
- /* Yes, it stinks here that we have to copy the buffer */
- /* We copy from valp to txbuf leaving
- the first location open for the address */
- for (i = 0; i < size; i++)
- txbuf[i + 1] = valp[i];
-
- /* Can't have anyone else changing the page behind our backs */
- mutex_lock(&page_mutex);
-
- if (((address >> 8) & 0xff) != id->page) {
- /* Switch pages */
- retval = rmi_set_page(id, ((address >> 8) & 0xff));
- if (retval)
- goto exit;
- }
-
- txbuf[0] = address & 0xff; /* put the address in the first byte */
- retval = i2c_master_send(id->i2cclient, txbuf, size + 1);
-
- /* TODO: Add in retyr on writes only in certian error return values */
- if (retval != 1) {
- dev_err(&id->i2cclient->dev, "%s: Write fail: %d\n",
- __func__, retval);
- goto exit;
- }
-exit:
- mutex_unlock(&page_mutex);
- if (txbuf != txbuf_most)
- kfree(txbuf);
- return retval;
-}
-
-/*
- * 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 *id = info;
- disable_irq(id->irq);
- if (id->rpd.attention)
- id->rpd.attention(&id->rpd, id->instance_no);
- return IRQ_HANDLED;
-}
-
-/* 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 *id;
- int retval = 0;
- int i;
- bool found = false;
-
- struct rmi_i2c_data *rmii2cdata;
- struct rmi_i2c_platformdata *platformdata;
-
- dev_dbg(&client->dev, "Probing i2c RMI device\n");
-
- /* Allocate and initialize the instance data for this client */
- id = kzalloc(sizeof(*id), GFP_KERNEL);
- if (!id) {
- dev_err(&client->dev,
- "%s: Out of memory trying to allocate instance_data.\n",
- __func__);
- return -ENOMEM;
- }
-
- id->rpd.name = DRIVER_NAME;
- id->rpd.write = rmi_i2c_write;
- id->rpd.read = rmi_i2c_read;
- id->rpd.write_multiple = rmi_i2c_write_multiple;
- id->rpd.read_multiple = rmi_i2c_read_multiple;
- id->rpd.module = THIS_MODULE;
- id->rpd.polling_required = true; /* 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 */
-
- id->page = 0xffff; /* So we set the page correctly
- the first time */
-
- /* cast to our struct rmi_i2c_data so we know
- the fields (see rmi_ic2.h) */
- rmii2cdata = client->dev.platform_data;
-
- /* Loop through the platform data and locate the one that matches
- the i2c_client I2C address */
- for (i = 0; i < rmii2cdata->num_clients; i++) {
- platformdata = &(rmii2cdata->platformdata[i]);
- if (client->addr == platformdata->i2c_address) {
- id->instance_no = i;
- found = true;
- /* set the device name using the instance_no appended
- to DEVICE_NAME to make a unique name */
- dev_set_name(&client->dev,
- "rmi4-i2c%d", id->instance_no);
-
- /* Determine if we need to poll (inefficient) or
- use interrupts.
- */
- if (platformdata->irq) {
- int irqtype;
-
- id->irq = platformdata->irq;
- switch (platformdata->irq_type) {
- case IORESOURCE_IRQ_HIGHEDGE:
- irqtype = IRQF_TRIGGER_RISING;
- break;
- case IORESOURCE_IRQ_LOWEDGE:
- irqtype = IRQF_TRIGGER_FALLING;
- break;
- case IORESOURCE_IRQ_HIGHLEVEL:
- irqtype = IRQF_TRIGGER_HIGH;
- break;
- case IORESOURCE_IRQ_LOWLEVEL:
- irqtype = IRQF_TRIGGER_LOW;
- break;
- default:
- dev_warn(&client->dev,
- "%s: Invalid IRQ flags in "
- "platform data.\n",
- __func__);
- kfree(id);
- return -ENXIO;
- }
-
- retval = request_irq(id->irq, i2c_attn_isr,
- irqtype, "rmi_i2c", id);
- if (retval) {
- dev_info(&client->dev,
- "%s: Unable to get attn irq %d."
- " Reverting to polling.\n",
- __func__, id->irq);
- id->rpd.polling_required = true;
- } else {
- dev_dbg(&client->dev,
- "rmi_i2c_probe: got irq.\n");
- id->rpd.polling_required = false;
- id->rpd.irq = id->irq;
- }
- } else {
- id->rpd.polling_required = true;
- dev_info(&client->dev,
- "%s: No IRQ info given. "
- "Polling required.\n",
- __func__);
- }
- }
- }
-
- /* if went through all the platform data list and didn't find a match
- then notify that we are defaulting to polling */
- if (!found) {
- dev_info(&client->dev,
- "%s: No platform data match found. "
- "Defaulting to use polling.\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, id);
-
- /* Copy i2c_client pointer into instance_data's i2c_client pointer for
- later use in rmi4_read, rmi4_write, etc. */
- id->i2cclient = client;
-
- /* Register physical driver - this will call the detect function that
- will then scan the device and determine the supported RMI4 functions.
- */
- retval = rmi_register_phys_driver(&id->rpd);
- if (retval) {
- dev_err(&client->dev, "%s: Failed to Register %s phys driver\n",
- __func__, id->rpd.name);
- i2c_set_clientdata(client, NULL);
- /* only free irq if we have an irq - otherwise the instance_data
- will be 0 for that field since kzalloc was used to alloc id */
- if (id->irq)
- free_irq(id->irq, id);
- kfree(id);
- return retval;
- }
-
- dev_dbg(&client->dev, "%s: Successfully Registered %s phys driver\n",
- __func__, id->rpd.name);
-
- return retval;
-}
-
-/* The Driver remove function. We tear down the instance data and unregister
- * the phys driver in this call.
- */
-static int
-rmi_i2c_remove(struct i2c_client *client)
-{
- struct instance_data *id = i2c_get_clientdata(client);
-
- dev_dbg(&client->dev, "%s: Unregistering phys driver %s\n", __func__, id->rpd.name);
-
- rmi_unregister_phys_driver(&id->rpd);
-
- dev_dbg(&client->dev, "%s: Unregistered phys driver %s\n",
- __func__, id->rpd.name);
-
- /* only free irq if we have an irq - otherwise the instance_data
- will be 0 for that field */
- if (id->irq)
- free_irq(id->irq, id);
-
- kfree(id);
- 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 = DRIVER_NAME,
- .owner = THIS_MODULE,
- },
- .id_table = rmi_i2c_id_table,
-};
-
-/*
- * Register ourselves with i2c Chip Driver.
- *
- */
-static int __init rmi_phys_i2c_init(void)
-{
- return i2c_add_driver(&rmi_i2c_driver);
-}
-
-/*
- * Un-register ourselves from the i2c Chip 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_sensor.c b/drivers/input/touchscreen/rmi_sensor.c
new file mode 100755
index 0000000..1f216bf
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_sensor.c
@@ -0,0 +1,706 @@
+/**
+ * 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.
+ *
+ *#############################################################################
+ */
+
+
+static const char sensorname[] = "sensor";
+
+#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_bus.h"
+#include "rmi_function.h"
+#include "rmi_sensor.h"
+
+extern void rmi_function_attn(struct rmi_function_device *function);
+
+
+#define RMI_REPORT_RATE_80 0
+#define RMI_REPORT_RATE_40 (1 << 6)
+
+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_LOCATION 0x00E9
+#define PDT_END_SCAN_LOCATION 0x0005
+#define PDT_ENTRY_SIZE 0x0006
+
+static DEFINE_MUTEX(rfi_mutex);
+
+struct rmi_functions *rmi_find_function(int functionNum);
+
+int rmi_read(struct rmi_sensor_driver *sensor, unsigned short address, char *dest)
+{
+ struct rmi_phys_driver *rpd = sensor->rpd;
+ 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;
+ 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;
+ 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;
+ if (!rpd)
+ return -ENODEV;
+ return rpd->write_multiple(rpd, address, data, length);
+}
+EXPORT_SYMBOL(rmi_write_multiple);
+
+bool rmi_polling_required(struct rmi_sensor_driver *sensor)
+{
+ return sensor->polling_required;
+}
+EXPORT_SYMBOL(rmi_polling_required);
+
+/** Functions can call this in order to dispatch IRQs. */
+void dispatchIRQs(struct rmi_sensor_driver *sensor, unsigned int irqRegisterSet,
+ unsigned int irqStatus)
+{
+ struct rmi_functions *fn;
+ struct rmi_function_info *rfi;
+ struct rmi_phys_driver *rpd;
+ struct rmi_module_info *rmi;
+
+ /* check each function and if the interrupt for function has been
+ * triggered then call that RMI4 functions inthandler function.
+ */
+ rpd = sensor->rpd; /* get ptr to rmi_physical_driver from app */
+ rmi = &(rpd->rmi); /* get ptr to rmi_module_info from physical driver */
+
+ list_for_each_entry(rfi, &rmi->functions, link) {
+ if ((rfi->interruptRegister == irqRegisterSet) &&
+ (rfi->interruptMask & irqStatus)) {
+ fn = rmi_find_function(rfi->functionNum);
+ if (fn) {
+ if (fn->inthandler != NULL) {
+ /* Call the functions interrupt handler function. */
+ fn->inthandler(sensor, rfi, (rfi->interruptMask & irqStatus));
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * 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, int instance)
+{
+ /* All we have to do is schedule work. */
+ schedule_work(&(physdrvr->sensor->work));
+}
+
+/**
+ * This is the meat of the driver. It notifies any functions that there
+ * is an interrupt and these will schedule work to read, read a block, etc.
+ * and do the appropriate thing according to the function.
+ */
+void attn_notify(struct rmi_sensor_driver *sensor)
+{
+ struct rmi_functions *fn;
+ struct rmi_function_info *rfi;
+ struct rmi_phys_driver *rpd;
+ struct rmi_module_info *rmi;
+
+ /* check each function that has data sources and if the interrupt for
+ * that triggered then call that RMI4 functions report() function to
+ * gather data and report it to the input subsystem */
+ rpd = sensor->rpd; /* get ptr to rmi_physical_driver from app */
+ rmi = &(rpd->rmi); /* get ptr to rmi_module_info from physical driver */
+
+ list_for_each_entry(rfi, &rmi->functions, link) {
+ bool found;
+ found = false;
+ fn = rmi_find_function(rfi->functionNum);
+ if (fn) {
+ found = true;
+ if (fn->attention != NULL) {
+ /* Call the attention function. */
+ fn->attention(sensor, rfi);
+ }
+ }
+ }
+}
+
+/* This is the worker function - it simply has to call int_notify. */
+static void sensor_work_func(struct work_struct *work)
+{
+ struct rmi_sensor_driver *sensor = container_of(work,
+ struct rmi_sensor_driver, work);
+
+ attn_notify(sensor);
+
+ /* we only need to enable the irq if doing interrupts */
+ if (!rmi_polling_required(sensor))
+ enable_irq(sensor->rpd->irq);
+}
+
+/* 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);
+
+ 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.
+ */
+static int probe(struct rmi_sensor_driver *sensor)
+{
+ struct rmi_phys_driver *rpd;
+ struct rmi_function_info *rfi;
+ struct rmi_module_info *rmi;
+ int data_sources;
+
+
+ rpd = sensor->rpd;
+ rmi = &(rpd->rmi);
+
+ if (!rpd) {
+ printk(KERN_ERR "%s: Invalid rmi physical driver - null ptr: %p\n", __func__, rpd);
+ return 0;
+ }
+
+ /* Check if this is a Synaptics device - report if not - but continue. */
+ /* This will allow other vendors to use RMI for their sensors. */
+ if (rmi->mfgid != 1) { /* Synaptics? */
+ printk(KERN_INFO "%s: non-Synaptics mfg id: %d\n",
+ __func__, rmi->mfgid);
+ }
+
+ /* for each function entry in the list accumulate it's number of data
+ sources */
+ list_for_each_entry(rfi, &rmi->functions, link) {
+ data_sources += rfi->numSources;
+ }
+
+ /* Report if we found any data sources - coninue if not since
+ we could have a sensor that is un-flashed and only has Fn $01 and
+ Fn $34 */
+ if (data_sources) {
+ /* We have detected one or more data sources such as
+ 2D Sensors, buttons, etc. */
+ printk(KERN_INFO "%s: Found %d data sources for sensor.\n",
+ __func__, data_sources);
+ } else {
+ /* we don't have any data sources for this sensor - oops!
+ - either an un-flashed sensor or bad!! */
+ printk(KERN_INFO "%s: No data sources found for sensor.\n",
+ __func__);
+ }
+
+ return 1;
+}
+
+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 *rfi;
+ struct rmi_phys_driver *rpd;
+ struct rmi_module_info *rmi;
+
+ rpd = sensor->rpd; /* get ptr to rmi_physical_driver from app */
+ rmi = &(rpd->rmi); /* get ptr to rmi_module_info from physical driver */
+
+ list_for_each_entry(rfi, &rmi->functions, link) {
+ /* Get and print some info about the data sources... */
+ struct rmi_functions *fn;
+ bool found = false;
+ /* check if function number matches - if so call that
+ config function */
+ fn = rmi_find_function(rfi->functionNum);
+ if (fn) {
+ found = true;
+ if (fn->config) {
+ fn->config(sensor, rfi);
+ } else {
+ /* the developer did not add in the
+ pointer to the config function into
+ rmi4_supported_data_src_functions */
+ printk(KERN_ERR
+ "%s: no config function for "
+ "function 0x%x\n",
+ __func__, rfi->functionNum);
+ break;
+ }
+ }
+
+ if (!found) {
+ /* 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 */
+ printk(KERN_ERR"%s: could not find support "
+ "for function 0x%x\n",
+ __func__, rfi->functionNum);
+ }
+
+ /* if we are not doing polling then enable the
+ interrupts for the data sources for this function */
+ if (!rmi_polling_required(sensor)) {
+ /* Turn on interrupts for this
+ function's data sources. */
+ rmi_write(sensor, sensor->sensorControlBaseAddr + 1 +
+ rfi->interruptRegister,
+ rfi->interruptMask);
+ printk(KERN_INFO
+ "%s: Interrupt Driven - turning on "
+ "interrupts for function 0x%x\n",
+ __func__, rfi->functionNum);
+ }
+ }
+
+ /* if we are not polling we need to set up the interrupt worker
+ thread - otherwise we need to set up the polling callback and
+ worker thread. */
+ if (!rmi_polling_required(sensor)) {
+ /* We're interrupt driven, so set up packet rate and the worker
+ thread function. */
+ if (HZ < 500) {
+ /* The default packet rate of 80 packets per
+ * second is too fast (the Linux time slice for
+ * sub-GHz processors is only 100 times per second).
+ * So re-program it to 40 packets per second.
+ */
+ rmi_write(sensor, sensor->sensorControlBaseAddr, RMI_REPORT_RATE_40);
+ }
+
+ INIT_WORK(&sensor->work, sensor_work_func);
+
+ } else {
+ /* We're polling driven, so set up the polling timer
+ and timer function. */
+ INIT_WORK(&sensor->work, sensor_work_func);
+ 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);
+ }
+}
+
+/*
+ * 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.
+ *
+ */
+int rmi_sensor_register_functions(struct rmi_sensor_driver *sensor)
+{
+ struct rmi_function_device *function;
+ unsigned int interruptRegisterCount;
+ struct rmi_phys_driver *rpd;
+ int i;
+ unsigned short fn01QueryBaseAddr; /* RMI4 device control */
+ unsigned short fn01ControlBaseAddr;
+ unsigned char std_queries[21];
+ unsigned char interruptCount;
+ struct rmi_function_info *rfi;
+ struct rmi_function_descriptor rmi_fd;
+ struct rmi_functions *fn;
+ bool found;
+ int retval;
+
+ pr_debug("%s: Registering sensor functions\n", __func__);
+
+ retval = 0;
+
+ /* Scan device for functions that may be supported */
+ {
+ pr_debug("%s: Scanning sensor for Functions:\n", __func__);
+
+ interruptCount = 0;
+ rpd = sensor->rpd;
+
+ /* init the physical drivers RMI module
+ info list of functions */
+ INIT_LIST_HEAD(&rpd->rmi.functions);
+
+ /* Read the Page Descriptor Table to determine what functions
+ are present */
+ 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) {
+ rfi = NULL;
+
+ if (rmi_fd.functionNum != 0x00 && rmi_fd.functionNum != 0xff) {
+ switch (rmi_fd.functionNum & 0xff) {
+ case 0x01:
+ /* save FN $01 info for use below */
+ pr_debug("%s: Fn $01 Found - RMI Device Control\n", __func__);
+ fn01QueryBaseAddr =
+ rmi_fd.queryBaseAddr;
+ fn01ControlBaseAddr =
+ rmi_fd.controlBaseAddr;
+ break;
+
+ default:
+ /* determine if the function is supported and if so
+ then bind this function device to the sensor */
+ if (rmi_fd.interruptSrcCnt) {
+ rfi = kmalloc(sizeof(*rfi), GFP_KERNEL);
+
+ if (!rfi) {
+ printk(KERN_ERR "%s: could not allocate memory for function 0x%x\n",
+ __func__, rmi_fd.functionNum);
+ retval = -ENOMEM;
+ goto exit_fail;
+ } else {
+
+ /* Get the ptr to the detect function based on
+ the function number */
+ found = false;
+ fn = rmi_find_function(rmi_fd.functionNum);
+ if (fn) {
+ found = true;
+ fn->detect(rpd->sensor, rfi, &rmi_fd,
+ interruptCount);
+
+ /* Create a function device and function driver for this Fn */
+ function = kzalloc(sizeof(*function), GFP_KERNEL);
+ if (!function) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_function_device\n", __func__);
+ return -ENOMEM;
+ }
+
+ function->rmi_funcs.inthandler = fn->inthandler;
+ function->rmi_funcs.detect = fn->detect;
+ function->rmi_funcs.config = fn->config;
+ function->rmi_funcs.init = fn->init;
+ function->rmi_funcs.attention = fn->attention;
+ function->rmi_funcs.workfn = fn->workfn;
+ function->sensor = sensor;
+ function->rfi = rfi;
+ rfi->function = 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 (rfi->interruptMask == 0 && fn->inthandler != NULL) {
+ printk(KERN_DEBUG "%s: Can't have an interrupt mask %d for function device %02x\n",
+ __func__, rfi->interruptMask, fn->functionNum);
+ }
+
+
+ /* 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 (rfi->interruptMask != 0 && fn->inthandler == NULL) {
+ printk(KERN_DEBUG "%s: Can't have a non-zero interrupt mask %d for function device %02x with a NULL inthandler fn.\n",
+ __func__, rfi->interruptMask, fn->functionNum);
+ }
+
+ /* Register the rmi function device */
+ retval = rmi_function_register_device(function, fn->functionNum);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed rmi_function_register_device.\n",
+ __func__);
+ return retval;
+ }
+ }
+
+ if (!found) {
+ printk(KERN_ERR "%s: could not find support for function 0x%x\n",
+ __func__, rmi_fd.functionNum);
+ }
+ }
+ } else {
+ printk(KERN_INFO "%s: Found Function %02x - Ignored.\n", __func__, rmi_fd.functionNum & 0xff);
+ }
+ break;
+ }
+
+ /* bump interrupt count for
+ next iteration */
+ interruptCount +=
+ (rmi_fd.interruptSrcCnt & 0x7);
+
+ /* link this function info to the RMI module infos list
+ of functions */
+ pr_debug("%s: Adding function "
+ "0x%x with %d sources.\n",
+ __func__, rfi->functionNum,
+ rfi->numSources);
+
+ mutex_lock(&rfi_mutex);
+ list_add_tail(&rfi->link,
+ &rpd->rmi.functions);
+ mutex_unlock(&rfi_mutex);
+
+ } else {
+ /* A zero or 0xff in the function number
+ signals the end of the PDT */
+ pr_debug("%s: Found End of PDT\n",
+ __func__);
+ break;
+ }
+ } else {
+ /* 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. */
+ printk(KERN_ERR "%s: Read Error 0x%x when "
+ "reading next PDT entry - "
+ "ending PDT scan.\n",
+ __func__, retval);
+ break;
+ }
+ }
+
+ /* calculate the interrupt register count - used in the
+ ISR to read the correct number of interrupt registers */
+ interruptRegisterCount = (interruptCount + 7) / 8;
+
+ /* Function $01 will be used to query the product properties,
+ product ID and other sensor related info. NOTE: Even an
+ unflashed device will still have FN $01
+ */
+
+ /* Load up the standard queries and get the RMI4 module info */
+ retval = rpd->read_multiple(rpd, fn01QueryBaseAddr, std_queries,
+ sizeof(std_queries));
+ if (retval) {
+ printk(KERN_ERR "%s: Failed reading standard sensor queries.\n",
+ __func__);
+ retval = -EIO;
+ goto exit_fail;
+ }
+
+ /* Currently supported RMI version is 4.0 */
+ rpd->rmi.rmi_maj_ver = 4;
+ rpd->rmi.rmi_min_ver = 0;
+
+ /* get manufacturer id, properties, product info,
+ date code, tester id, serial num and product id (name) */
+ rpd->rmi.mfgid = std_queries[0];
+ rpd->rmi.properties = std_queries[1];
+
+ rpd->rmi.prod_info[0] = std_queries[2];
+ rpd->rmi.prod_info[1] = std_queries[3];
+
+ /* year - 2001-2032 */
+ rpd->rmi.date_code[0] = std_queries[4] & 0x1f;
+ /* month - 1-12 */
+ rpd->rmi.date_code[1] = std_queries[5] & 0x0f;
+ /* day - 1-31 */
+ rpd->rmi.date_code[2] = std_queries[6] & 0x1f;
+
+ rpd->rmi.tester_id = ((std_queries[7] & 0x7f) << 8) |
+ (std_queries[8] & 0x7f);
+
+ rpd->rmi.serial_num = ((std_queries[9] & 0x7f) << 8) |
+ (std_queries[10] & 0x7f);
+
+ memcpy(rpd->rmi.prod_id, &std_queries[11], 10);
+ rpd->rmi.prod_id[10] = 0;
+
+ pr_debug("%s: RMI Protocol: %d.%d\n",
+ __func__, rpd->rmi.rmi_maj_ver, rpd->rmi.rmi_min_ver);
+ pr_debug("%s: Manufacturer: %d", __func__,
+ rpd->rmi.mfgid);
+ if (rpd->rmi.mfgid == 1)
+ pr_debug(" (Synaptics)");
+ pr_debug("\n");
+
+ pr_debug("%s: Properties: 0x%x\n",
+ __func__, rpd->rmi.properties);
+
+ pr_debug("%s: Product Info: 0x%x 0x%x\n",
+ __func__, rpd->rmi.prod_info[0], rpd->rmi.prod_info[1]);
+
+ pr_debug("%s: Date Code: Year : %d Month: %d Day: %d\n",
+ __func__, rpd->rmi.date_code[0], rpd->rmi.date_code[1],
+ rpd->rmi.date_code[2]);
+
+ pr_debug("%s: Tester ID: %d\n", __func__, rpd->rmi.tester_id);
+
+ pr_debug("%s: Serial Number: 0x%x\n",
+ __func__, rpd->rmi.serial_num);
+
+ pr_debug("%s: Product ID: %s\n", __func__, rpd->rmi.prod_id);
+ }
+
+ return 0;
+
+exit_fail:
+ return retval;
+}
+EXPORT_SYMBOL(rmi_sensor_register_functions);
+
+int rmi_sensor_register_device(struct rmi_sensor_device *dev, int index)
+{
+ int status;
+
+ printk(KERN_INFO "%s: Registering sensor device.\n", __func__);
+
+ /* make name - sensor00, sensor01, etc. */
+ dev_set_name(&dev->dev, "sensor%02d", index);
+ status = device_register(&dev->dev);
+
+ return status;
+}
+EXPORT_SYMBOL(rmi_sensor_register_device);
+
+static void rmi_sensor_unregister_device(struct rmi_sensor_device *rmisensordev)
+{
+ printk(KERN_INFO "%s: Unregistering sensor device.\n", __func__);
+
+ device_unregister(&rmisensordev->dev);
+}
+EXPORT_SYMBOL(rmi_sensor_unregister_device);
+
+int rmi_sensor_register_driver(struct rmi_sensor_driver *driver)
+{
+ static int index;
+ int ret;
+ char *drvrname;
+
+ printk(KERN_INFO "%s: Registering sensor driver.\n", __func__);
+
+ /* assign the bus type for this driver to be rmi bus */
+ driver->drv.bus = &rmi_bus_type;
+ /* Create a function device and function driver for this Fn */
+ drvrname = kzalloc(sizeof(sensorname) + 4, GFP_KERNEL);
+ if (!drvrname) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_sensor_driver name.\n", __func__);
+ return -ENOMEM;
+ }
+ sprintf(drvrname, "sensor%02d", index++);
+
+ driver->drv.name = drvrname;
+ driver->module = driver->drv.owner;
+
+ /* register the sensor driver */
+ ret = driver_register(&driver->drv);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed driver_register %d\n",
+ __func__, ret);
+ goto exit_fail;
+ }
+
+ /* register the functions on the sensor */
+ ret = rmi_sensor_register_functions(driver);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed rmi_sensor_register_functions %d\n",
+ __func__, ret);
+ }
+
+exit_fail:
+ return ret;
+}
+EXPORT_SYMBOL(rmi_sensor_register_driver);
+
+static void rmi_sensor_unregister_driver(struct rmi_sensor_driver *driver)
+{
+ printk(KERN_INFO "%s: Unregistering sensor driver.\n", __func__);
+
+ /* 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 */
+
+ driver_unregister(&driver->drv);
+}
+EXPORT_SYMBOL(rmi_sensor_unregister_driver);
+
+
+static int __init rmi_sensor_init(void)
+{
+ printk(KERN_DEBUG "%s: RMI Sensor Init\n", __func__);
+ return 0;
+}
+
+static void __exit rmi_sensor_exit(void)
+{
+ printk(KERN_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_sensor.h b/drivers/input/touchscreen/rmi_sensor.h
new file mode 100755
index 0000000..593253f
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_sensor.h
@@ -0,0 +1,121 @@
+/**
+ *
+ * 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.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_SENSOR_H
+#define _RMI_SENSOR_H
+
+struct rmi_sensor_driver {
+ struct module *module;
+ struct device_driver drv;
+
+ /* 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, int instance);
+ /* 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 irqRegisterSet,
+ unsigned int irqStatus);
+
+ /* Register Functions
+ * This function is called in the rmi bus
+ * driver to have the sensor driver scan for any supported
+ * functions on the sensor and add devices for each one.
+ */
+ void (*rmi_sensor_register_functions)(struct rmi_sensor_driver *sensor);
+
+ unsigned short sensorQueryBaseAddr; /* RMI4 sensor control */
+ unsigned short sensorControlBaseAddr;
+ unsigned short sensorCommandBaseAddr;
+ unsigned short sensorDataBaseAddr;
+ unsigned int interruptRegisterCount;
+
+ 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;
+
+ /* This list is for keeping around the list of sensors.
+ * Every time that a physical device is detected by the
+ * physical layer - be it i2c, spi, or some other - then
+ * we need to bind the physical layer to the device. When
+ * the Page Descriptor Table is scanned and when Function $01
+ * is found then a new sensor device is created. The corresponding
+ * rmi_phys_driver struct pointer needs to be bound to the new
+ * sensor since Function $01 will be used to control and get
+ * interrupt information about the particular data source that is
+ * doing the interrupt. The rmi_phys_driver contains the pointers
+ * to the particular read, write, read_multiple, write_multiple
+ * functions for this device. This rmi_phys_driver struct will
+ * have to be up-bound to any drivers upstream that need it.
+ */
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head sensor_drivers; /* link sensor drivers into list */
+};
+
+/* 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;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head sensors; /* link sensors into list */
+};
+
+int rmi_sensor_register_device(struct rmi_sensor_device *dev, int index);
+int rmi_sensor_register_driver(struct rmi_sensor_driver *driver);
+int rmi_sensor_register_functions(struct rmi_sensor_driver *sensor);
+
+#endif
+
diff --git a/drivers/input/touchscreen/rmi_spi.c b/drivers/input/touchscreen/rmi_spi.c
new file mode 100755
index 0000000..2d6ada7
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_spi.c
@@ -0,0 +1,477 @@
+/**
+ *
+ * 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/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include "rmi_spi.h"
+#include "rmi_drvr.h"
+
+#define DRIVER_NAME "rmi4_ts"
+#define DEVICE_NAME "rmi4_ts"
+
+#define RMI_TDPB 65 /* 65 microseconds inter-byte delay between bytes for RMI chip*/
+#define SPI_BUFSIZ 32
+
+static u8 *buf;
+
+/** This is a count of how many clients are accessing this driver.
+*/
+static int num_clients;
+static struct rmi_spi_platformdata *platformdata;
+
+
+/**
+ * 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;
+ struct rmi_phys_driver rpd;
+ struct spi_device *spidev;
+};
+
+
+static int spi_xfer(struct spi_device *spi,
+ const u8 *txbuf, unsigned n_tx,
+ u8 *rxbuf, unsigned n_rx)
+{
+ static DECLARE_MUTEX(lock);
+
+ int status;
+ struct spi_message message;
+ struct spi_transfer x[2];
+ u8 *local_buf;
+
+
+ if ((n_tx + n_rx) > SPI_BUFSIZ)
+ return -EINVAL;
+
+ spi_message_init(&message);
+ memset(x, 0, sizeof x);
+ if (n_tx) {
+ x[0].len = n_tx;
+ x[0].delay_usecs = RMI_TDPB;
+ spi_message_add_tail(&x[0], &message);
+ }
+ if (n_rx) {
+#ifdef CONFIG_ARCH_OMAP
+ x[1].len = n_rx-1; /* since OMAP has one dummy byte. */
+#else
+ x[1].len = n_rx;
+#endif
+ x[1].delay_usecs = RMI_TDPB;
+ spi_message_add_tail(&x[1], &message);
+ }
+
+ /* ... unless someone else is using the pre-allocated buffer */
+ if (down_trylock(&lock)) {
+ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
+ if (!local_buf)
+ return -ENOMEM;
+ } else
+ local_buf = buf;
+
+ memcpy(local_buf, txbuf, n_tx);
+
+
+ x[0].tx_buf = local_buf;
+ x[1].rx_buf = local_buf + n_tx;
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0) {
+ memcpy(rxbuf, x[1].rx_buf, n_rx);
+ status = message.status;
+ } else {
+ printk(KERN_ERR "spi_sync fials!\n");
+ }
+
+ if (x[0].tx_buf == buf)
+ up(&lock);
+ else
+ kfree(local_buf);
+
+ return status;
+}
+
+/**
+ * Read a single register through spi.
+ * \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(struct rmi_phys_driver *pd, unsigned short address, char *valp)
+{
+ struct instance_data *id = container_of(pd, struct instance_data, rpd);
+
+ char rxbuf[2];
+ int retval;
+ unsigned short addr = address;
+
+ addr = ((addr & 0xff00) >> 8);
+ address = ((address & 0x00ff) << 8);
+ addr |= address;
+ addr |= 0x80; /* High bit set indicates read. */
+
+ retval = spi_xfer(id->spidev, (u8 *)&addr, 2, rxbuf, 1);
+
+ *valp = rxbuf[0];
+
+ return retval;
+}
+
+/**
+ * Same as rmi_spi_read, 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(struct rmi_phys_driver *pd, unsigned short address,
+ char *valp, int size)
+{
+ struct instance_data *id = container_of(pd, struct instance_data, rpd);
+ int retval;
+
+ unsigned short addr = address;
+
+ addr = ((addr & 0xff00) >> 8);
+ address = ((address & 0x00ff) << 8);
+ addr |= address;
+ addr |= 0x80; /* High bit set indicates read. */
+
+ retval = spi_xfer(id->spidev, (u8 *)&addr, 2, valp, size);
+
+ return retval;
+}
+
+/**
+ * Write a single register through spi.
+ * 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(struct rmi_phys_driver *pd, unsigned short address, char data)
+{
+ struct instance_data *id = container_of(pd, struct instance_data, rpd);
+ unsigned char txbuf[4];
+ int retval;
+
+ txbuf[2] = data;
+ txbuf[1] = address;
+ txbuf[0] = address>>8;
+
+ retval = spi_xfer(id->spidev, txbuf, 3, NULL, 0);
+ return retval ? 0 : 1;
+}
+
+/**
+ * Write multiple registers.
+ * \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(struct rmi_phys_driver *pd, unsigned short address,
+ char *valp, int size)
+{
+ struct instance_data *id = container_of(pd, struct instance_data, rpd);
+ unsigned char txbuf[32];
+ 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->spidev, txbuf, size+2, NULL, 0);
+
+ return retval ? 0 : 1;
+}
+
+/**
+ * This is the Interrupt Service Routine. It just notifies the application
+ * layer that attention is required.
+ */
+static irqreturn_t spi_attn_isr(int irq, void *info)
+{
+ struct instance_data *id = info;
+ disable_irq(id->irq);
+ if (id->rpd.attention)
+ id->rpd.attention(&id->rpd, id->instance_no);
+ return IRQ_HANDLED;
+}
+
+
+static int rmi_spi_probe(struct spi_device *spi)
+{
+ struct instance_data *id;
+ int retval;
+ int i;
+ bool found;
+ struct rmi_spi_data *rmispidata;
+ struct rmi_spi_platformdata *platformdata;
+
+ printk(KERN_INFO "Probing RMI4 SPI device\n");
+
+ found = false;
+
+ spi->bits_per_word = 8;
+
+ spi->mode = SPI_MODE_3;
+
+ buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
+ if (!buf) {
+ printk(KERN_ERR "%s: Out of memory - can't allocate memory for spi buffer\n", __func__);
+ return -ENOMEM;
+ }
+
+ retval = spi_setup(spi);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: spi_setup failed\n", __func__);
+ return retval;
+ }
+
+ id = kzalloc(sizeof(*id), GFP_KERNEL);
+ if (!id) {
+ printk(KERN_ERR "%s: Out of memory - can't allocate memory for instance data\n", __func__);
+ return -ENOMEM;
+ }
+
+ id->spidev = spi;
+ id->rpd.name = DRIVER_NAME;
+ id->rpd.write = rmi_spi_write;
+ id->rpd.read = rmi_spi_read;
+ id->rpd.write_multiple = rmi_spi_write_multiple;
+ id->rpd.read_multiple = rmi_spi_read_multiple;
+ id->rpd.module = THIS_MODULE;
+ id->rpd.polling_required = true; /* default to polling if irq not used */
+
+ /* Loop through the client data and locate the one that was found. */
+
+ rmispidata = spi->dev.platform_data;
+
+ /* Loop through the platform data and locate the one that matches the clients address */
+ for (i = 0; i < rmispidata->num_clients; i++) {
+ platformdata = &(rmispidata->platformdata[i]);
+ if (platformdata->chip == RMI_SUPPORT) {
+ id->instance_no = i;
+ found = true;
+
+ /* set the device name using the instance_no appended to DEVICE_NAME to make a unique name */
+ dev_set_name(&spi->dev, "rmi4-spi%d", id->instance_no);
+ /*
+ * Determine if we need to poll (inefficient) or use interrupts.
+ */
+ if (platformdata->irq) {
+ int irqtype;
+
+ id->irq = platformdata->irq;
+ switch (platformdata->irq_type) {
+ case IORESOURCE_IRQ_HIGHEDGE:
+ irqtype = IRQF_TRIGGER_RISING;
+ break;
+ case IORESOURCE_IRQ_LOWEDGE:
+ irqtype = IRQF_TRIGGER_FALLING;
+ break;
+ case IORESOURCE_IRQ_HIGHLEVEL:
+ irqtype = IRQF_TRIGGER_HIGH;
+ break;
+ case IORESOURCE_IRQ_LOWLEVEL:
+ irqtype = IRQF_TRIGGER_LOW;
+ break;
+ default:
+ dev_warn(&spi->dev, "%s: Invalid IRQ flags in platform data\n", __func__);
+ kfree(id);
+ return -ENXIO;
+ }
+
+ retval = request_irq(id->irq, spi_attn_isr, irqtype, "rmi_spi", id);
+ if (retval) {
+ dev_info(&spi->dev, "%s: Unable to get attn irq %d. Reverting to polling.\n", __func__, id->irq);
+ id->rpd.polling_required = true;
+ } else {
+ dev_dbg(&spi->dev, "%s: got irq\n", __func__);
+ id->rpd.polling_required = false;
+ id->rpd.irq = id->irq;
+ }
+ } else {
+ id->rpd.polling_required = true;
+ dev_info(&spi->dev, "%s: No IRQ info given. Polling required.\n", __func__);
+ }
+ }
+ }
+
+ /* if went through all the platform data list and didn't find a match then notify that we are defaulting to polling */
+ if (!found) {
+ dev_info(&spi->dev, "%s: No platform data match found.Defaulting to use polling.\n", __func__);
+ }
+
+ /* Store instance data for later access. */
+ if (id) {
+ spi_set_drvdata(spi, id);
+ }
+
+ /* Register the sensor driver - which will trigger a scan of the PDT. */
+ retval = rmi_register_sensors(&id->rpd);
+ if (retval) {
+ printk(KERN_ERR "rmi_register_phys_driver failed.\n");
+ if (id->irq)
+ free_irq(id->irq, id);
+ kfree(id);
+ return retval;
+ }
+
+ printk(KERN_INFO "%s: Successfully Registered %s\n", __func__, id->rpd.name);
+
+ return 0;
+}
+
+static int rmi_spi_suspend(struct spi_device *spi, pm_message_t message)
+{
+ return 0;
+}
+
+static int rmi_spi_resume(struct spi_device *spi)
+{
+ return 0;
+}
+
+static int __devexit rmi_spi_remove(struct spi_device *spi)
+{
+ struct instance_data *id = spi_get_drvdata(spi);
+
+ rmi_spi_suspend(spi, PMSG_SUSPEND);
+
+ rmi_unregister_sensors(&id->rpd);
+
+ if (id) {
+ if (id->irq)
+ free_irq(id->irq, id);
+ kfree(id);
+ }
+
+ return 0;
+}
+
+static struct spi_driver rmi_spi_driver = {
+ .driver = {
+ .name = "rmi_spi",
+ .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,
+};
+
+/**
+ * The Platform Driver probe function. We just tell the spi subsystem about
+ * ourselves in this call.
+ */
+static int
+rmi_spi_plat_probe(struct platform_device *dev)
+{
+ struct rmi_spi_data *mid = dev->dev.platform_data;
+
+ if (!mid) {
+ printk(KERN_ERR "A platform device must contain rmi_spi_data\n");
+ return -ENXIO;
+ }
+
+ num_clients = mid->num_clients;
+ platformdata = mid->platformdata;
+
+ return spi_register_driver(&rmi_spi_driver);
+}
+
+/**
+ * Tell the spi subsystem that we're done.
+ * \param[in] dev
+ * \return Always returns 0.
+ */
+static int
+rmi_spi_plat_remove(struct platform_device *dev)
+{
+ spi_unregister_driver(&rmi_spi_driver);
+ return 0;
+}
+
+/**
+ * Structure used to tell the Platform Driver subsystem about us.
+ */
+static struct platform_driver rmi_spi_platform_driver = {
+ .driver = {
+ .name = "rmi_spi_plat",
+ },
+ .probe = rmi_spi_plat_probe,
+ .remove = rmi_spi_plat_remove,
+};
+
+static int __init rmi_spi_init(void)
+{
+ return platform_driver_register(&rmi_spi_platform_driver);
+}
+module_init(rmi_spi_init);
+
+static void __exit rmi_spi_exit(void)
+{
+ if (buf) {
+ kfree(buf);
+ buf = NULL;
+ }
+ platform_driver_unregister(&rmi_spi_platform_driver);
+}
+module_exit(rmi_spi_exit);
+
+/** Standard driver module information - the author of the module.
+ */
+MODULE_AUTHOR("Synaptics, Inc.");
+/** Standard driver module information - a summary description of this module.
+ */
+MODULE_DESCRIPTION("RMI4 Driver SPI Physical Layer");
+/** Standard driver module information - the license under which this module
+ * is included in the kernel.
+ */
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/rmi_spi.h b/drivers/input/touchscreen/rmi_spi.h
new file mode 100755
index 0000000..169645e
--- /dev/null
+++ b/drivers/input/touchscreen/rmi_spi.h
@@ -0,0 +1,53 @@
+/**
+ *
+ * Register Mapped Interface SPI Physical Layer Driver Header File.
+ * Copyright (C) 2008-2020, 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 RMI_CHIP_VER_3 0
+#define RMI_CHIP_VER_4 1
+
+#define RMI_SUPPORT (RMI_CHIP_VER_3|RMI_CHIP_VER_4)
+
+/** Platform-specific configuration data.
+ * This structure is used by the platform-specific driver to designate
+ * specific information about the hardware. A platform client may supply
+ * an array of these to the rmi_phys_spi driver.
+ */
+struct rmi_spi_platformdata {
+ /* struct spi_device spi_dev; */
+ int chip;
+
+ /** The number of the irq. Set to zero if polling is required. */
+ int irq;
+
+ /** The type of the irq (e.g., IRQF_TRIGGER_FALLING). Only valid if
+ * irq != 0 */
+ int irq_type;
+};
+
+/** Descriptor structure.
+ * Describes the number of spi devices on the bus that speak RMI.
+ */
+struct rmi_spi_data {
+ int num_clients;
+ struct rmi_spi_platformdata *platformdata;
+};
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-01-13 14:51 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-13 2:40 [PATCH 0/1] input synaptics-rmi4: Synaptics Touchscreen Driver Christopher Heiny
2011-01-13 2:40 ` [PATCH 1/1] " Christopher Heiny
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).