text: /**
   *
   * 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;
  }
  