input: atmel_mxt_ts: Fix to reject coordinates outside active touch area

Firmware reports minimum/maximum coordinates when touches are
from outside of active area. Generate a release event in this
case to handle touches that are going to inactive area. Add
pdata entries for minimum values and check before reporting
the coordinates to userspace.

CRs-fixed: 326858
Change-Id: I385fb80eb670e539b45d232c04969c4502cdf65a
Signed-off-by: Mohan Pallaka <mpallaka@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d0045e2..b062dde 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -930,8 +930,14 @@
 static struct mxt_platform_data mxt_platform_data = {
 	.config_array		= mxt_config_array,
 	.config_array_size	= ARRAY_SIZE(mxt_config_array),
-	.x_size			= 1365,
-	.y_size			= 767,
+	.panel_minx		= 0,
+	.panel_maxx		= 1365,
+	.panel_miny		= 0,
+	.panel_maxy		= 767,
+	.disp_minx		= 0,
+	.disp_maxx		= 1365,
+	.disp_miny		= 0,
+	.disp_maxy		= 767,
 	.irqflags		= IRQF_TRIGGER_FALLING,
 	.i2c_pull_up		= true,
 	.reset_gpio		= MXT_TS_RESET_GPIO,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 51c8af6..59651a7 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1522,10 +1522,14 @@
 static struct mxt_platform_data mxt_platform_data_8930 = {
 	.config_array		= mxt_config_array,
 	.config_array_size	= ARRAY_SIZE(mxt_config_array),
-	.x_size			= 540,
-	.y_size			= 960,
-	.touch_x_size		= 566,
-	.touch_y_size		= 1067,
+	.panel_minx		= 0,
+	.panel_maxx		= 566,
+	.panel_miny		= 0,
+	.panel_maxy		= 1067,
+	.disp_minx		= 0,
+	.disp_maxx		= 540,
+	.disp_miny		= 0,
+	.disp_maxy		= 960,
 	.irqflags		= IRQF_TRIGGER_FALLING,
 #ifdef MSM8930_PHASE_2
 	.digital_pwr_regulator	= true,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 384da36..e8df203 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1948,8 +1948,14 @@
 static struct mxt_platform_data mxt_platform_data_2d = {
 	.config_array		= mxt_config_array_2d,
 	.config_array_size	= ARRAY_SIZE(mxt_config_array_2d),
-	.x_size			= 1365,
-	.y_size			= 767,
+	.panel_minx		= 0,
+	.panel_maxx		= 1365,
+	.panel_miny		= 0,
+	.panel_maxy		= 767,
+	.disp_minx		= 0,
+	.disp_maxx		= 1365,
+	.disp_miny		= 0,
+	.disp_maxy		= 767,
 	.irqflags		= IRQF_TRIGGER_FALLING,
 	.i2c_pull_up		= true,
 	.reset_gpio		= MXT_TS_RESET_GPIO,
@@ -1970,8 +1976,14 @@
 static struct mxt_platform_data mxt_platform_data_3d = {
 	.config_array		= mxt_config_array_3d,
 	.config_array_size	= ARRAY_SIZE(mxt_config_array_3d),
-	.x_size			= 1919,
-	.y_size			= 1199,
+	.panel_minx		= 0,
+	.panel_maxx		= 1919,
+	.panel_miny		= 0,
+	.panel_maxy		= 1199,
+	.disp_minx		= 0,
+	.disp_maxx		= 1919,
+	.disp_miny		= 0,
+	.disp_maxy		= 1199,
 	.irqflags		= IRQF_TRIGGER_FALLING,
 	.i2c_pull_up		= true,
 	.reset_gpio		= MXT_TS_RESET_GPIO,
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index ad4114d..218374d 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -1134,8 +1134,14 @@
 static struct mxt_platform_data mxt_platform_data = {
 	.config_array		= mxt_config_array,
 	.config_array_size	= ARRAY_SIZE(mxt_config_array),
-	.x_size                 = 479,
-	.y_size                 = 799,
+	.panel_minx		= 0,
+	.panel_maxx		= 479,
+	.panel_miny		= 0,
+	.panel_maxy		= 799,
+	.disp_minx		= 0,
+	.disp_maxx		= 479,
+	.disp_miny		= 0,
+	.disp_maxy		= 799,
 	.irqflags               = IRQF_TRIGGER_FALLING,
 	.i2c_pull_up            = true,
 	.reset_gpio		= MXT_TS_RESET_GPIO,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f5bfc7b..39c158d 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -324,8 +324,6 @@
 	struct mxt_info info;
 	struct mxt_finger finger[MXT_MAX_FINGER];
 	unsigned int irq;
-	unsigned int touch_x_size;
-	unsigned int touch_y_size;
 	struct regulator *vcc_ana;
 	struct regulator *vcc_dig;
 	struct regulator *vcc_i2c;
@@ -751,6 +749,17 @@
 			continue;
 
 		input_mt_slot(input_dev, id);
+		/* Firmware reports min/max values when the touch is
+		 * outside screen area. Send a release event in
+		 * such cases to avoid unwanted touches.
+		 */
+		if (finger[id].x <= data->pdata->panel_minx ||
+				finger[id].x >= data->pdata->panel_maxx ||
+				finger[id].y <= data->pdata->panel_miny ||
+				finger[id].y >= data->pdata->panel_maxy) {
+			finger[id].status = MXT_RELEASE;
+		}
+
 		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
 				finger[id].status != MXT_RELEASE);
 
@@ -771,6 +780,13 @@
 
 	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
 
+	if (finger[single_id].x <= data->pdata->panel_minx ||
+		finger[single_id].x >= data->pdata->panel_maxx ||
+		finger[single_id].y <= data->pdata->panel_miny ||
+		finger[single_id].y >= data->pdata->panel_maxy) {
+		status = MXT_RELEASE;
+	}
+
 	if (status != MXT_RELEASE) {
 		input_report_abs(input_dev, ABS_X, finger[single_id].x);
 		input_report_abs(input_dev, ABS_Y, finger[single_id].y);
@@ -809,9 +825,9 @@
 
 	x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
 	y = (message->message[2] << 4) | ((message->message[3] & 0xf));
-	if (data->touch_x_size < 1024)
+	if (data->pdata->panel_maxx < 1024)
 		x = x >> 2;
-	if (data->touch_y_size < 1024)
+	if (data->pdata->panel_maxy < 1024)
 		y = y >> 2;
 
 	area = message->message[4];
@@ -2123,9 +2139,9 @@
 
 	/* For single touch */
 	input_set_abs_params(input_dev, ABS_X,
-			     0, data->pdata->x_size, 0, 0);
+			pdata->disp_minx, pdata->disp_maxx, 0, 0);
 	input_set_abs_params(input_dev, ABS_Y,
-			     0, data->pdata->y_size, 0, 0);
+			pdata->disp_miny, pdata->disp_maxy, 0, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE,
 			     0, 255, 0, 0);
 
@@ -2134,22 +2150,12 @@
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, MXT_MAX_AREA, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     0, data->pdata->x_size, 0, 0);
+			pdata->disp_minx, pdata->disp_maxx, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     0, data->pdata->y_size, 0, 0);
+			pdata->disp_miny, pdata->disp_maxy, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_PRESSURE,
 			     0, 255, 0, 0);
 
-	if (pdata->touch_x_size)
-		data->touch_x_size = pdata->touch_x_size;
-	else
-		data->touch_x_size = pdata->x_size;
-
-	if (pdata->touch_y_size)
-		data->touch_y_size = pdata->touch_y_size;
-	else
-		data->touch_y_size = pdata->y_size;
-
 	/* set key array supported keys */
 	if (pdata->key_codes) {
 		for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index a2391e3..b54fcb4 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -53,10 +53,18 @@
 	const struct mxt_config_info *config_array;
 	size_t config_array_size;
 
-	unsigned int x_size;
-	unsigned int y_size;
-	unsigned int touch_x_size;
-	unsigned int touch_y_size;
+	/* touch panel's minimum and maximum coordinates */
+	u32 panel_minx;
+	u32 panel_maxx;
+	u32 panel_miny;
+	u32 panel_maxy;
+
+	/* display's minimum and maximum coordinates */
+	u32 disp_minx;
+	u32 disp_maxx;
+	u32 disp_miny;
+	u32 disp_maxy;
+
 	unsigned long irqflags;
 	bool	i2c_pull_up;
 	bool	digital_pwr_regulator;