/**
 *
 * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
 * Copyright (c) 2007 - 2011, Synaptics Incorporated
 *
 */
/*
 * This file is licensed under the GPL2 license.
 *
 *#############################################################################
 * GPL
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 *#############################################################################
 */

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/input/rmi_platformdata.h>
#include <linux/module.h>

#include "rmi.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;

struct f11_instance_data {
	struct rmi_F11_device_query *deviceInfo;
	struct rmi_F11_sensor_query *sensorInfo;
	struct rmi_F11_control *controlRegisters;
	int button_height;
	unsigned char fingerDataBufferSize;
	unsigned char absDataOffset;
	unsigned char absDataSize;
	unsigned char relDataOffset;
	unsigned char gestureDataOffset;
	unsigned char *fingerDataBuffer;
		/* Last X & Y seen, needed at finger lift.  Was down indicates at least one finger was here. */
		/* TODO: Eventually we'll need to track this info on a per finger basis. */
	bool wasdown;
	unsigned int oldX;
	unsigned int oldY;
		/* Transformations to be applied to coordinates before reporting. */
	bool flipX;
	bool flipY;
	int offsetX;
	int offsetY;
	int clipXLow;
	int clipXHigh;
	int clipYLow;
	int clipYHigh;
	bool swap_axes;
	bool relReport;
};

enum f11_finger_state {
	F11_NO_FINGER = 0,
	F11_PRESENT = 1,
	F11_INACCURATE = 2,
	F11_RESERVED = 3
};

static ssize_t rmi_fn_11_flip_show(struct device *dev,
				struct device_attribute *attr, char *buf);

static ssize_t rmi_fn_11_flip_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count);

DEVICE_ATTR(flip, 0664, rmi_fn_11_flip_show, rmi_fn_11_flip_store);     /* RW attr */

static ssize_t rmi_fn_11_clip_show(struct device *dev,
				struct device_attribute *attr, char *buf);

static ssize_t rmi_fn_11_clip_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count);

DEVICE_ATTR(clip, 0664, rmi_fn_11_clip_show, rmi_fn_11_clip_store);     /* RW attr */

static ssize_t rmi_fn_11_offset_show(struct device *dev,
				struct device_attribute *attr, char *buf);

static ssize_t rmi_fn_11_offset_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count);

DEVICE_ATTR(offset, 0664, rmi_fn_11_offset_show, rmi_fn_11_offset_store);     /* RW attr */

static ssize_t rmi_fn_11_swap_show(struct device *dev,
				struct device_attribute *attr, char *buf);

static ssize_t rmi_fn_11_swap_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count);

DEVICE_ATTR(swap, 0664, rmi_fn_11_swap_show, rmi_fn_11_swap_store);     /* RW attr */

static ssize_t rmi_fn_11_relreport_show(struct device *dev,
				struct device_attribute *attr, char *buf);

static ssize_t rmi_fn_11_relreport_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count);

DEVICE_ATTR(relreport, 0664, rmi_fn_11_relreport_show, rmi_fn_11_relreport_store);     /* RW attr */

static ssize_t rmi_fn_11_maxPos_show(struct device *dev,
				struct device_attribute *attr, char *buf);

static ssize_t rmi_fn_11_maxPos_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count);

DEVICE_ATTR(maxPos, 0664, rmi_fn_11_maxPos_show, rmi_fn_11_maxPos_store);     /* RW attr */


static void FN_11_relreport(struct rmi_function_info *rmifninfo);

/*
 * 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_function_info *rmifninfo,
	unsigned int assertedIRQs)
{
	/* number of touch points - fingers down in this case */
	int fingerDownCount;
	int finger;
	struct rmi_function_device *function_device;
	struct f11_instance_data *instanceData;

	instanceData = (struct f11_instance_data *) rmifninfo->fndata;

	fingerDownCount = 0;
	function_device = rmifninfo->function_device;

	/* get 2D sensor finger data */

	if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr,
		instanceData->fingerDataBuffer, instanceData->fingerDataBufferSize)) {
		printk(KERN_ERR "%s: Failed to read finger data registers.\n", __func__);
		return;
	}

	/* First we need to count the fingers and generate some events related to that. */
	for (finger = 0; finger < instanceData->sensorInfo->numberOfFingers; 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 = (instanceData->fingerDataBuffer[reg] >> fingerShift) & 3;

		if (fingerStatus == F11_PRESENT || fingerStatus == F11_INACCURATE) {
			fingerDownCount++;
			instanceData->wasdown = true;
		}
	}
	input_report_key(function_device->input,
			BTN_TOUCH, !!fingerDownCount);

	for (finger = 0; finger < instanceData->sensorInfo->numberOfFingers; finger++) {
		int reg;
		int fingerShift;
		int fingerStatus;
		int X = 0, Y = 0, Z = 0, Wy = 0, Wx = 0;

		/* determine which data byte the finger status is in */
		reg = finger/4;
		/* bit shift to get finger's status */
		fingerShift = (finger % 4) * 2;
		fingerStatus = (instanceData->fingerDataBuffer[reg] >> fingerShift) & 3;

		/* if finger status indicates a finger is present then
		read the finger data and report it */
		if (fingerStatus == F11_PRESENT || fingerStatus == F11_INACCURATE) {

			if (instanceData->sensorInfo->hasAbs) {
				int maxX = instanceData->controlRegisters->sensorMaxXPos;
				int maxY = instanceData->controlRegisters->sensorMaxYPos;
				reg = instanceData->absDataOffset + (finger * instanceData->absDataSize);
				X = (instanceData->fingerDataBuffer[reg] << 4) & 0x0ff0;
				X |= (instanceData->fingerDataBuffer[reg+2] & 0x0f);
				Y = (instanceData->fingerDataBuffer[reg+1] << 4) & 0x0ff0;
				Y |= ((instanceData->fingerDataBuffer[reg+2] & 0xf0) >> 4) & 0x0f;
				/* First thing to do is swap axes if needed.
				 */
				if (instanceData->swap_axes) {
					int temp = X;
					X = Y;
					Y = temp;
					maxX = instanceData->controlRegisters->sensorMaxYPos;
					maxY = instanceData->controlRegisters->sensorMaxXPos;
				}
				if (instanceData->flipX)
					X = max(maxX-X, 0);
				X = X - instanceData->offsetX;
				X = min(max(X, instanceData->clipXLow), instanceData->clipXHigh);
				if (instanceData->flipY)
					Y = max(maxY-Y, 0);
				Y = Y - instanceData->offsetY;
				Y = min(max(Y, instanceData->clipYLow), instanceData->clipYHigh);

				/* upper 4 bits of W are Wy,
				lower 4 of W are Wx */
				Wy =  (instanceData->fingerDataBuffer[reg+3] >> 4) & 0x0f;
				Wx = instanceData->fingerDataBuffer[reg+3] & 0x0f;
				if (instanceData->swap_axes) {
					int temp = Wx;
					Wx = Wy;
					Wy = temp;
				}

				Z = instanceData->fingerDataBuffer[reg+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) {
					instanceData->oldX = X;
					instanceData->oldY = Y;
					input_report_abs(function_device->input, ABS_X, X);
					input_report_abs(function_device->input, ABS_Y, Y);
					input_report_abs(function_device->input, ABS_PRESSURE, Z);
					input_report_abs(function_device->input, ABS_TOOL_WIDTH,
							max(Wx, Wy));

				} else {
					/* TODO generate non MT events for multifinger situation. */
				}
#ifdef CONFIG_SYNA_MULTI_TOUCH
				/* Report Multi-Touch events for each finger */
				input_report_abs(function_device->input,
							ABS_MT_PRESSURE, Z);
				input_report_abs(function_device->input, ABS_MT_POSITION_X, X);
				input_report_abs(function_device->input, ABS_MT_POSITION_Y, Y);

				/* TODO: Tracking ID needs to be reported but not used yet. */
				/* Could be formed by keeping an id per position and assiging */
				/* a new id when fingerStatus changes for that position.*/
				input_report_abs(function_device->input, ABS_MT_TRACKING_ID,
						finger);
				/* MT sync between fingers */
				input_mt_sync(function_device->input);
#endif
			}
		}
	}

	/* if we had a finger down before and now we don't have any send a button up. */
	if ((fingerDownCount == 0) && instanceData->wasdown) {
		instanceData->wasdown = false;

#ifdef CONFIG_SYNA_MULTI_TOUCH
		input_report_abs(function_device->input, ABS_MT_PRESSURE, 0);
		input_report_key(function_device->input, BTN_TOUCH, 0);
		input_mt_sync(function_device->input);
#endif
	}

	FN_11_relreport(rmifninfo);
	input_sync(function_device->input); /* sync after groups of events */

}
EXPORT_SYMBOL(FN_11_inthandler);

/* This function reads in relative data for first finger and send to input system */
static void FN_11_relreport(struct rmi_function_info *rmifninfo)
{
	struct f11_instance_data *instanceData;
	struct rmi_function_device *function_device;
	signed char X, Y;
	unsigned short fn11DataBaseAddr;

	instanceData = (struct f11_instance_data *) rmifninfo->fndata;

	if (instanceData->sensorInfo->hasRel && instanceData->relReport) {
		int reg = instanceData->relDataOffset;

		function_device = rmifninfo->function_device;

		fn11DataBaseAddr = rmifninfo->funcDescriptor.dataBaseAddr;
		/* Read and report Rel data for primary finger one register for X and one for Y*/
		X = instanceData->fingerDataBuffer[reg];
		Y = instanceData->fingerDataBuffer[reg+1];
		if (instanceData->swap_axes) {
			signed char temp = X;
			X = Y;
			Y = temp;
		}
		if (instanceData->flipX) {
			X = -X;
		}
		if (instanceData->flipY) {
			Y = -Y;
		}
		X = (signed char) min(127, max(-128, (int) X));
		Y = (signed char) min(127, max(-128, (int) Y));

		input_report_rel(function_device->input, REL_X, X);
		input_report_rel(function_device->input, REL_Y, Y);
	}
}

int FN_11_config(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(rmifninfo->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(rmifninfo->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);

/* This operation is done in a number of places, so we have a handy routine
 * for it.
 */
static void f11_set_abs_params(struct rmi_function_device *function_device)
{
	struct f11_instance_data *instance_data = function_device->rfi->fndata;
	/* Use the max X and max Y read from the device, or the clip values,
	 * whichever is stricter.
	 */
	int xMin = instance_data->clipXLow;
	int xMax = min((int) instance_data->controlRegisters->sensorMaxXPos, instance_data->clipXHigh);
	int yMin = instance_data->clipYLow;
	int yMax = min((int) instance_data->controlRegisters->sensorMaxYPos, instance_data->clipYHigh) - instance_data->button_height;
	if (instance_data->swap_axes) {
		int temp = xMin;
		xMin = yMin;
		yMin = temp;
		temp = xMax;
		xMax = yMax;
		yMax = temp;
	}
	printk(KERN_DEBUG "%s: Set ranges X=[%d..%d] Y=[%d..%d].", __func__, xMin, xMax, yMin, yMax);
	input_set_abs_params(function_device->input, ABS_X, xMin, xMax,
		0, 0);
	input_set_abs_params(function_device->input, ABS_Y, yMin, yMax,
		0, 0);
	input_set_abs_params(function_device->input, ABS_PRESSURE, 0, 255, 0, 0);
	input_set_abs_params(function_device->input, ABS_TOOL_WIDTH, 0, 15, 0, 0);

#ifdef CONFIG_SYNA_MULTI_TOUCH
	input_set_abs_params(function_device->input, ABS_MT_PRESSURE,
							0, 15, 0, 0);
	input_set_abs_params(function_device->input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
	input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID,
							0, 10, 0, 0);
	input_set_abs_params(function_device->input, ABS_MT_POSITION_X, xMin, xMax,
		0, 0);
	input_set_abs_params(function_device->input, ABS_MT_POSITION_Y, yMin, yMax,
		0, 0);
#endif
}

/* Initialize any function $11 specific params and settings - input
 * settings, device settings, etc.
 */
int FN_11_init(struct rmi_function_device *function_device)
{
	struct f11_instance_data *instanceData = function_device->rfi->fndata;
	int retval = 0;
	struct rmi_f11_functiondata *functiondata = rmi_sensor_get_functiondata(function_device->sensor, RMI_F11_INDEX);
	printk(KERN_DEBUG "%s: RMI4 F11 init", __func__);

	/* TODO: Initialize these through some normal kernel mechanism.
	 */
	instanceData->flipX = false;
	instanceData->flipY = false;
	instanceData->swap_axes = false;
	instanceData->relReport = true;
	instanceData->offsetX = instanceData->offsetY = 0;
	instanceData->clipXLow = instanceData->clipYLow = 0;
	/* TODO: 65536 should actually be the largest valid RMI4 position coordinate */
	instanceData->clipXHigh = instanceData->clipYHigh = 65536;

	/* Load any overrides that were specified via platform data.
	 */
	if (functiondata) {
		printk(KERN_DEBUG "%s: found F11 per function platformdata.", __func__);
		instanceData->flipX = functiondata->flipX;
		instanceData->flipY = functiondata->flipY;
		instanceData->button_height = functiondata->button_height;
		instanceData->swap_axes = functiondata->swap_axes;
		if (functiondata->offset) {
			instanceData->offsetX = functiondata->offset->x;
			instanceData->offsetY = functiondata->offset->y;
		}
		if (functiondata->clipX) {
			if (functiondata->clipX->min >= functiondata->clipX->max) {
				printk(KERN_WARNING "%s: Clip X min (%d) >= X clip max (%d) - ignored.",
					   __func__, functiondata->clipX->min, functiondata->clipX->max);
			} else {
				instanceData->clipXLow = functiondata->clipX->min;
				instanceData->clipXHigh = functiondata->clipX->max;
			}
		}
		if (functiondata->clipY) {
			if (functiondata->clipY->min >= functiondata->clipY->max) {
				printk(KERN_WARNING "%s: Clip Y min (%d) >= Y clip max (%d) - ignored.",
					   __func__, functiondata->clipY->min, functiondata->clipY->max);
			} else {
				instanceData->clipYLow = functiondata->clipY->min;
				instanceData->clipYHigh = functiondata->clipY->max;
			}
		}
	}

	/* need to init the input abs params for the 2D */
	set_bit(EV_ABS, function_device->input->evbit);
	set_bit(EV_SYN, function_device->input->evbit);
	set_bit(EV_KEY, function_device->input->evbit);
	set_bit(BTN_TOUCH, function_device->input->keybit);
	set_bit(KEY_OK, function_device->input->keybit);

	f11_set_abs_params(function_device);

	printk(KERN_DEBUG "%s: Creating sysfs files.", __func__);
	retval = device_create_file(&function_device->dev, &dev_attr_flip);
	if (retval) {
		printk(KERN_ERR "%s: Failed to create flip.", __func__);
		return retval;
	}
	retval = device_create_file(&function_device->dev, &dev_attr_clip);
	if (retval) {
		printk(KERN_ERR "%s: Failed to create clip.", __func__);
		return retval;
	}
	retval = device_create_file(&function_device->dev, &dev_attr_offset);
	if (retval) {
		printk(KERN_ERR "%s: Failed to create offset.", __func__);
		return retval;
	}
	retval = device_create_file(&function_device->dev, &dev_attr_swap);
	if (retval) {
		printk(KERN_ERR "%s: Failed to create swap.", __func__);
		return retval;
	}
	retval = device_create_file(&function_device->dev, &dev_attr_relreport);
	if (retval) {
		printk(KERN_ERR "%s: Failed to create relreport.", __func__);
		return retval;
	}
	retval = device_create_file(&function_device->dev, &dev_attr_maxPos);
	if (retval) {
		printk(KERN_ERR "%s: Failed to create maxPos.", __func__);
		return retval;
	}

	return 0;
}
EXPORT_SYMBOL(FN_11_init);

int FN_11_detect(struct rmi_function_info *rmifninfo,
	struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
{
	unsigned char fn11Queries[12];   /* TODO: Compute size correctly. */
	unsigned char fn11Control[12];   /* TODO: Compute size correctly. */
	int i;
	unsigned short fn11InterruptOffset;
	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;
	struct f11_instance_data *instanceData;

	printk(KERN_DEBUG "%s: RMI4 F11 detect\n", __func__);

	instanceData = kzalloc(sizeof(struct f11_instance_data), GFP_KERNEL);
	if (!instanceData) {
		printk(KERN_ERR "%s: Error allocating F11 instance data.\n", __func__);
		return -ENOMEM;
	}
	instanceData->deviceInfo = kzalloc(sizeof(struct rmi_F11_device_query), GFP_KERNEL);
	if (!instanceData->deviceInfo) {
		printk(KERN_ERR "%s: Error allocating F11 device query.\n", __func__);
		return -ENOMEM;
	}
	instanceData->sensorInfo = kzalloc(sizeof(struct rmi_F11_sensor_query), GFP_KERNEL);
	if (!instanceData->sensorInfo) {
		printk(KERN_ERR "%s: Error allocating F11 sensor query.\n", __func__);
		return -ENOMEM;
	}
	rmifninfo->fndata = instanceData;

	/* 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(rmifninfo->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;
	}

	/* Extract device data. */
	instanceData->deviceInfo->hasQuery9 = (fn11Queries[0] & 0x04) != 0;
	instanceData->deviceInfo->numberOfSensors = (fn11Queries[0] & 0x07) + 1;
	printk(KERN_DEBUG "%s: F11 device - %d sensors.  Query 9? %d.", __func__, instanceData->deviceInfo->numberOfSensors, instanceData->deviceInfo->hasQuery9);

	/* Extract sensor data. */
	/* 2D data sources have only 3 bits for the number of fingers
	supported - so the encoding is a bit wierd. */
	instanceData->sensorInfo->numberOfFingers = 2; /* default number of fingers supported */
	if ((fn11Queries[1] & 0x7) <= 4)
		/* add 1 since zero based */
		instanceData->sensorInfo->numberOfFingers = (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)
			instanceData->sensorInfo->numberOfFingers = 10;
	}
	instanceData->sensorInfo->configurable = (fn11Queries[1] & 0x80) != 0;
	instanceData->sensorInfo->hasSensitivityAdjust = (fn11Queries[1] & 0x40) != 0;
	instanceData->sensorInfo->hasGestures = (fn11Queries[1] & 0x20) != 0;
	instanceData->sensorInfo->hasAbs = (fn11Queries[1] & 0x10) != 0;
	instanceData->sensorInfo->hasRel = (fn11Queries[1] & 0x08) != 0;
	instanceData->sensorInfo->absDataSize = fn11Queries[5] & 0x03;
	printk(KERN_DEBUG "%s: Number of fingers: %d.", __func__, instanceData->sensorInfo->numberOfFingers);

	/* Need to get interrupt info to be used later when handling
	interrupts. */
	rmifninfo->interruptRegister = interruptCount/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;

	/* Figure out just how much data we'll need to read. */
	instanceData->fingerDataBufferSize = (instanceData->sensorInfo->numberOfFingers + 3) / 4;
	/* One each for X and Y, one for LSB for X & Y, one for W, one for Z */
	fn11AbsDataBlockSize = 5;
	if (instanceData->sensorInfo->absDataSize != 0)
		printk(KERN_WARNING "%s: Unrecognized abs data size %d ignored.", __func__, instanceData->sensorInfo->absDataSize);
	if (instanceData->sensorInfo->hasAbs) {
		instanceData->absDataSize = fn11AbsDataBlockSize;
		instanceData->absDataOffset = instanceData->fingerDataBufferSize;
		instanceData->fingerDataBufferSize += instanceData->sensorInfo->numberOfFingers * fn11AbsDataBlockSize;
	}
	if (instanceData->sensorInfo->hasRel) {
		instanceData->relDataOffset = ((instanceData->sensorInfo->numberOfFingers + 3) / 4) +
			/* absolute data, per finger times number of fingers */
			(fn11AbsDataBlockSize * instanceData->sensorInfo->numberOfFingers);
		instanceData->fingerDataBufferSize += instanceData->sensorInfo->numberOfFingers * 2;
	}
	if (instanceData->sensorInfo->hasGestures) {
		instanceData->gestureDataOffset = instanceData->fingerDataBufferSize;
		printk(KERN_WARNING "%s: WARNING Need to correctly compute gesture data location.", __func__);
	}

	/* 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 */
		((instanceData->sensorInfo->numberOfFingers + 3) / 4) +
		/* absolute data, per finger times number of fingers */
		(fn11AbsDataBlockSize * instanceData->sensorInfo->numberOfFingers) +
		/* 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);
	instanceData->fingerDataBuffer = kcalloc(instanceData->fingerDataBufferSize, sizeof(unsigned char), GFP_KERNEL);
	if (!instanceData->fingerDataBuffer) {
		printk(KERN_ERR "%s: Failed to allocate finger data buffer.", __func__);
		return -ENOMEM;
	}

	/* Grab a copy of the control registers. */
	instanceData->controlRegisters = kzalloc(sizeof(struct rmi_F11_control), GFP_KERNEL);
	if (!instanceData->controlRegisters) {
		printk(KERN_ERR "%s: Error allocating F11 control registers.\n", __func__);
		return -ENOMEM;
	}
	retval = rmi_read_multiple(rmifninfo->sensor, fndescr->controlBaseAddr,
		fn11Control, sizeof(fn11Control));
	if (retval) {
		printk(KERN_ERR "%s: Failed to read F11 control registers.", __func__);
		return retval;
	}
	instanceData->controlRegisters->sensorMaxXPos = (((int) fn11Control[7] & 0x0F) << 8) + fn11Control[6];
	instanceData->controlRegisters->sensorMaxYPos = (((int) fn11Control[9] & 0x0F) << 8) + fn11Control[8];
	printk(KERN_DEBUG "%s: Max X %d Max Y %d", __func__, instanceData->controlRegisters->sensorMaxXPos, instanceData->controlRegisters->sensorMaxYPos);
	return 0;
}
EXPORT_SYMBOL(FN_11_detect);

static ssize_t rmi_fn_11_maxPos_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;

	return sprintf(buf, "%u %u\n", instance_data->controlRegisters->sensorMaxXPos, instance_data->controlRegisters->sensorMaxYPos);
}

static ssize_t rmi_fn_11_maxPos_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	return -EPERM;
}

static ssize_t rmi_fn_11_flip_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;

	return sprintf(buf, "%u %u\n", instance_data->flipX, instance_data->flipY);
}

static ssize_t rmi_fn_11_flip_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
	unsigned int newX, newY;

	printk(KERN_DEBUG "%s: Flip set to %s", __func__, buf);

	if (sscanf(buf, "%u %u", &newX, &newY) != 2)
		return -EINVAL;
	if (newX < 0 || newX > 1 || newY < 0 || newY > 1)
		return -EINVAL;
	instance_data->flipX = newX;
	instance_data->flipY = newY;

	return count;
}

static ssize_t rmi_fn_11_swap_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;

	return sprintf(buf, "%u\n", instance_data->swap_axes);
}

static ssize_t rmi_fn_11_swap_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
	unsigned int newSwap;

	printk(KERN_DEBUG "%s: Swap set to %s", __func__, buf);

	if (sscanf(buf, "%u", &newSwap) != 1)
		return -EINVAL;
	if (newSwap < 0 || newSwap > 1)
		return -EINVAL;
	instance_data->swap_axes = newSwap;

	f11_set_abs_params(fn);

	return count;
}

static ssize_t rmi_fn_11_relreport_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;

	return sprintf(buf, "%u \n", instance_data->relReport);
}

static ssize_t rmi_fn_11_relreport_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
	unsigned int relRep;

	printk(KERN_DEBUG "%s: relReport set to %s", __func__, buf);
	if (sscanf(buf, "%u", &relRep) != 1)
		return -EINVAL;
	if (relRep < 0 || relRep > 1)
		return -EINVAL;
	instance_data->relReport = relRep;

	return count;
}

static ssize_t rmi_fn_11_offset_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;

	return sprintf(buf, "%d %d\n", instance_data->offsetX, instance_data->offsetY);
}

static ssize_t rmi_fn_11_offset_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
	int newX, newY;

	printk(KERN_DEBUG "%s: Offset set to %s", __func__, buf);

	if (sscanf(buf, "%d %d", &newX, &newY) != 2)
		return -EINVAL;
	instance_data->offsetX = newX;
	instance_data->offsetY = newY;

	return count;
}

static ssize_t rmi_fn_11_clip_show(struct device *dev,
				struct device_attribute *attr, char *buf)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;

	return sprintf(buf, "%u %u %u %u\n",
				   instance_data->clipXLow, instance_data->clipXHigh,
				   instance_data->clipYLow, instance_data->clipYHigh);
}

static ssize_t rmi_fn_11_clip_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	struct rmi_function_device *fn = dev_get_drvdata(dev);
	struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
	unsigned int newXLow, newXHigh, newYLow, newYHigh;

	printk(KERN_DEBUG "%s: Clip set to %s", __func__, buf);

	if (sscanf(buf, "%u %u %u %u", &newXLow, &newXHigh, &newYLow, &newYHigh) != 4)
		return -EINVAL;
	if (newXLow < 0 || newXLow >= newXHigh || newYLow < 0 || newYLow >= newYHigh)
		return -EINVAL;
	instance_data->clipXLow = newXLow;
	instance_data->clipXHigh = newXHigh;
	instance_data->clipYLow = newYLow;
	instance_data->clipYHigh = newYHigh;

	f11_set_abs_params(fn);

	return count;
}
