aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>2010-06-01 18:03:51 +0530
committerJohn Rigby <john.rigby@linaro.org>2010-09-02 22:45:32 -0600
commitce731e3682788935e9d9b9889f9a15b4ea7d1785 (patch)
treea0c03319b2ec90e77fa5b66beeefd96f6d6eaf69
parentf344d5b7119e8729bcab6f7aed8541276f82759e (diff)
downloadlinux-2.6.34-ux500-ce731e3682788935e9d9b9889f9a15b4ea7d1785.tar.gz
bu21013: Driver for new dual touch controllers support
Adding bu21013 dual touch controllers driver and support for it in mach-ux500. ST-Ericsson ID: WP 257134 Signed-off-by: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/413 Reviewed-by: Jonas ABERG <jonas.aberg@stericsson.com> Tested-by: Jonas ABERG <jonas.aberg@stericsson.com> Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> Change-Id: If084c45539cd18982ddf210cf2b80be2e8da4dd3 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2390
-rwxr-xr-x[-rw-r--r--]arch/arm/configs/mop500_USB_HOST_defconfig3
-rwxr-xr-xarch/arm/configs/mop500_defconfig9
-rwxr-xr-xarch/arm/configs/mop500_ed_defconfig9
-rwxr-xr-xarch/arm/configs/mop500_power_defconfig9
-rwxr-xr-xarch/arm/mach-ux500/board-mop500.c234
-rwxr-xr-xarch/arm/mach-ux500/include/mach/devices.h15
-rwxr-xr-xarch/arm/mach-ux500/include/mach/u8500_tsc.h286
-rw-r--r--drivers/input/touchscreen/Kconfig51
-rw-r--r--drivers/input/touchscreen/Makefile2
-rwxr-xr-xdrivers/input/touchscreen/bu21013_ts.c1357
-rw-r--r--drivers/input/touchscreen/u8500_tsc.c1474
-rwxr-xr-xinclude/linux/bu21013.h284
12 files changed, 1801 insertions, 1932 deletions
diff --git a/arch/arm/configs/mop500_USB_HOST_defconfig b/arch/arm/configs/mop500_USB_HOST_defconfig
index 7a672a088b4..4d5baad47af 100644..100755
--- a/arch/arm/configs/mop500_USB_HOST_defconfig
+++ b/arch/arm/configs/mop500_USB_HOST_defconfig
@@ -784,6 +784,9 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_TOUCHSCREEN_W90X900 is not set
+CONFIG_TOUCHSCREEN_BU21013=y
+CONFIG_BU21013_TSC_CNTL1=y
+# CONFIG_BU21013_TSC_CNTL2 is not set
# CONFIG_INPUT_MISC is not set
#
diff --git a/arch/arm/configs/mop500_defconfig b/arch/arm/configs/mop500_defconfig
index 8a20009329b..d5a6b934a81 100755
--- a/arch/arm/configs/mop500_defconfig
+++ b/arch/arm/configs/mop500_defconfig
@@ -903,13 +903,10 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_TOUCHSCREEN_W90X900 is not set
-CONFIG_U8500_TSC=y
-# CONFIG_U8500_TSC_SINGLETOUCH is not set
-CONFIG_U8500_TSC_MULTITOUCH=y
-# CONFIG_U8500_TSC_X_FLIP is not set
-CONFIG_U8500_TSC_Y_FLIP=y
-# CONFIG_U8500_TSC_EXT_CLK_9_6 is not set
CONFIG_TOUCHP_TUNING=y
+CONFIG_TOUCHSCREEN_BU21013=y
+CONFIG_BU21013_TSC_CNTL1=y
+# CONFIG_BU21013_TSC_CNTL2 is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
diff --git a/arch/arm/configs/mop500_ed_defconfig b/arch/arm/configs/mop500_ed_defconfig
index 23ec4889f89..f54d89a9d47 100755
--- a/arch/arm/configs/mop500_ed_defconfig
+++ b/arch/arm/configs/mop500_ed_defconfig
@@ -881,13 +881,10 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_TOUCHSCREEN_W90X900 is not set
-CONFIG_U8500_TSC=y
-# CONFIG_U8500_TSC_SINGLETOUCH is not set
-CONFIG_U8500_TSC_MULTITOUCH=y
-# CONFIG_U8500_TSC_X_FLIP is not set
-CONFIG_U8500_TSC_Y_FLIP=y
-# CONFIG_U8500_TSC_EXT_CLK_9_6 is not set
CONFIG_TOUCHP_TUNING=y
+CONFIG_TOUCHSCREEN_BU21013=y
+#CONFIG_BU21013_TSC_CNTL1=y
+# CONFIG_BU21013_TSC_CNTL2 is not set
# CONFIG_INPUT_MISC is not set
#
diff --git a/arch/arm/configs/mop500_power_defconfig b/arch/arm/configs/mop500_power_defconfig
index 3d0ec148809..42664d52ef7 100755
--- a/arch/arm/configs/mop500_power_defconfig
+++ b/arch/arm/configs/mop500_power_defconfig
@@ -903,13 +903,10 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
# CONFIG_TOUCHSCREEN_TSC2007 is not set
# CONFIG_TOUCHSCREEN_W90X900 is not set
-CONFIG_U8500_TSC=y
-# CONFIG_U8500_TSC_SINGLETOUCH is not set
-CONFIG_U8500_TSC_MULTITOUCH=y
-# CONFIG_U8500_TSC_X_FLIP is not set
-CONFIG_U8500_TSC_Y_FLIP=y
-# CONFIG_U8500_TSC_EXT_CLK_9_6 is not set
CONFIG_TOUCHP_TUNING=y
+CONFIG_TOUCHSCREEN_BU21013=y
+#CONFIG_BU21013_TSC_CNTL1=y
+# CONFIG_BU21013_TSC_CNTL2 is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 4fd04c72af1..c72b3699c9c 100755
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -18,6 +18,7 @@
#include <linux/i2c/lp5521.h>
#include <linux/power_supply.h>
#include <linux/lsm303dlh.h>
+#include <linux/bu21013.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
@@ -37,7 +38,6 @@
#include <mach/mmc.h>
#include <mach/setup.h>
#include <mach/i2c.h>
-#include <mach/u8500_tsc.h>
#include <video/mcde_display.h>
#include <video/mcde_display-generic_dsi.h>
@@ -179,243 +179,250 @@ static struct i2c_board_info __initdata nmdk_i2c0_egpio1_devices[] = {
/**
* Touch panel related platform specific initialization
*/
-#if defined(CONFIG_U8500_TSC)
/**
- * tp_gpio_board_init : configures the touch panel.
+ * bu21013_gpio_board_init : configures the touch panel.
+ * @ext_clk_en: external clcok enable
+ * @reset_pin: reset pin number
* This function can be used to configures
* the voltage and reset the touch panel controller.
*/
-int tp_gpio_board_init(void)
+static int bu21013_gpio_board_init(int reset_pin)
{
#ifndef CONFIG_REGULATOR
int val;
#endif
int retval = 0;
-#if (defined CONFIG_U8500_TSC_EXT_CLK_9_6 && !defined CONFIG_U8500_TSC_EXT_CLK_SHARE)
void __iomem *clk_base;
unsigned int clk_value;
-#endif
+
+ static bool config_set;
#ifndef CONFIG_REGULATOR
- /** Set the voltage for Bu21013 controller */
+ /* Set the voltage for Bu21013 controller */
val = ab8500_read(AB8500_REGU_CTRL2, AB8500_REGU_VAUX12_REGU_REG);
retval = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VAUX12_REGU_REG,
- (val | 0x1));
+ (val | TSC_AVDD_AUX1_REGULATOR));
if (retval < 0)
- return -1;
+ return retval;
val = ab8500_read(AB8500_REGU_CTRL2, AB8500_REGU_VAUX1_SEL_REG);
retval = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VAUX1_SEL_REG,
- 0x0C);
+ TSC_AVDD_VOLTAGE_2_5);
if (retval < 0)
- return -1;
-#endif
-#ifdef CONFIG_U8500_TSC_EXT_CLK_9_6
-#ifndef CONFIG_U8500_TSC_EXT_CLK_SHARE
- retval = stm_gpio_altfuncenable(GPIO_ALT_TP_SET_EXT_CLK);
- if (retval < 0) {
- printk(KERN_ERR " ext clock stm_gpio_altfuncenable failed \n");
- return -1;
- }
- clk_base = (void __iomem *)IO_ADDRESS(U8500_PRCMU_BASE + 0x1CC);
- clk_value = readl(clk_base);
- writel(0x840000, clk_base);
-#endif
+ return retval;
#endif
- if (platform_id == MOP500_PLATFORM_ID) {
- retval = gpio_request(TOUCHP_CS0, "touchp_cs0");
- if (retval) {
- printk(KERN_ERR "Unable to request gpio TOUCHP_CS0");
+ if (!config_set) {
+ retval = stm_gpio_altfuncenable(GPIO_ALT_TP_SET_EXT_CLK);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: gpio alternate failed\n", __func__);
return retval;
}
- /** why set directtion is not working ~ FIXME */
- /* gpio_direction_output(270,1); */
- gpio_set_value(TOUCHP_CS0, 1);
+ clk_base = (void __iomem *)IO_ADDRESS(U8500_PRCMU_BASE + PRCMU_CLOCK_OCR);
+ clk_value = readl(clk_base);
+ writel(TSC_EXT_CLOCK_9_6MHZ, clk_base);
+ }
+ if (platform_id == MOP500_PLATFORM_ID) {
+ gpio_set_value(EGPIO_PIN_2, 1);
} else if (platform_id == HREF_PLATFORM_ID) {
- retval = gpio_request(EGPIO_PIN_13, "touchp_cs0");
- if (retval) {
- printk(KERN_ERR "Unable to request gpio TOUCHP_CS0");
- return retval;
- }
-
- retval = gpio_direction_output(EGPIO_PIN_13, 1);
- if (retval < 0) {
- printk(KERN_ERR " reset gpio_direction_output init failed \n");
- return -1;
+ if (!config_set) {
+ retval = gpio_direction_output(reset_pin, 1);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: gpio direction failed\n", __func__);
+ return retval;
+ }
+ gpio_set_value(reset_pin, 1);
+ config_set = true;
}
- gpio_set_value(EGPIO_PIN_13, 1);
}
return retval;
}
/**
- * tp_gpio_board_exit : deconfigures the touch panel controller
+ * bu21013_gpio_board_exit : deconfigures the touch panel controller
+ * @reset_pin: reset pin number
* This function can be used to deconfigures the chip selection
* for touch panel controller.
*/
-int tp_gpio_board_exit(void)
+static int bu21013_gpio_board_exit(int reset_pin)
{
int retval = 0;
+ static bool config_disable_set;
if (platform_id == MOP500_PLATFORM_ID) {
- /** why set directtion is not working ~ FIXME */
- /* gpio_direction_output(270,1); */
- gpio_set_value(TOUCHP_CS0, 0);
+ gpio_set_value(EGPIO_PIN_2, 0);
} else if (platform_id == HREF_PLATFORM_ID) {
- retval = gpio_direction_output(EGPIO_PIN_13, 0);
- if (retval < 0) {
- printk(KERN_ERR " reset gpio_direction_output exit failed \n");
- return -1;
+ if (!config_disable_set) {
+ retval = gpio_direction_output(reset_pin, 0);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: gpio direction failed\n", __func__);
+ return retval;
+ }
+ gpio_set_value(reset_pin, 0);
+ config_disable_set = true;
}
- gpio_set_value(EGPIO_PIN_13, 0);
}
return retval;
}
/**
- * tp_init_irq : sets the callback for touch panel controller
+ * bu21013_init_irq : sets the callback for touch panel controller
* @parameter: function pointer for touch screen callback handler.
* @data: data to be passed for touch panel callback handler.
* This function can be used to set the callback handler for
* touch panel controller.
*/
-int tp_init_irq(void (*callback)(void *parameter), void *data)
+static int bu21013_init_irq(void (*callback)(void *parameter), void *data)
{
int retval = 0;
-
if (platform_id == MOP500_PLATFORM_ID) {
- retval = stmpe2401_set_callback(TOUCHP_IRQ, callback,
+ retval = stmpe2401_set_callback(EGPIO_PIN_3, callback,
(void *)data);
if (retval < 0)
- printk(KERN_ERR " stmpe2401_set_callback failed \n");
+ printk(KERN_ERR "%s: set callback failed\n", __func__);
} else if (platform_id == HREF_PLATFORM_ID) {
- if (href_v1_board == 0) {
+ if (!href_v1_board) {
retval = tc35892_set_callback(EGPIO_PIN_12, callback,
(void *)data);
if (retval < 0)
- printk(KERN_ERR " tc35892_set_callback failed \n");
+ printk(KERN_ERR "%s: set callback failed\n", __func__);
+ retval = tc35892_set_gpio_intr_conf(EGPIO_PIN_12,
+ EDGE_SENSITIVE, TC35892_FALLING_EDGE_OR_LOWLEVEL);
+ if (retval < 0)
+ printk(KERN_ERR "%s: config failed\n", __func__);
}
}
return retval;
}
/**
- * tp_exit_irq : removes the callback for touch panel controller
+ * bu21013_exit_irq : removes the callback for touch panel controller
* This function can be used to removes the callback handler for
* touch panel controller.
*/
-int tp_exit_irq(void)
+static int bu21013_exit_irq(void)
{
int retval = 0;
if (platform_id == MOP500_PLATFORM_ID) {
- retval = stmpe2401_remove_callback(TOUCHP_IRQ);
+ retval = stmpe2401_remove_callback(EGPIO_PIN_3);
if (retval < 0)
- printk(KERN_ERR " stmpe2401_remove_callback failed \n");
+ printk(KERN_ERR "%s: remove callback failed\n", __func__);
} else if (platform_id == HREF_PLATFORM_ID) {
- if (href_v1_board == 0) {
+ if (!href_v1_board) {
retval = tc35892_remove_callback(EGPIO_PIN_12);
if (retval < 0)
- printk(KERN_ERR " tc35892_remove_callback failed \n");
+ printk(KERN_ERR "%s: remove calllback failed\n", __func__);
}
}
return retval;
}
/**
- * tp_pen_down_irq_enable : enable the interrupt for touch panel controller
+ * bu21013_pen_down_irq_enable : enable the interrupt for touch panel controller
* This function can be used to enable the interrupt for touch panel controller.
*/
-int tp_pen_down_irq_enable(void)
+static int bu21013_pen_down_irq_enable(void)
{
int retval = 0;
- if (platform_id == MOP500_PLATFORM_ID) {
- /* do nothing */
- } else if (platform_id == HREF_PLATFORM_ID) {
- if (href_v1_board == 0) {
- retval = tc35892_set_gpio_intr_conf(EGPIO_PIN_12,
- EDGE_SENSITIVE, TC35892_FALLING_EDGE_OR_LOWLEVEL);
- if (retval < 0)
- printk(KERN_ERR " tc35892_set_gpio_intr_conf failed\n");
+ if (platform_id == HREF_PLATFORM_ID) {
+ if (!href_v1_board) {
retval = tc35892_set_intr_enable(EGPIO_PIN_12,
ENABLE_INTERRUPT);
if (retval < 0)
- printk(KERN_ERR " tc35892_set_intr_enable failed \n");
+ printk(KERN_ERR "%s: failed\n", __func__);
}
}
return retval;
}
/**
- * tp_pen_down_irq_disable : disable the interrupt
+ * bu21013_pen_down_irq_disable : disable the interrupt
* This function can be used to disable the interrupt for
* touch panel controller.
*/
-int tp_pen_down_irq_disable(void)
+static int bu21013_pen_down_irq_disable(void)
{
int retval = 0;
- if (platform_id == MOP500_PLATFORM_ID) {
- /* do nothing */
- } else if (platform_id == HREF_PLATFORM_ID) {
- if (href_v1_board == 0) {
+ if (platform_id == HREF_PLATFORM_ID) {
+ if (!href_v1_board) {
retval = tc35892_set_intr_enable(EGPIO_PIN_12,
DISABLE_INTERRUPT);
if (retval < 0)
- printk(KERN_ERR " tc35892_set_intr_enable failed \n");
+ printk(KERN_ERR "%s: failed\n", __func__);
}
}
return retval;
}
/**
- * tp_read_pin_val : get the interrupt pin value
+ * bu21013_read_pin_val : get the interrupt pin value
* This function can be used to get the interrupt pin value for touch panel
* controller.
*/
-int tp_read_pin_val(void)
+static int bu21013_read_pin_val(void)
{
int data = 0;
- unsigned int touch_gpio_pin = 84;
if (platform_id == MOP500_PLATFORM_ID)
- data = gpio_get_value(TOUCHP_IRQ);
+ data = gpio_get_value(EGPIO_PIN_3);
else if (platform_id == HREF_PLATFORM_ID) {
- if (href_v1_board == 0)
+ if (!href_v1_board)
data = gpio_get_value(EGPIO_PIN_12);
else
- data = gpio_get_value(touch_gpio_pin);
+ data = gpio_get_value(TOUCH_GPIO_PIN);
}
return data;
}
/**
- * tp_board_href_v1 : update the href v1 flag
+ * bu21013_board_href_v1 : update the href v1 flag
* This function can be used to update the board.
*/
-int tp_board_href_v1(void)
+static bool bu21013_board_check(void)
{
- unsigned int touch_gpio_pin = 84;
+ href_v1_board = false;
if (platform_id == HREF_PLATFORM_ID) {
- if (u8500_is_earlydrop())
- href_v1_board = 0;
- else
- href_v1_board = gpio_get_value(touch_gpio_pin);
- } else
- href_v1_board = 0;
+ if (!u8500_is_earlydrop()) {
+ if (gpio_get_value(TOUCH_GPIO_PIN) == 1)
+ href_v1_board = true;
+ }
+ }
return href_v1_board;
}
-static struct tp_device tsc_plat_device = {
- .cs_en = tp_gpio_board_init,
- .cs_dis = tp_gpio_board_exit,
- .irq_init = tp_init_irq,
- .irq_exit = tp_exit_irq,
- .pirq_en = tp_pen_down_irq_enable,
- .pirq_dis = tp_pen_down_irq_disable,
- .pirq_read_val = tp_read_pin_val,
- .board_href_v1 = tp_board_href_v1,
- .irq = GPIO_TO_IRQ(84),
-};
+static struct bu21013_platform_device tsc_plat_device = {
+ .cs_en = bu21013_gpio_board_init,
+ .cs_dis = bu21013_gpio_board_exit,
+ .irq_init = bu21013_init_irq,
+ .irq_exit = bu21013_exit_irq,
+ .pirq_en = bu21013_pen_down_irq_enable,
+ .pirq_dis = bu21013_pen_down_irq_disable,
+ .pirq_read_val = bu21013_read_pin_val,
+ .board_check = bu21013_board_check,
+ .irq = GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+ .cs_pin = EGPIO_PIN_13,
+ .x_max_res = 480,
+ .y_max_res = 864,
+ .touch_x_max = TOUCH_XMAX,
+ .touch_y_max = TOUCH_YMAX,
+#ifdef CONFIG_BU21013_TSC_CNTL1
+ .tp_cntl = 1,
#endif
+};
+static struct bu21013_platform_device tsc_cntl2_plat_device = {
+ .cs_en = bu21013_gpio_board_init,
+ .cs_dis = bu21013_gpio_board_exit,
+ .board_check = bu21013_board_check,
+ .pirq_read_val = bu21013_read_pin_val,
+ .irq = GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+ .cs_pin = EGPIO_PIN_13,
+ .x_max_res = 480,
+ .y_max_res = 864,
+ .touch_x_max = TOUCH_XMAX,
+ .touch_y_max = TOUCH_YMAX,
+#ifdef CONFIG_BU21013_TSC_CNTL2
+ .tp_cntl = 2,
+#endif
+};
/* Portrait */
#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY
/* Rotation always on */
@@ -510,13 +517,16 @@ static struct i2c_board_info __initdata u8500_i2c3_devices[] = {
/* NFC - Address TBD, FIXME */
I2C_BOARD_INFO("nfc", 0x68),
},
-#if defined(CONFIG_U8500_TSC)
{
/* Touschscreen */
- I2C_BOARD_INFO(DRIVER_TP, I2C3_TOUCHP_ADDRESS),
+ I2C_BOARD_INFO("bu21013_tp", 0x5C),
.platform_data = &tsc_plat_device,
},
-#endif
+ {
+ /* Touschscreen */
+ I2C_BOARD_INFO("bu21013_tp", 0x5D),
+ .platform_data = &tsc_cntl2_plat_device,
+ },
};
@@ -1467,8 +1477,8 @@ static struct platform_device *platform_board_devs[] __initdata = {
&ab8500_gpadc_device,
&ab8500_bm_device,
&ux500_musb_device,
- &ux500_b2r2_device,
&ux500_mcde_device,
+ &ux500_b2r2_device,
#ifdef CONFIG_ANDROID_PMEM
&u8500_pmem_device,
&u8500_pmem_mio_device,
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index c00a36cffed..73ddb146626 100755
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -63,4 +63,19 @@ extern int platform_id;
#define MOP500_PLATFORM_ID 0
#define HREF_PLATFORM_ID 1
+#define MOP500_PLATFORM_ID 0
+#define HREF_PLATFORM_ID 1
+
+/**
+ * Touchpanel related macros declaration
+ */
+#define TOUCH_GPIO_PIN 84
+
+#define TOUCH_XMAX 384
+#define TOUCH_YMAX 704
+
+#define PRCMU_CLOCK_OCR 0x1CC
+#define TSC_EXT_CLOCK_9_6MHZ 0x840000
+#define TSC_AVDD_VOLTAGE_2_5 0x08
+#define TSC_AVDD_AUX1_REGULATOR 0x01
#endif
diff --git a/arch/arm/mach-ux500/include/mach/u8500_tsc.h b/arch/arm/mach-ux500/include/mach/u8500_tsc.h
deleted file mode 100755
index c51ca4cc207..00000000000
--- a/arch/arm/mach-ux500/include/mach/u8500_tsc.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Overview:
- * Touch panel register definitions
- *
- * Copyright (C) 2009 ST-Ericsson SA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-
-
-#ifndef _TOUCHP_NOMADIK_H
-#define _TOUCHP_NOMADIK_H
-
-#include <mach/hardware.h>
-
-/**
- * Touchpanel related macros declaration
- */
-#define I2C3_TOUCHP_ADDRESS 0x5C/* I2C slave address */
-#define TOUCHP_IRQ EGPIO_PIN_3 /* PENIRQNO egpio3 */
-#define TOUCHP_CS0 EGPIO_PIN_2 /* Chip select egpio2 */
-
-#define DRIVER_TP "u8500_tp"
-/*
- *TOUCH SCREEN DRIVER MACROS used for Power on Sequence
- */
-#define TSC_INT_CLR 0xE8
-#define TSC_INT_MODE 0xE9
-#define TSC_GAIN 0xEA
-#define TSC_OFFSET_MODE 0xEB
-#define TSC_XY_EDGE 0xEC
-#define TSC_RESET 0xED
-#define TSC_CALIB 0xEE
-#define TSC_DONE 0xEF
-#define TSC_SENSOR_0_7 0xF0
-#define TSC_SENSOR_8_15 0xF1
-#define TSC_SENSOR_16_23 0xF2
-#define TSC_POS_MODE1 0xF3
-#define TSC_POS_MODE2 0xF4
-#define TSC_CLK_MODE 0xF5
-#define TSC_IDLE 0xFA
-#define TSC_FILTER 0xFB
-#define TSC_TH_ON 0xFC
-#define TSC_TH_OFF 0xFD
-#define TSC_INTR_STATUS 0x7B
-#define TSC_POS_X1 0x73
-#define TSC_POS_Y1 0x75
-#define TSC_POS_X2 0x77
-#define TSC_POS_Y2 0x79
-
-#define MAX_10BIT ((1<<10)-1)
-
-
-#define TSC_CLK_MODE_VAL1 0x82
-#define TSC_CLK_MODE_VAL2 0x81
-#define TSC_IDLE_VAL 0x11
-#define TSC_INT_MODE_VAL 0x00
-#define TSC_FILTER_VAL 0xFF
-#define TSC_TH_ON_VAL 0x20
-#define TSC_TH_OFF_VAL 0x18
-#define TSC_GAIN_VAL 0x03
-#define TSC_OFFSET_MODE_VAL 0x00
-#define TSC_XY_EDGE_VAL 0xA5
-#define TSC_DONE_VAL 0x01
-
-
-/*
- * Resolutions
- */
-/*Panel Resolution, Target size. (864*480)*/
-#define X_MAX (480)
-#define Y_MAX (864)
-
-/*Touchpanel Resolution */
-#define TOUCH_XMAX 384
-#define TOUCH_YMAX 704
-
-#define TRUE (1)
-#define FALSE (0)
-
-#define SET (1)
-#define CLR (0)
-
-#define START (0)
-#define STOP (-1)
-
-/*Direction Indicator */
-#define DIR_INVALID (0)
-#define DIR_LEFT (1)
-#define DIR_RIGHT (2)
-#define DIR_UP (3)
-#define DIR_DOWN (4)
-
-/* Pinch */
-#define PINCH_KEEP (0)
-#define PINCH_IN (1)
-#define PINCH_OUT (2)
-
-/* Rotate */
-#define ROTATE_INVALID (0)
-#define ROTATE_R_UR (1)
-#define ROTATE_R_RD (2)
-#define ROTATE_R_DL (3)
-#define ROTATE_R_LU (4)
-#define ROTATE_L_LD (5)
-#define ROTATE_L_DR (6)
-#define ROTATE_L_RU (7)
-#define ROTATE_L_UL (8)
-
-/* Gesture Information */
-#define GES_FLICK 0x01
-#define GES_TAP 0x02
-#define GES_PINCH 0x03
-#define GES_DRAGDROP 0x04
-#define GES_TOUCHSTART 0x05
-#define GES_TOUCHEND 0x06
-#define GES_MOVE 0x07
-#define GES_ROTATE 0x08
-#define GES_UNKNOWN 0xff
-
-/* Tap times */
-#define TAP_SINGLE 0x01
-#define TAP_DOUBLE 0x02
-#define TAP_TRIPLE 0x03
-
-/* Speed */
-#define LOWSPEED 1
-#define HIGHSPEED 2
-#define THRESHOLD_TAPLIMIT 60
-#define THRESHOLD_FLICK 60
-#define THRESHOLD_FLICK_SPEED 300
-#define THRESHOLD_PINCH_SPEED 3000
-#define THRESHOLD_DRAGDROP 100
-#define THRESHOLD_ROTATE 3
-#define THRESHOLD_ROTATE_HIST 8
-#define THRESHOLD_PINCH 500
-#define DIRHEADER 6
-#define DIRTRACEN 32
-#define SMA_N 80
-#define SMA_ARRAY 81
-#define THRESHOLD_SMA_N SMA_N
-#define MULTITOUCH_SIN_N 6
-#define PENUP_TIMEOUT (10) /* msec */
-
-/**
- * Error handling messages
- **/
-typedef enum {
- TSC_OK = 0,
- TSC_BAD_PARAMETER = -2,
- TSC_FEAT_NOT_SUPPORTED = -3,
- TSC_INTERNAL_ERROR = -4,
- TSC_TIMEOUT_ERROR = -5,
- TSC_INITIALIZATION_ERROR = -6,
- TSC_I2C_ERROR = -7,
- TSC_ERROR = -8
-} tsc_error;
-
-/**
- * struct tp_device - Handle the platform data
- * @cs_en: pointer to the cs enable function
- * @cs_dis: pointer to the cs disable function
- * @irq_init: pointer to the irq init function
- * @irq_exit: pointer to the irq exit function
- * @pirq_en: pointer to the pen irq en function
- * @pirq_dis: pointer to the pen irq disable function
- * @pirq_read_val: pointer to read the pen irq value function
- * @board_href_v1: pointer to the get the board version
- * @irq: irq variable
- * This is used to handle the platform data
- **/
-struct tp_device {
- int (*cs_en)(void);
- int (*cs_dis)(void);
- int (*irq_init)(void (*callback)(void *parameter), void *p);
- int (*irq_exit)(void);
- int (*pirq_en) (void);
- int (*pirq_dis)(void);
- int (*pirq_read_val)(void);
- int (*board_href_v1)(void);
- unsigned int irq;
-};
-
-/**
- * struct touch_point - x and y co-ordinates of touch panel
- * @x: x co-ordinate
- * @y: y co-ordinate
- * This is used to hold the x and y co-ordinates of touch panel
- **/
-struct touch_point {
- signed short x;
- signed short y;
-};
-
-/**
- * struct gesture_info - hold the gesture of the touch
- * @gesture_kind: gesture kind variable
- * @pt: arry to touch_point structure
- * @dir: direction variable
- * @times: touch times
- * @speed: speed of the touch
- * This is used to hold the gesture of the touch.
- **/
-struct gesture_info {
- signed short gesture_kind;
- struct touch_point pt[2];
- signed short dir;
- signed short times;
- signed short speed;
-};
-
-/**
- * struct u8500_tsc_data - touch panel data structure
- * @client: pointer to the i2c client
- * @chip: pointer to the touch panel controller
- * @pin_dev: pointer to the input device structure
- * @penirq_timer: variable to the timer list structure
- * @touchp_event: variable to the wait_queue_head_t structure
- * @touch_en: variable for reporting the co-ordinates to input device.
- * @finger1_pressed: variable to indicate the first co-ordinates.
- * @finger2_pressed: variable to indicate the first co-ordinates.
- * @m_tp_timer_int_wq: variable to work structure for timer
- * @m_tp_timer_gpio_wq: variable to work structure for interrupt
- * @gesture_info: variable to gesture_info structure
- * @touch_count: variable to maintain sensors input count
- * @touchflag: variable to indicate the touch
- * @pre_tap_flag: flag to indicate the pre tap
- * @flick_flag: flickering flag
- * @touch_continue: to continue the touch flag
- * @pre_tap_flag_level: pre tap level flag
- * @x1: x1 co-ordinate
- * @y1: y1 co-ordinate
- * @x2: x2 co-ordinate
- * @y2: y2 co-ordinate
- * @pinch_start: pinch start
- * @tap_start_point: variable to touch_point structure
- * @dir_trace: array for data trace
- * @dir_idx: id for direction
- * @rotate_data: array to maintain the rotate data
- * @href_v1_flag: variable to indicate the href v1 board
- * @finger2_count: count for finger2 touches
- *
- * Tocuh panel data structure
- */
-struct u8500_tsc_data {
- struct i2c_client *client;
- struct tp_device *chip;
- struct input_dev *pin_dev;
- struct task_struct *touchp_tsk;
- struct timer_list penirq_timer;
- wait_queue_head_t touchp_event;
- unsigned short touch_en;
- unsigned short finger1_pressed;
- unsigned short finger2_pressed;
- struct work_struct m_tp_timer_int_wq;
- struct work_struct m_tp_gpio_int_wq;
- struct gesture_info gesture_info;
- signed long touch_count;
- unsigned short touchflag;
- unsigned char pre_tap_flag;
- unsigned char flick_flag;
- unsigned char touch_continue;
- unsigned char pre_tap_flag_level;
- signed short x1, y1;
- signed short x2, y2;
- unsigned char pinch_start;
- struct touch_point tap_start_point;
- unsigned char dir_trace[DIRHEADER+DIRTRACEN];
- unsigned char dir_idx;
- unsigned char rotate_data[5][5];
- bool href_v1_flag;
- u8 finger2_count;
-};
-
-int doCalibrate(struct i2c_client *i2c);
-int getCalibStatus(struct i2c_client *i2c);
-void init_config(struct u8500_tsc_data *data);
-void get_touch(struct u8500_tsc_data *data);
-void touch_calculation(struct gesture_info *p_gesture_info);
-int get_touch_message(struct u8500_tsc_data *data);
-void check_board(struct u8500_tsc_data *data);
-#endif
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index b0866806767..1899e800bb8 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -595,49 +595,18 @@ config TOUCHSCREEN_PCAP
To compile this driver as a module, choose M here: the
module will be called pcap_ts.
-config U8500_TSC
- tristate "BU21013 based capcitive based sensors for U8500 platform"
- depends on ARCH_U8500 && I2C_NOMADIK
- default m
- help
- Say Y here if you have a touchscreen interface using the
- BU21013 controller for U8500 platform.
-
- If unsure, say N (but it's safe to say "Y").
-
- To compile this driver as a module, choose M here:
- choice
- prompt "TOUCH MODE"
- depends on U8500_TSC
- default U8500_TSC_SINGLETOUCH
-
- config U8500_TSC_SINGLETOUCH
- depends on U8500_TSC
- bool "Single Touch Mode"
-
- config U8500_TSC_MULTITOUCH
- depends on U8500_TSC
- bool "Multi Touch Mode"
- endchoice
-
-config U8500_TSC_X_FLIP
- bool "Enable x flip for U8500 touch panel in portrait mode"
- depends on U8500_TSC && FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
-
-config U8500_TSC_Y_FLIP
- bool "Enable y flip for U8500 touch panel in portrait mode"
- depends on U8500_TSC && FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
+config TOUCHSCREEN_BU21013
+ tristate "BU21013 based touch panel controllers"
+ depends on I2C_NOMADIK && FB_MCDE
default y
-config U8500_TSC_EXT_CLK_9_6
- bool "Enable external clock for U8500 touch panel tuning"
- depends on U8500_TSC
+config BU21013_TSC_CNTL1
+ bool "Touch panel1 with BU21013 controller"
+ depends on TOUCHSCREEN_BU21013
+ default y
-config U8500_TSC_EXT_CLK_SHARE
- bool "Clock shared between Camera and touch panel"
- depends on U8500_TSC_EXT_CLK_9_6
+config BU21013_TSC_CNTL2
+ bool "Touch panel2 with BU21013 controller2"
+ depends on TOUCHSCREEN_BU21013
-config TOUCHP_TUNING
- bool "Enable sysfs for U8500 touch panel tuning"
- depends on U8500_TSC
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 7ff5b85e858..7ad9a8405d2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -46,4 +46,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
-obj-$(CONFIG_U8500_TSC) += u8500_tsc.o
+obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
new file mode 100755
index 00000000000..1b7f8c165df
--- /dev/null
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -0,0 +1,1357 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2009
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/bu21013.h>
+
+/**
+ * Touchpanel related macros declaration
+ */
+#define PEN_DOWN_INTR 0
+#define PEN_UP_INTR 1
+#define RESET_DELAY 30
+#define POLLING_DELAY 100
+#define MAX_TOOL_WIDTH 15
+#define MAX_TOUCH_MAJOR 255
+#define MAX_PRESSURE 1
+#define PENUP_TIMEOUT (20)/* msec */
+#define SCALE_FACTOR 1000
+#define I2C_ADDR_TP2 0x5D
+
+#define START (0)
+#define STOP (-1)
+
+/*Direction Indicator */
+#define DIR_INVALID (0)
+#define DIR_LEFT (1)
+#define DIR_RIGHT (2)
+#define DIR_UP (3)
+#define DIR_DOWN (4)
+
+/* Pinch */
+#define PINCH_KEEP (0)
+#define PINCH_IN (1)
+#define PINCH_OUT (2)
+
+/* Rotate */
+#define ROTATE_INVALID (0)
+#define ROTATE_R_UR (1)
+#define ROTATE_R_RD (2)
+#define ROTATE_R_DL (3)
+#define ROTATE_R_LU (4)
+#define ROTATE_L_LD (5)
+#define ROTATE_L_DR (6)
+#define ROTATE_L_RU (7)
+#define ROTATE_L_UL (8)
+
+/* Gesture Information */
+#define GES_FLICK 0x01
+#define GES_TAP 0x02
+#define GES_PINCH 0x03
+#define GES_DRAGDROP 0x04
+#define GES_TOUCHSTART 0x05
+#define GES_TOUCHEND 0x06
+#define GES_MOVE 0x07
+#define GES_ROTATE 0x08
+#define GES_UNKNOWN 0xff
+
+/* Speed */
+#define LOWSPEED 1
+#define HIGHSPEED 2
+#define THRESHOLD_TAPLIMIT 60
+#define THRESHOLD_FLICK 60
+#define THRESHOLD_FLICK_SPEED 300
+#define THRESHOLD_PINCH_SPEED 3000
+#define THRESHOLD_DRAGDROP 100
+#define THRESHOLD_ROTATE 3
+#define THRESHOLD_ROTATE_HIST 8
+#define THRESHOLD_PINCH 500
+#define DIRHEADER 6
+#define DIRTRACEN 32
+#define DIR_TRACE_VALUE 0x05
+#define DRIVER_TP "bu21013_tp"
+
+static struct i2c_driver bu21013_tp_driver;
+struct bu21013_ts_data *tp_sys_data;
+
+static int bu21013_init_chip(struct bu21013_ts_data *data);
+
+static ssize_t touchp_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ u8 timeout;
+ u8 sys_th_on;
+ u8 sys_th_off;
+ u8 sys_gain;
+ u8 sys_ext_clock;
+ u8 sys_edge_mode;
+
+ if (strcmp(attr->name, "timeout_value") == 0) {
+ timeout = tp_sys_data->penup_timer;
+ sprintf(buf, "%d\n", timeout);
+ } else if (strcmp(attr->name, "th_on") == 0) {
+ sys_th_on = tp_sys_data->th_on;
+ sprintf(buf, "%d\n", sys_th_on);
+ } else if (strcmp(attr->name, "th_off") == 0) {
+ sys_th_off = tp_sys_data->th_off;
+ sprintf(buf, "%d\n", sys_th_off);
+ } else if (strcmp(attr->name, "gain") == 0) {
+ sys_gain = tp_sys_data->gain;
+ sprintf(buf, "%d\n", sys_gain);
+ } else if (strcmp(attr->name, "ext_clk") == 0) {
+ sys_ext_clock = tp_sys_data->chip->ext_clk;
+ sprintf(buf, "%d\n", sys_ext_clock);
+ } else if (strcmp(attr->name, "edge_mode") == 0) {
+ sys_edge_mode = tp_sys_data->chip->edge_mode;
+ sprintf(buf, "%d\n", sys_edge_mode);
+ }
+ return strlen(buf);
+}
+static ssize_t touchp_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ int ret = 0;
+ int timeout;
+ int sys_th_on;
+ int sys_th_off;
+ int sys_gain;
+ int sys_ext_clock;
+ int sys_edge_mode;
+
+ if (strcmp(attr->name, "timeout_value") == 0) {
+ ret = sscanf(buf, "%d", &timeout);
+ if (ret == 1)
+ tp_sys_data->penup_timer = timeout;
+ } else if (strcmp(attr->name, "th_on") == 0) {
+ ret = sscanf(buf, "%d", &sys_th_on);
+ if ((ret == 1) && (tp_sys_data->th_on != sys_th_on)) {
+ tp_sys_data->th_on = sys_th_on;
+ if (tp_sys_data->th_on < BU21013_TH_ON_MAX)
+ bu21013_init_chip(tp_sys_data);
+ }
+ } else if (strcmp(attr->name, "th_off") == 0) {
+ ret = sscanf(buf, "%d", &sys_th_off);
+ if ((ret == 1) && (tp_sys_data->th_off != sys_th_off)) {
+ tp_sys_data->th_off = sys_th_off;
+ if (tp_sys_data->th_off < BU21013_TH_OFF_MAX)
+ bu21013_init_chip(tp_sys_data);
+ }
+ } else if (strcmp(attr->name, "gain") == 0) {
+ ret = sscanf(buf, "%d", &sys_gain);
+ if ((ret == 1) && (tp_sys_data->gain != sys_gain)) {
+ tp_sys_data->gain = sys_gain;
+ bu21013_init_chip(tp_sys_data);
+ }
+ } else if (strcmp(attr->name, "ext_clk") == 0) {
+ ret = sscanf(buf, "%d", &sys_ext_clock);
+ if ((ret == 1) && (tp_sys_data->chip->ext_clk != sys_ext_clock)) {
+ tp_sys_data->chip->ext_clk = sys_ext_clock;
+ bu21013_init_chip(tp_sys_data);
+ }
+ } else if (strcmp(attr->name, "edge_mode") == 0) {
+ ret = sscanf(buf, "%d", &sys_edge_mode);
+ if ((ret == 1) && (tp_sys_data->chip->edge_mode != sys_edge_mode)) {
+ tp_sys_data->chip->edge_mode = sys_edge_mode;
+ bu21013_init_chip(tp_sys_data);
+ }
+ }
+ return ret == 1 ? len : -EINVAL;
+}
+
+static struct attribute touchp_timeout = {.name = "timeout_value",
+ .mode = 0666};
+static struct attribute touchp_th_on = {.name = "th_on", .mode = 0666};
+static struct attribute touchp_th_off = {.name = "th_off", .mode = 0666};
+static struct attribute touchp_gain = {.name = "gain", .mode = 0666};
+static struct attribute touchp_ext_clk = {.name = "ext_clk", .mode = 0666};
+static struct attribute touchp_edge_mode = {.name = "edge_mode", .mode = 0666};
+
+static struct attribute *touchp_attribute[] = {
+ &touchp_timeout,
+ &touchp_th_on,
+ &touchp_th_off,
+ &touchp_gain,
+ &touchp_ext_clk,
+ &touchp_edge_mode,
+ NULL
+};
+
+static struct sysfs_ops touchp_sysfs_ops = {
+ .show = touchp_attr_show,
+ .store = touchp_attr_store,
+};
+
+static struct kobj_type ktype_touchp = {
+ .sysfs_ops = &touchp_sysfs_ops,
+ .default_attrs = touchp_attribute,
+};
+
+/*
+ * bu21013_do_calibrate() - Do the software Calibration
+ * @i2c: i2c_client structure pointer
+ * Do the soft calibration on the touch screen
+ * and returns integer
+ */
+int bu21013_do_calibrate(struct i2c_client *i2c)
+{
+ int retval;
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_CALIB,
+ BU21013_CALIB_ENABLE);
+ if (retval < 0)
+ dev_err(&i2c->dev, "reset failed retval=0x%x \n", retval);
+ return retval;
+}
+/**
+ * bu21013_touch_calc(): Get the exact co-ordinates of the touch interrupt
+ * @data:bu21013_ts_data structure pointer
+ * Transfer the position information from touch sensor
+ * coordinate to display coordinate and returns none.
+ */
+void bu21013_touch_calc(struct bu21013_ts_data *data)
+{
+ signed short x1, y1;
+ struct bu21013_gesture_info *p_gesture_info = &data->gesture_info;
+ int tmpx, tmpy;
+ signed short x2, y2;
+
+ tmpx = (data->chip->x_max_res * SCALE_FACTOR / data->chip->touch_x_max);
+ tmpy = (data->chip->y_max_res * SCALE_FACTOR / data->chip->touch_y_max);
+ x1 = p_gesture_info->pt[0].x;
+ y1 = p_gesture_info->pt[0].y;
+ x1 = x1 * tmpx / SCALE_FACTOR;
+ y1 = y1 * tmpy / SCALE_FACTOR;
+ if ((data->chip->portrait) && (y1 != 0))
+ y1 = data->chip->y_max_res - y1;
+ p_gesture_info->pt[0].x = x1;
+ p_gesture_info->pt[0].y = y1;
+ x2 = p_gesture_info->pt[1].x;
+ y2 = p_gesture_info->pt[1].y;
+ x2 = x2 * tmpx / SCALE_FACTOR;
+ y2 = y2 * tmpy / SCALE_FACTOR;
+ if ((data->chip->portrait) && (y2 != 0))
+ y2 = data->chip->y_max_res - y2;
+ p_gesture_info->pt[1].x = x2;
+ p_gesture_info->pt[1].y = y2;
+
+}
+
+/**
+ * bu21013_get_touch(): Get the co-ordinates of the touch interrupt
+ * @data:bu21013_ts_data structure pointer
+ * Get touched point position
+ * from touch sensor registers and write to global variables.
+ */
+void bu21013_get_touch(struct bu21013_ts_data *data)
+{
+ struct i2c_client *i2c = data->client;
+ int retval;
+ u8 sensors_buf[3];
+ u8 finger1_buf[4];
+ int count;
+ signed short tmp1x = 0;
+ signed short tmp1y = 0;
+ u8 finger2_buf[4];
+ signed short tmp2x = 0;
+ signed short tmp2y = 0;
+ short touch_x_max = data->chip->touch_x_max;
+ short touch_y_max = data->chip->touch_y_max;
+
+ for (count = 0; count < 2; count++) {
+ if (!data->chip->edge_mode) {
+ retval = i2c_smbus_read_i2c_block_data(i2c, BU21013_SENSORS_BTN_0_7, 3, sensors_buf);
+ if (retval < 0)
+ goto end;
+ data->last_press = sensors_buf[0] | sensors_buf[1] | sensors_buf[2];
+ }
+ retval = i2c_smbus_read_i2c_block_data(i2c, BU21013_X1_POS_MSB, 4, finger1_buf);
+ if (retval < 0)
+ goto end;
+ tmp1x = (finger1_buf[0] << 2) | finger1_buf[1];
+ tmp1y = (finger1_buf[2] << 2) | finger1_buf[3];
+ if ((tmp1x != 0) && (tmp1y != 0))
+ break;
+ }
+ data->finger1_pressed = false;
+ if ((data->chip->edge_mode || data->last_press) &
+ (tmp1x != 0 && tmp1y != 0) &&
+ (tmp1x < touch_x_max && tmp1y < touch_y_max))
+ data->finger1_pressed = true;
+
+ if (data->finger1_pressed) {
+ data->x1 = tmp1x;
+ data->y1 = tmp1y;
+ } else {
+ data->x1 = 0;
+ data->y1 = 0;
+ }
+ for (count = 0; count < 2; count++) {
+ retval = i2c_smbus_read_i2c_block_data(i2c, BU21013_X2_POS_MSB, 4, finger2_buf);
+ if (retval < 0)
+ goto end;
+ tmp2x = (finger2_buf[0] << 2) | finger2_buf[1];
+ tmp2y = (finger2_buf[2] << 2) | finger2_buf[3];
+ if ((tmp2x != 0) && (tmp2y != 0))
+ break;
+ }
+ data->finger2_pressed = false;
+ if ((data->chip->edge_mode || data->last_press) &&
+ (tmp2x != 0 && tmp2y != 0) &&
+ (tmp2x < touch_x_max && tmp2y < touch_y_max))
+ data->finger2_pressed = true;
+ data->finger2_count = 1;
+end:
+ if (data->finger2_pressed) {
+ data->x2 = tmp2x;
+ data->y2 = tmp2y;
+ } else {
+ data->x2 = 0;
+ data->y2 = 0;
+ }
+ if (data->finger1_pressed || data->finger2_pressed) {
+ data->touch_en = true;
+ data->touchflag = true;
+ } else {
+ data->touch_en = false;
+ data->touchflag = false;
+ }
+ if ((!data->finger1_pressed) && (data->finger2_pressed)) {
+ data->x1 = tmp2x;
+ data->y1 = tmp2y;
+ data->x2 = 0;
+ data->y2 = 0;
+ data->finger2_pressed = false;
+ }
+}
+/**
+ * bu21013_update_ges_no_touch(): Generate the gesture message for single touch
+ * @data: a pointer to the device structure
+ * Generate the gesture message for single touch.
+ */
+void bu21013_update_ges_st_touch(struct bu21013_ts_data *data)
+{
+ struct bu21013_gesture_info *p_gesture_info = &data->gesture_info;
+ signed short x_delta, y_delta;
+ unsigned char dir_left_right, dir_up_down;
+ unsigned char tmp;
+ unsigned char dir1, dir2;
+ static struct bu21013_touch_point pre_gesture_point;
+ x_delta = p_gesture_info->pt[0].x - pre_gesture_point.x;
+ y_delta = p_gesture_info->pt[0].y - pre_gesture_point.y;
+ if ((x_delta < THRESHOLD_ROTATE) ||
+ (-x_delta < THRESHOLD_ROTATE))
+ x_delta = 0;
+
+ if ((y_delta < THRESHOLD_ROTATE) ||
+ (-y_delta < THRESHOLD_ROTATE))
+ y_delta = 0;
+
+ p_gesture_info->dir = DIR_INVALID;
+ if (x_delta != y_delta) {
+ dir_left_right = DIR_RIGHT;
+ if (x_delta < 0) {
+ dir_left_right = DIR_LEFT;
+ x_delta = -x_delta;
+ }
+ dir_up_down = DIR_DOWN;
+ if (y_delta < 0) {
+ y_delta = -y_delta;
+ dir_up_down = DIR_UP;
+ }
+ p_gesture_info->dir = dir_up_down;
+ if (x_delta > y_delta)
+ p_gesture_info->dir = dir_left_right;
+ tmp = p_gesture_info->dir;
+ data->dir_trace[tmp]++;
+ data->dir_trace[data->dir_idx] = tmp;
+ if (data->dir_idx < (THRESHOLD_ROTATE_HIST + DIRHEADER))
+ data->dir_idx++;
+ else
+ data->dir_idx = DIRHEADER;
+ data->dir_trace[data->dir_trace[data->dir_idx]]--;
+ dir1 = data->dir_trace[0];
+ for (dir2 = 1; dir2 < 5; dir2++) {
+ if (data->dir_trace[data->dir_trace[0]]
+ < data->dir_trace[dir2]) {
+ data->dir_trace[0] = dir2;
+ p_gesture_info->dir
+ = data->rotate_data[dir1][dir2];
+ if (p_gesture_info->dir)
+ p_gesture_info->gesture_kind
+ = GES_ROTATE;
+ break;
+ }
+ }
+ }
+ if (p_gesture_info->dir == ROTATE_INVALID) {
+ p_gesture_info->gesture_kind = GES_MOVE;
+ p_gesture_info->speed = data->touch_count;
+ }
+}
+/**
+ * bu21013_update_ges_no_touch(): Generate the gesture message for multi touch
+ * @data: a pointer to the device structure
+ * Generate the gesture message for multi touch.
+ */
+void bu21013_update_ges_mt_touch(struct bu21013_ts_data *data)
+{
+ struct bu21013_gesture_info *p_gesture_info = &data->gesture_info;
+ signed short x_delta, y_delta;
+ signed short area_diff;
+ unsigned long area;
+ static unsigned long pre_area;
+
+ x_delta = p_gesture_info->pt[0].x - p_gesture_info->pt[1].x;
+ y_delta = p_gesture_info->pt[0].y - p_gesture_info->pt[1].y;
+ if (x_delta < 0)
+ x_delta = -x_delta;
+ if (y_delta < 0)
+ y_delta = -y_delta;
+ x_delta++;
+ y_delta++;
+ area = x_delta * y_delta;
+ p_gesture_info->dir = PINCH_KEEP;
+ area_diff = area - pre_area;
+ if (area_diff > 0) {
+ if (area_diff > THRESHOLD_PINCH) {
+ p_gesture_info->dir = PINCH_OUT;
+ if (area_diff < THRESHOLD_PINCH_SPEED)
+ p_gesture_info->speed = LOWSPEED;
+ else
+ p_gesture_info->speed = HIGHSPEED;
+ }
+ } else if (area_diff < 0) {
+ if ((pre_area - area) > THRESHOLD_PINCH) {
+ p_gesture_info->dir = PINCH_IN;
+ if ((pre_area - area) < THRESHOLD_PINCH_SPEED)
+ p_gesture_info->speed = LOWSPEED;
+ else
+ p_gesture_info->speed = HIGHSPEED;
+ }
+ }
+ if (data->pinch_start == false) {
+ p_gesture_info->dir = PINCH_KEEP;
+ pre_area = 0;
+ data->pinch_start = true;
+ }
+ p_gesture_info->gesture_kind = GES_PINCH;
+ pre_area = area;
+}
+/**
+ * bu21013_update_ges_no_touch(): Generate the gesture message for no touch
+ * @data: a pointer to the device structure
+ * Generate the gesture message for no touch.
+ */
+void bu21013_update_ges_no_touch(struct bu21013_ts_data *data)
+{
+ struct bu21013_gesture_info *p_gesture_info = &data->gesture_info;
+ signed short x_delta, y_delta;
+ bool flick_series_flag;
+ signed short i;
+ unsigned char dir_left_right, dir_up_down;
+ static struct bu21013_touch_point pre_gesture_point;
+
+ flick_series_flag = false;
+ if (data->flick_flag) {
+ x_delta = p_gesture_info->pt[0].x - data->tap_start_point.x;
+ y_delta = p_gesture_info->pt[0].y - data->tap_start_point.y;
+ dir_left_right = DIR_RIGHT;
+ dir_up_down = DIR_DOWN;
+ if (x_delta < 0) {
+ dir_left_right = DIR_LEFT;
+ x_delta = -x_delta;
+ }
+ if (y_delta < 0) {
+ y_delta = -y_delta;
+ dir_up_down = DIR_UP;
+ }
+ if ((THRESHOLD_FLICK <= x_delta) || (THRESHOLD_FLICK <= y_delta)) {
+ if (THRESHOLD_DRAGDROP <= data->touch_count) {
+ p_gesture_info->gesture_kind = GES_DRAGDROP;
+ p_gesture_info->speed = data->touch_count;
+ p_gesture_info->pt[0].x = data->tap_start_point.x;
+ p_gesture_info->pt[0].y = data->tap_start_point.y;
+ p_gesture_info->pt[1].x = pre_gesture_point.x;
+ p_gesture_info->pt[1].y = pre_gesture_point.y;
+ } else {
+ p_gesture_info->speed = LOWSPEED;
+ p_gesture_info->gesture_kind = GES_FLICK;
+ p_gesture_info->dir = dir_up_down;
+ if ((THRESHOLD_FLICK_SPEED < x_delta) ||
+ (THRESHOLD_FLICK_SPEED < y_delta))
+ p_gesture_info->speed = HIGHSPEED;
+ if (x_delta > y_delta)
+ p_gesture_info->dir = dir_left_right;
+ }
+ data->pre_tap_flag_level = 0;
+ data->flick_flag = false;
+ data->touch_count = STOP;
+ flick_series_flag = true;
+ }
+ }
+ if (flick_series_flag == false) {
+ if (THRESHOLD_TAPLIMIT <= data->touch_count) {
+ p_gesture_info->gesture_kind = GES_TAP;
+ p_gesture_info->times = data->pre_tap_flag_level;
+ p_gesture_info->speed = data->touch_count;
+ data->pre_tap_flag_level = 0;
+ data->flick_flag = false;
+ data->touch_count = STOP;
+ data->dir_idx = DIRHEADER;
+ for (i = 0; i < DIRHEADER; i++)
+ data->dir_trace[i] = 0x0;
+ for (i = DIRHEADER; i < DIRTRACEN; i++)
+ data->dir_trace[i] = DIR_TRACE_VALUE;
+ }
+ }
+}
+/**
+ * bu21013_get_touch_mesg(): Generate the gesture message
+ * @data: a pointer to the device structure
+ * Generate the gesture message according to the
+ * information collected and returns integer.
+ */
+int bu21013_get_touch_mesg(struct bu21013_ts_data *data)
+{
+ struct bu21013_gesture_info *p_gesture_info = &data->gesture_info;
+ static struct bu21013_touch_point pre_gesture_point;
+ p_gesture_info->gesture_kind = GES_UNKNOWN;
+
+ bu21013_get_touch(data);
+ if (!data->touchflag) {
+ if (data->touch_continue) {
+ data->touch_continue = false;
+ p_gesture_info->gesture_kind = GES_TOUCHEND;
+ if (data->pre_tap_flag_level <= 2)
+ data->pre_tap_flag_level++;
+ data->pre_tap_flag = false;
+ } else {
+ if (!data->pinch_start) {
+ bu21013_update_ges_no_touch(data);
+ } else {
+ data->pinch_start = false;
+ data->pre_tap_flag_level = 0;
+ data->flick_flag = false;
+ data->touch_count = STOP;
+ }
+ }
+ } else {
+ p_gesture_info->pt[0].x = data->x1;
+ p_gesture_info->pt[0].y = data->y1;
+ p_gesture_info->pt[1].x = data->x2;
+ p_gesture_info->pt[1].y = data->y2;
+ bu21013_touch_calc(data);
+
+ if (data->touch_continue) {
+ if ((data->x2 != 0) && (data->y2 != 0))
+ bu21013_update_ges_mt_touch(data);
+ else
+ bu21013_update_ges_st_touch(data);
+ data->flick_flag = true;
+ } else {
+ p_gesture_info->gesture_kind = GES_TOUCHSTART;
+ data->tap_start_point.x = p_gesture_info->pt[0].x;
+ data->tap_start_point.y = p_gesture_info->pt[0].y;
+ data->touch_count = START;
+ }
+ data->touch_continue = true;
+ pre_gesture_point.x = p_gesture_info->pt[0].x;
+ pre_gesture_point.y = p_gesture_info->pt[0].y;
+ }
+ return 0;
+}
+
+/**
+ * bu21013_timer_start() - restart the timer
+ * @data:bu21013_ts_data structure pointer
+ *
+ * This funtion used to run the timer and returns none.
+ */
+static inline void bu21013_timer_start(struct bu21013_ts_data *data)
+{
+ mod_timer(&data->penirq_timer, jiffies + msecs_to_jiffies(data->penup_timer));
+}
+
+/**
+ * tsc_clear_irq() - clear the tsc interrupt
+ * @i2c:i2c_client structure pointer
+ *
+ * This funtion used to clear the
+ * bu21013 controller interrupt for next Pen interrupts and returns none.
+ */
+static void tsc_clear_irq(struct i2c_client *i2c)
+{
+ int retval;
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_CLR,
+ BU21013_INTR_CLEAR);
+ if (retval < 0)
+ dev_err(&i2c->dev, "int cleared failed \n");
+}
+
+/**
+ * tsc_en_irq() - Reactivate the tsc interrupt
+ * @i2c:i2c_client structure pointer
+ *
+ * This funtion used to activate the bu21013 controller
+ * interrupt for next Pen interrupts.
+ */
+static void tsc_en_irq(struct i2c_client *i2c)
+{
+ int retval;
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_CLR,
+ BU21013_INTR_ENABLE);
+ if (retval < 0)
+ dev_err(&i2c->dev, "interrupt enable failed\n");
+}
+/**
+ * tsc_input_report_pen_down() - report the touch point
+ * @data:bu21013_ts_data structure pointer
+ * This funtion calls, when we need to report the Pen down interrupt
+ */
+static void tsc_input_report_pen_down(struct bu21013_ts_data *data)
+{
+ short pt0x;
+ short pt0y;
+ short pt1x;
+ short pt1y;
+ if (data->chip->portrait) {
+ pt0x = data->gesture_info.pt[0].x;
+ pt0y = data->gesture_info.pt[0].y;
+ pt1x = data->gesture_info.pt[1].x;
+ pt1y = data->gesture_info.pt[1].y;
+ } else {
+ pt0x = data->gesture_info.pt[0].y;
+ pt0y = data->gesture_info.pt[0].x;
+ pt1x = data->gesture_info.pt[1].y;
+ pt1y = data->gesture_info.pt[1].x;
+ }
+
+ input_report_abs(data->pin_dev, ABS_X, pt0x);
+ input_report_abs(data->pin_dev, ABS_Y, pt0y);
+
+ input_report_abs(data->pin_dev, ABS_PRESSURE, 1);
+ input_report_abs(data->pin_dev, ABS_TOOL_WIDTH, 1);
+ input_report_key(data->pin_dev, BTN_TOUCH, 1);
+
+ if (data->finger2_pressed) {
+ input_report_key(data->pin_dev, BTN_2, 1);
+ input_report_abs(data->pin_dev, ABS_HAT0X, pt1x);
+ input_report_abs(data->pin_dev, ABS_HAT0Y, pt1y);
+ }
+ input_report_abs(data->pin_dev, ABS_MT_TOUCH_MAJOR, 1);
+ input_report_key(data->pin_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_report_abs(data->pin_dev, ABS_MT_POSITION_X, pt0x);
+ input_report_abs(data->pin_dev, ABS_MT_POSITION_Y, pt0y);
+ input_mt_sync(data->pin_dev);
+ if (data->finger2_pressed) {
+ input_report_abs(data->pin_dev, ABS_MT_TOUCH_MAJOR, 1);
+ input_report_key(data->pin_dev, ABS_MT_WIDTH_MAJOR, 1);
+ input_report_abs(data->pin_dev, ABS_MT_POSITION_X, pt1x);
+ input_report_abs(data->pin_dev, ABS_MT_POSITION_Y, pt1y);
+ input_mt_sync(data->pin_dev);
+ }
+ input_sync(data->pin_dev);
+}
+/**
+ * tsc_input_report_pen_up() - report the touch point
+ * @data:bu21013_ts_data structure pointer
+ * This funtion calls, when we need to report the Pen up interrupt
+ */
+static void tsc_input_report_pen_up(struct bu21013_ts_data *data)
+{
+ input_report_abs(data->pin_dev, ABS_PRESSURE, 0);
+ input_report_abs(data->pin_dev, ABS_TOOL_WIDTH, 0);
+ input_report_key(data->pin_dev, BTN_TOUCH, 0);
+ if (data->finger2_count) {
+ input_report_key(data->pin_dev, BTN_2, 0);
+ input_report_abs(data->pin_dev, ABS_MT_TOUCH_MAJOR, 0);
+ input_report_key(data->pin_dev, ABS_MT_WIDTH_MAJOR, 0);
+ input_mt_sync(data->pin_dev);
+ data->finger2_count = 0;
+ }
+ input_sync(data->pin_dev);
+}
+/**
+ * tsc_input_report() - report the touch point
+ * @data:bu21013_ts_data structure pointer
+ * @value:value to be passed for en down or pen up
+ * This funtion calls, when we need to report the Pen down/up interrupt
+ */
+static void tsc_input_report(struct bu21013_ts_data *data, bool value)
+{
+ if (value)
+ tsc_input_report_pen_down(data);
+ else
+ tsc_input_report_pen_up(data);
+}
+
+/**
+ * tsc_callback() - callback handler for Pen down
+ * @device_data:void pointer
+ *
+ * This funtion calls, when we get the Pen down interrupt from Egpio Pin
+ * and assigns the task and returns none.
+ */
+
+static void tsc_callback(void *device_data)
+{
+ struct bu21013_ts_data *data = (struct bu21013_ts_data *)device_data;
+ schedule_work(&data->tp_gpio_handler);
+}
+
+/**
+ * tsc_gpio_callback() - callback handler for Pen down
+ * @device_data:void pointer
+ * @irq: irq value
+ *
+ * This funtion calls for HREF v1, when we get the Pen down interrupt from GPIO Pin
+ * and assigns the task and returns irqreturn_t.
+ */
+
+static irqreturn_t tsc_gpio_callback(int irq, void *device_data)
+{
+ struct bu21013_ts_data *data = (struct bu21013_ts_data *)device_data;
+ schedule_work(&data->tp_gpio_handler);
+ return IRQ_HANDLED;
+}
+
+/**
+ * tsc_timer_callback() - callback handler for Timer
+ * @dev_data:touch screen data
+ *
+ * This callback handler used to schedule the work for Pen up
+ * and Pen down interrupts and returns none
+ */
+static void tsc_timer_callback(unsigned long dev_data)
+{
+ struct bu21013_ts_data *data = (struct bu21013_ts_data *)dev_data;
+ schedule_work(&data->tp_timer_handler);
+}
+/**
+ * tsc_level_mode_report() - report the touch point in level mode
+ * @data:bu21013_ts_data structure pointer
+ * This funtion used to report the Pen down/up interrupt for level mode.
+ */
+static void tsc_level_mode_report(struct bu21013_ts_data *data)
+{
+ if (data->touch_en) {
+ data->prev_press_report = true;
+ tsc_input_report(data, true);
+ } else {
+ if (data->prev_press_report) {
+ data->prev_press_report = false;
+ tsc_input_report(data, false);
+ }
+ }
+}
+/**
+ * tp_timer_wq() - Work Queue for timer handler
+ * @work:work_struct structure pointer
+ *
+ * This work queue used to get the co-ordinates
+ * of the Pen up and Pen down interrupts and returns none
+ */
+static void tp_timer_wq(struct work_struct *work)
+{
+ struct bu21013_ts_data *data = container_of(work, struct bu21013_ts_data, tp_timer_handler);
+ struct task_struct *tsk = current;
+
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ data->intr_pin = data->chip->pirq_read_val();
+ bu21013_get_touch_mesg(data);
+
+ if (data->chip->edge_mode)
+ tsc_input_report(data, data->touch_en);
+ else
+ tsc_level_mode_report(data);
+
+ if (data->intr_pin == PEN_DOWN_INTR) {
+ bu21013_timer_start(data);
+ } else {
+ if (!data->chip->edge_mode) {
+ tsc_clear_irq(data->client);
+ tsc_en_irq(data->client);
+ }
+ enable_irq(data->chip->irq);
+ }
+}
+
+/**
+ * tp_gpio_int_wq() - Work Queue for GPIO_INT handler
+ * @work:work_struct structure pointer
+ *
+ * This work queue used to get the co-ordinates
+ * of the Pen up and Pen down interrupts and returns none
+ */
+static void tp_gpio_int_wq(struct work_struct *work)
+{
+ struct bu21013_ts_data *tp_data = container_of(work, struct bu21013_ts_data, tp_gpio_handler);
+ struct task_struct *tsk = current;
+
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ tp_data->intr_pin = tp_data->chip->pirq_read_val();
+ if (tp_data->intr_pin == PEN_DOWN_INTR) {
+ disable_irq(tp_data->chip->irq);
+ bu21013_get_touch_mesg(tp_data);
+ if (tp_data->chip->edge_mode)
+ tsc_input_report(tp_data, tp_data->touch_en);
+ else
+ tsc_level_mode_report(tp_data);
+ if (!tp_data->chip->edge_mode) {
+ tsc_clear_irq(tp_data->client);
+ tsc_en_irq(tp_data->client);
+ }
+ bu21013_timer_start(tp_data);
+ } else {
+ if (tp_data->chip->edge_mode) {
+ tsc_input_report(tp_data, false);
+ } else if (tp_data->prev_press_report) {
+ tp_data->prev_press_report = false;
+ tsc_input_report(tp_data, false);
+ }
+ }
+}
+
+/*
+ * bu21013_init_config(): Initialize the Global variables
+ * @data: device structure pointer
+ * This function used to initialize the device variables and returns none
+ */
+void bu21013_init_config(struct bu21013_ts_data *data)
+{
+ signed int i;
+
+ data->touch_count = STOP;
+ /* turning right */
+ data->rotate_data[DIR_UP][DIR_RIGHT] = ROTATE_R_UR;
+ data->rotate_data[DIR_RIGHT][DIR_DOWN] = ROTATE_R_RD;
+ data->rotate_data[DIR_DOWN][DIR_LEFT] = ROTATE_R_DL;
+ data->rotate_data[DIR_LEFT][DIR_UP] = ROTATE_R_LU;
+
+ /* turning left */
+ data->rotate_data[DIR_LEFT][DIR_DOWN] = ROTATE_L_LD;
+ data->rotate_data[DIR_RIGHT][DIR_UP] = ROTATE_L_DR;
+ data->rotate_data[DIR_DOWN][DIR_RIGHT] = ROTATE_L_RU;
+ data->rotate_data[DIR_UP][DIR_LEFT] = ROTATE_L_UL;
+
+ data->dir_idx = DIRHEADER;
+
+ for (i = DIRHEADER; i < DIRTRACEN; i++)
+ data->dir_trace[i] = DIR_TRACE_VALUE;
+
+ return;
+}
+/**
+ * bu21013_init_chip() - Power on sequence for the bu21013 controller
+ * @data: device structure pointer
+ *
+ * This funtion is used to power on
+ * the bu21013 controller and returns integer.
+ **/
+static int bu21013_init_chip(struct bu21013_ts_data *data)
+{
+ int retval;
+ struct i2c_client *i2c = data->client;
+
+ dev_dbg(&i2c->dev, "bu21013_init_chip start\n");
+
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_RESET,
+ BU21013_RESET_ENABLE);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "ED reg write failed\n");
+ goto err;
+ }
+ mdelay(RESET_DELAY);
+
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7,
+ BU21013_SENSORS_EN_0_7);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F0 reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15,
+ BU21013_SENSORS_EN_8_15);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F1 reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23,
+ BU21013_SENSORS_EN_16_23);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F2 reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1,
+ (BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F3 reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2,
+ (BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 | BU21013_POS_MODE2_AVG2 |
+ BU21013_POS_MODE2_EN_RAW | BU21013_POS_MODE2_MULTI));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F4 reg write failed\n");
+ goto err;
+ }
+ if (data->chip->ext_clk) {
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE,
+ (BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F5 reg write failed\n");
+ goto err;
+ }
+ } else {
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE,
+ (BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "F5 reg write failed\n");
+ goto err;
+ }
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE,
+ (BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "FA reg write failed\n");
+ goto err;
+ }
+ if (data->chip->edge_mode) {
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE,
+ BU21013_INT_MODE_EDGE);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "E9 reg write failed\n");
+ goto err;
+ }
+ } else {
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE,
+ BU21013_INT_MODE_LEVEL);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "E9 reg write failed\n");
+ goto err;
+ }
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER,
+ (BU21013_DELTA_0_6 | BU21013_FILTER_EN));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "FB reg write failed\n");
+ goto err;
+ }
+
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON, data->th_on);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "FC reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF, data->th_off);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "FD reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN, data->gain);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "EA reg write failed\n");
+ goto err;
+ }
+
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE,
+ BU21013_OFFSET_MODE_DEFAULT);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "EB reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE,
+ (BU21013_X_EDGE_0 | BU21013_X_EDGE_2 |
+ BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3));
+ if (retval < 0) {
+ dev_err(&i2c->dev, "EC reg write failed\n");
+ goto err;
+ }
+ retval = i2c_smbus_write_byte_data(i2c, BU21013_REG_DONE, BU21013_DONE);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "EF reg write failed\n");
+ goto err;
+ }
+err:
+ return retval;
+}
+/*
+ * tsc_driver_register() - Used for input driver registeration
+ * @pdata: pointer to bu21013_tsc_data structure
+ * This function used to register the
+ * touch screen as input device and returns integer
+ */
+static int tsc_driver_register(struct bu21013_ts_data *pdata)
+{
+ int ret;
+ short x_max;
+ short y_max;
+
+ struct input_dev *in_dev;
+ struct i2c_client *i2c = pdata->client;
+ dev_dbg(&i2c->dev, "input register start\n");
+
+ /* register the touch screen driver to input device */
+ if (pdata->chip->portrait) {
+ x_max = pdata->chip->x_max_res;
+ y_max = pdata->chip->y_max_res;
+ } else {
+ x_max = pdata->chip->y_max_res;
+ y_max = pdata->chip->x_max_res;
+ }
+ in_dev = input_allocate_device();
+ pdata->pin_dev = in_dev;
+ if (!in_dev) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ in_dev->name = DRIVER_TP;
+ set_bit(EV_SYN, in_dev->evbit);
+ set_bit(EV_KEY, in_dev->evbit);
+ set_bit(EV_ABS, in_dev->evbit);
+ set_bit(BTN_TOUCH, in_dev->keybit);
+ input_set_abs_params(in_dev, ABS_X, 0, x_max, 0, 0);
+ input_set_abs_params(in_dev, ABS_Y, 0, y_max, 0, 0);
+ input_set_abs_params(in_dev, ABS_PRESSURE, 0, MAX_PRESSURE, 0, 0);
+ input_set_abs_params(in_dev, ABS_TOOL_WIDTH, 0, MAX_TOOL_WIDTH, 0, 0);
+ set_bit(BTN_2, in_dev->keybit);
+ input_set_abs_params(in_dev, ABS_HAT0X, 0, x_max, 0, 0);
+ input_set_abs_params(in_dev, ABS_HAT0Y, 0, y_max, 0, 0);
+ input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, x_max, 0, 0);
+ input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, y_max, 0, 0);
+ input_set_abs_params(in_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
+ input_set_abs_params(in_dev, ABS_MT_WIDTH_MAJOR, 0, MAX_TOOL_WIDTH, 0, 0);
+ ret = input_register_device(in_dev);
+ if (ret) {
+ dev_err(&i2c->dev, " input register error \n");
+ goto err;
+ }
+ dev_dbg(&i2c->dev, "input register done \n");
+err:
+ return ret;
+}
+/**
+ * tsc_config() - configure the touch screen controller
+ * @pdev_data: pointer to bu21013_ts_data structure
+ *
+ * This funtion is used to configure
+ * the bu21013 controller and returns tsc error.
+ **/
+static int tsc_config(struct bu21013_ts_data *pdev_data)
+{
+ int retval;
+
+ retval = bu21013_init_chip(pdev_data);
+ if (retval < 0)
+ goto err;
+
+ bu21013_init_config(pdev_data);
+ if ((!pdev_data->board_flag) &&
+ ((pdev_data->chip->pirq_en) && (pdev_data->chip->pirq_dis) &&
+ (pdev_data->chip->irq_init))) {
+ retval = pdev_data->chip->pirq_dis();
+ if (retval < 0) {
+ dev_err(&pdev_data->client->dev, "irq dis failed \n");
+ goto err;
+ }
+ retval = pdev_data->chip->pirq_en();
+ if (retval < 0) {
+ dev_err(&pdev_data->client->dev, "irq en failed \n");
+ goto err_init_irq;
+ }
+ if (pdev_data->chip->irq_init(tsc_callback, pdev_data)) {
+ dev_err(&pdev_data->client->dev, "irq init failed \n");
+ goto err_init_irq;
+ }
+ }
+ retval = bu21013_do_calibrate(pdev_data->client);
+ if (retval < 0) {
+ dev_err(&pdev_data->client->dev, "calibration not done \n");
+ goto err_init_irq;
+ }
+ return retval;
+err_init_irq:
+ pdev_data->chip->pirq_dis();
+ pdev_data->chip->irq_exit();
+err:
+ pdev_data->chip->cs_dis(pdev_data->chip->cs_pin);
+ return retval;
+}
+#ifdef CONFIG_PM
+/**
+ * bu21013_tp_suspend() - suspend the touch screen controller
+ * @client: pointer to i2c client structure
+ * @mesg: message from power manager
+ *
+ * This funtion is used to suspend the
+ * touch panel controller and returns integer
+ **/
+static int bu21013_tp_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int retval;
+ struct bu21013_ts_data *tsc_data = i2c_get_clientdata(client);
+
+ if (!tsc_data->board_flag) {
+ retval = tsc_data->chip->pirq_dis();
+ if (retval < 0) {
+ dev_err(&client->dev, "irq disable failed \n");
+ goto err;
+ }
+ retval = tsc_data->chip->irq_exit();
+ if (retval < 0) {
+ dev_err(&client->dev, "irq exit failed \n");
+ goto err;
+ }
+ } else
+ disable_irq(tsc_data->chip->irq);
+ return 0;
+err:
+ kfree(tsc_data);
+ return retval;
+}
+
+/**
+ * bu21013_tp_resume() - resume the touch screen controller
+ * @client: pointer to i2c client structure
+ *
+ * This funtion is used to resume the touch panel
+ * controller and returns integer.
+ **/
+static int bu21013_tp_resume(struct i2c_client *client)
+{
+ int retval;
+ struct bu21013_ts_data *tsc_data = i2c_get_clientdata(client);
+
+ retval = tsc_config(tsc_data);
+ if (retval < 0) {
+ dev_err(&client->dev, "tsc config failed \n");
+ goto err;
+ }
+ if (tsc_data->board_flag)
+ enable_irq(tsc_data->chip->irq);
+ return 0;
+err:
+ kfree(tsc_data);
+ return retval;
+}
+#endif
+/**
+ * bu21013_tp_sysfs() - sys fs parameters
+ * @tp_kobj: kernel object structure pointer
+ *
+ * This funtion uses to initialize the sysfs for touch panel
+ **/
+int bu21013_tp_sysfs(struct kobject *tp_kobj)
+{
+ int retval;
+ tp_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+ if (tp_kobj == NULL) {
+ retval = -ENOMEM;
+ goto err;
+ }
+ tp_kobj->ktype = &ktype_touchp;
+ kobject_init(tp_kobj, tp_kobj->ktype);
+ retval = kobject_set_name(tp_kobj, "touchp1");
+ if (retval) {
+ kfree(tp_kobj);
+ goto err;
+ }
+ retval = kobject_add(tp_kobj, NULL, "touchp1");
+ if (retval) {
+ kfree(tp_kobj);
+ goto err;
+ }
+ return 0;
+err:
+ return retval;
+}
+/**
+ * bu21013_tp_probe() - Initialze the i2c-client touchscreen driver
+ * @i2c: i2c client structure pointer
+ * @id:i2c device id pointer
+ *
+ * This funtion uses to Initializes the i2c-client touchscreen
+ * driver and returns integer.
+ **/
+static int bu21013_tp_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+ int retval;
+ struct bu21013_ts_data *tsc_data;
+ struct bu21013_platform_device *pdata = i2c->dev.platform_data;
+ dev_dbg(&i2c->dev, "u8500_tsc_probe:: start\n");
+
+ tsc_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL);
+ if (!tsc_data) {
+ dev_err(&i2c->dev, "tp memory alloc failed \n");
+ retval = -ENOMEM;
+ return retval;
+ }
+ if (!pdata) {
+ dev_err(&i2c->dev, "tp platform data not defined \n");
+ retval = -EINVAL;
+ goto err_alloc;
+ }
+ tsc_data->chip = pdata;
+ tsc_data->client = i2c;
+ /*
+ * Hack for dynamic detection of HREF v1 board
+ */
+ tsc_data->board_flag = tsc_data->chip->board_check();
+ /*
+ * Hack for not supporting touch panel controller2
+ * for the ED and MOP500 v1 boards, due to no support
+ * of shared irq callback registeration in tc35892
+ * and stmpe2401 driver.
+ */
+ if ((!tsc_data->chip->tp_cntl) ||
+ ((tsc_data->chip->tp_cntl == 2) &&
+ (!tsc_data->board_flag))) {
+ dev_err(&i2c->dev, "tp is not supported \n");
+ retval = -EINVAL;
+ goto err_alloc;
+ }
+ /*
+ * Hardcoded for portrait mode
+ */
+ tsc_data->chip->portrait = true;
+ INIT_WORK(&tsc_data->tp_timer_handler, tp_timer_wq);
+ INIT_WORK(&tsc_data->tp_gpio_handler, tp_gpio_int_wq);
+
+ init_timer(&tsc_data->penirq_timer);
+ tsc_data->penirq_timer.data = (unsigned long)tsc_data;
+ tsc_data->penirq_timer.function = tsc_timer_callback;
+ i2c_set_clientdata(i2c, tsc_data);
+ /* configure the gpio pins */
+ if (tsc_data->chip->cs_en) {
+ retval = tsc_data->chip->cs_en(tsc_data->chip->cs_pin);
+ if (retval != 0) {
+ dev_err(&i2c->dev, "error in chip initialization\n");
+ goto err;
+ }
+ }
+ /* sys_fs value configuration */
+ tsc_data->th_on = BU21013_TH_ON_5;
+ tsc_data->th_off = (BU21013_TH_OFF_3 | BU21013_TH_OFF_4);
+ tsc_data->gain = (BU21013_GAIN_0 | BU21013_GAIN_1);
+ tsc_data->penup_timer = PENUP_TIMEOUT;
+
+ /* configure the touch panel controller */
+ retval = tsc_config(tsc_data);
+ if (retval < 0) {
+ dev_err(&i2c->dev, "error in tp config\n");
+ goto err;
+ }
+ if (tsc_data->board_flag) {
+ retval = request_irq(tsc_data->chip->irq, tsc_gpio_callback,
+ (IRQF_TRIGGER_FALLING | IRQF_SHARED), DRIVER_TP, tsc_data);
+ if (retval) {
+ dev_err(&i2c->dev, "request irq %d failed\n", tsc_data->chip->irq);
+ free_irq(tsc_data->chip->irq, tsc_data);
+ goto err;
+ }
+ }
+ retval = tsc_driver_register(tsc_data);
+ if (retval)
+ goto err_init;
+ if (tsc_data->chip->tp_cntl != 2) {
+ retval = bu21013_tp_sysfs(&tsc_data->touchp_kobj);
+ if (retval)
+ goto err_init;
+ else
+ tp_sys_data = tsc_data;
+ }
+ dev_dbg(&i2c->dev, "u8500_tsc_probe : done \n");
+ return retval;
+err_init:
+ input_free_device(tsc_data->pin_dev);
+err:
+ del_timer_sync(&tsc_data->penirq_timer);
+err_alloc:
+ kfree(tsc_data);
+ return retval;
+}
+/**
+ * bu21013_tp_remove() - Removes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ *
+ * This funtion uses to remove the i2c-client
+ * touchscreen driver and returns integer.
+ **/
+static int __exit bu21013_tp_remove(struct i2c_client *client)
+{
+ struct bu21013_ts_data *data = i2c_get_clientdata(client);
+ del_timer_sync(&data->penirq_timer);
+
+ if (data->chip != NULL) {
+ if (!data->board_flag) {
+ data->chip->irq_exit();
+ data->chip->pirq_dis();
+ } else
+ free_irq(data->chip->irq, data);
+ data->chip->cs_dis(data->chip->cs_pin);
+ }
+ kfree(&data->touchp_kobj);
+ input_unregister_device(data->pin_dev);
+ input_free_device(data->pin_dev);
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
+ return 0;
+}
+
+static const struct i2c_device_id bu21013_tp_id[] = {
+ { DRIVER_TP, 0 },
+ { DRIVER_TP, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, bu21013_tp_id);
+
+static struct i2c_driver bu21013_tp_driver = {
+ .driver = {
+ .name = DRIVER_TP,
+ .owner = THIS_MODULE,
+ },
+ .probe = bu21013_tp_probe,
+#ifdef CONFIG_PM
+ .suspend = bu21013_tp_suspend,
+ .resume = bu21013_tp_resume,
+#endif
+ .remove = __exit_p(bu21013_tp_remove),
+ .id_table = bu21013_tp_id,
+};
+
+/**
+ * bu21013_tp_init() - Initialize the paltform touchscreen driver
+ *
+ * This funtion uses to initialize the platform
+ * touchscreen driver and returns integer.
+ **/
+static int __init bu21013_tp_init(void){
+ return i2c_add_driver(&bu21013_tp_driver);
+}
+
+/**
+ * bu21013_tp_exit() - De-initialize the paltform touchscreen driver
+ *
+ * This funtion uses to de-initialize the platform
+ * touchscreen driver and returns none.
+ **/
+static void __exit bu21013_tp_exit(void){
+ i2c_del_driver(&bu21013_tp_driver);
+}
+
+module_init(bu21013_tp_init);
+module_exit(bu21013_tp_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("NAVEEN KUMAR G");
+MODULE_DESCRIPTION("Touch Screen driver for Bu21013 controller");
diff --git a/drivers/input/touchscreen/u8500_tsc.c b/drivers/input/touchscreen/u8500_tsc.c
deleted file mode 100644
index 3aef1ea873b..00000000000
--- a/drivers/input/touchscreen/u8500_tsc.c
+++ /dev/null
@@ -1,1474 +0,0 @@
-/*
- * Overview:
- * Touch panel driver for u8500 platform
- *
- * Copyright (C) 2009 ST-Ericsson SA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/platform_device.h>
-#include <linux/poll.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <linux/workqueue.h>
-#include <linux/input.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/types.h>
-#include <mach/debug.h>
-#include <mach/u8500_tsc.h>
-#include <linux/timer.h>
-
-static void tsc_timer_wq(struct work_struct *_chip);
-static void tp_gpio_int_wq(struct work_struct *_chip);
-
-static struct i2c_driver tp_driver;
-static tsc_error tsc_write_byte(struct i2c_client *i2c, u8 reg,
- unsigned char data);
-static tsc_error bu21013_tsc_init(struct i2c_client *i2c);
-static tsc_error tsc_config(struct u8500_tsc_data *pdev_data);
-static void tsc_clear_irq(struct i2c_client *i2c);
-static void tsc_en_irq(struct i2c_client *i2c);
-static void tsc_callback(void *tsc);
-static irqreturn_t tsc_gpio_callback(int irq, void *device_data);
-static int tsc_driver_register(struct u8500_tsc_data *pdata);
-static void tsc_timer_callback(unsigned long data);
-#ifdef CONFIG_U8500_TSC_EXT_CLK_9_6
-static tsc_error tsc_read_byte(struct i2c_client *i2c, u8 reg, unsigned char *val);
-#endif
-
-#if (defined CONFIG_CPU_IDLE || defined CONFIG_TOUCHP_TUNING)
-static u8 th_on = TSC_TH_ON_VAL; /* 0x20; */
-static u8 th_off = TSC_TH_OFF_VAL; /* 0x18; */
-#endif
-#ifdef CONFIG_TOUCHP_TUNING
-unsigned long penup_timer = PENUP_TIMEOUT;
-unsigned long g_tool_width = 1;
-static struct kobject *touchp_kobj;
-struct u8500_tsc_data *pdev_data;
-static ssize_t touchp_attr_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- u8 timeout = 0;
- u8 sys_th_on = 0;
- u8 sys_th_off = 0;
-
- if (strcmp(attr->name, "timeout_value") == 0) {
- timeout = penup_timer;
- sprintf(buf, "%d\n", timeout);
- } else if (strcmp(attr->name, "th_on") == 0) {
- sys_th_on = th_on;
- sprintf(buf, "%d\n", sys_th_on);
- } else if (strcmp(attr->name, "th_off") == 0) {
- sys_th_off = th_off;
- sprintf(buf, "%d\n", sys_th_off);
- }
- return strlen(buf);
-}
-static ssize_t touchp_attr_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t len)
-{
- int ret = 0;
- int timeout = 0;
- int sys_th_on = 0;
- int sys_th_off = 0;
-
- if (strcmp(attr->name, "timeout_value") == 0) {
- ret = sscanf(buf, "%d", &timeout);
- if (ret == 1)
- penup_timer = timeout;
- } else if (strcmp(attr->name, "th_on") == 0) {
- ret = sscanf(buf, "%d", &sys_th_on);
- if ((ret == 1) && (th_on != sys_th_on)) {
- th_on = sys_th_on;
- if (th_on < 0xFF)
- bu21013_tsc_init(pdev_data->client);
- }
- } else if (strcmp(attr->name, "th_off") == 0) {
- ret = sscanf(buf, "%d", &sys_th_off);
- if ((ret == 1) && (th_off != sys_th_off)) {
- th_off = sys_th_off;
- if (th_off < 0xFF)
- bu21013_tsc_init(pdev_data->client);
- }
- }
- return ret == 1 ? len : -EINVAL;
-}
-
-static struct attribute touchp_timeout = {.name = "timeout_value",
- .mode = 0666};
-static struct attribute touchp_th_on = {.name = "th_on", .mode = 0666};
-static struct attribute touchp_th_off = {.name = "th_off", .mode = 0666};
-
-static struct attribute *touchp_attribute[] = {
- &touchp_timeout,
- &touchp_th_on,
- &touchp_th_off,
- NULL
-};
-
-static struct sysfs_ops touchp_sysfs_ops = {
- .show = touchp_attr_show,
- .store = touchp_attr_store,
-};
-
-static struct kobj_type ktype_touchp = {
- .sysfs_ops = &touchp_sysfs_ops,
- .default_attrs = touchp_attribute,
-};
-#endif
-/**
- * tsc_write_byte() - Write a single byte to touch screen.
- * @i2c:i2c client structure
- * @reg:register offset
- * @value:data byte to be written
- *
- * This funtion uses smbus byte write API
- * to write a single byte to touch screen and returns tsc error.
- */
-static tsc_error tsc_write_byte(struct i2c_client *i2c, u8 reg,
- unsigned char value)
-{
- int retval = TSC_OK;
- retval = i2c_smbus_write_byte_data(i2c, reg, value);
- if (retval < 0)
- dev_err(&i2c->dev,
- "tsc_write_byte:: i2c smbus write byte failed\n");
- return retval;
-}
-#ifdef CONFIG_U8500_TSC_EXT_CLK_9_6
-/**
- * tsc_read_byte() - read single byte from touch screen
- * @i2c:i2c client structure
- * @reg:register offset
- * @val:value to get from i2c register
- *
- * This funtion uses smbus read block API
- * to read single byte from the reg offset and returns tsc error.
- */
-static tsc_error tsc_read_byte(struct i2c_client *i2c, u8 reg,
- unsigned char *val)
-{
- int retval = 0;
- retval = i2c_smbus_read_byte_data(i2c, reg);
- if (retval < 0)
- return retval;
- *val = (unsigned char)retval;
- return TSC_OK;
-}
-#endif
-/**
- * tsc_read()-read data from touch panel
- * @i2c:i2c client structure pointer
- * @reg:register offset
- * @buf:read the data in this buffer
- * @nbytes:number of bytes to read
- *
- * This funtion uses smbus read block API
- * to read multiple bytes from the reg offset.
- **/
-static int tsc_read_block(struct i2c_client *i2c, u8 reg, u8 *buf, u8 nbytes)
-{
- int ret;
-
- ret = i2c_smbus_read_i2c_block_data(i2c, reg, nbytes, buf);
- if (ret < nbytes)
- return ret;
- return TSC_OK;
-}
-/**
- * tsc_read_10bit() - read 10 bit data from touch screen
- * @i2c:i2c client structure
- * @reg:register offset
- * @val:value to get from i2c register
- *
- * This funtion uses smbus read block API
- * to read 10-bit from the reg offset and returns tsc error.
- */
-static tsc_error tsc_read_10bit(struct i2c_client *i2c,
- u8 reg, unsigned int *val)
-{
- u16 data = 0;
- int retval = 0;
- u8 buf[2];
- retval = tsc_read_block(i2c, reg, buf, 2);
- if (retval < 0)
- return retval;
- data = buf[0];
- data = (data << 2) | buf[1];
- *val = data;
- return TSC_OK;
-}
-
-/**
- * touch_calculation(): Get the exact co-ordinates of the touch interrupt
- * @p_gesture_info: gesture_info structure pointer
- * Transfer the position information from touch sensor
- * coordinate to display coordinate and returns none.
- */
-void touch_calculation(struct gesture_info *p_gesture_info)
-{
- signed short x1, y1;
- int tmpx, tmpy;
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- signed short x2, y2;
-#endif
-
- tmpx = (X_MAX * 1000 / TOUCH_XMAX);
- tmpy = (Y_MAX * 1000 / TOUCH_YMAX);
-
- x1 = p_gesture_info->pt[0].x;
- y1 = p_gesture_info->pt[0].y;
-
- x1 = x1 * tmpx / 1000;
-#if (defined CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT && defined CONFIG_U8500_TSC_X_FLIP)
- x1 = X_MAX - x1;
-#endif
- p_gesture_info->pt[0].x = x1;
-
- y1 = y1 * tmpy / 1000;
-#if (defined CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT && defined CONFIG_U8500_TSC_Y_FLIP)
- y1 = Y_MAX - y1;
-#endif
- p_gesture_info->pt[0].y = y1;
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- x2 = p_gesture_info->pt[1].x;
- x2 = x2 * tmpx / 1000;
-#if (defined CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT && defined CONFIG_U8500_TSC_X_FLIP)
- x2 = X_MAX - x2;
-#endif
- p_gesture_info->pt[1].x = x2;
-
- y2 = p_gesture_info->pt[1].y;
- y2 = y2 * tmpy / 1000;
-#if (defined CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT && defined CONFIG_U8500_TSC_Y_FLIP)
- y2 = Y_MAX - y2;
-#endif
- p_gesture_info->pt[1].y = y2;
-#endif
-}
-
-/**
- * get_touch(): Get the co-ordinates of the touch interrupt
- * @data:u8500_tsc_data structure pointer
- * Get touched point position
- * from touch sensor registers and write to global variables.
- */
-void get_touch(struct u8500_tsc_data *data)
-{
- struct i2c_client *i2c = data->client;
- tsc_error retval = TSC_OK;
- u8 finger1_buf[4];
- int count;
- signed short tmp1x, tmp1y;
- u8 j, i;
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- u8 finger2_buf[4];
- signed short tmp2x, tmp2y;
-#endif
- if (i2c != NULL) {
- for (count = 0; count < 2; count++) {
- #ifdef CONFIG_U8500_TSC_EXT_CLK_9_6
- i = TSC_POS_X1;
- for (j = 0; j < 2; j++) {
- retval = tsc_read_byte(i2c, i, &finger1_buf[j]);
- if (retval < 0)
- return;
- i++;
- }
- tmp1x = finger1_buf[0];
- tmp1x = (tmp1x << 2) | finger1_buf[1];
- if (tmp1x != 0) {
- i = TSC_POS_Y1;
- for (j = 2; j < 4; j++) {
- retval = tsc_read_byte(i2c, i, &finger1_buf[j]);
- if (retval < 0)
- return;
- i++;
- }
- tmp1y = finger1_buf[2];
- tmp1y = (tmp1y << 2) | finger1_buf[3];
- } else
- tmp1y = 0;
- #else
- retval = tsc_read_block(i2c, TSC_POS_X1, finger1_buf, 4);
- if (retval != 0)
- return;
- tmp1x = finger1_buf[0];
- tmp1x = (tmp1x << 2) | finger1_buf[1];
- tmp1y = finger1_buf[2];
- tmp1y = (tmp1y << 2) | finger1_buf[3];
- #endif
- if (tmp1x != 0 && tmp1y != 0)
- break;
- }
- if (tmp1x != 0 && tmp1y != 0)
- data->finger1_pressed = TRUE;
- else
- data->finger1_pressed = FALSE;
-
- if (tmp1x > TOUCH_XMAX || tmp1y > TOUCH_YMAX)
- data->finger1_pressed = FALSE;
-
- if (data->finger1_pressed) {
- data->x1 = tmp1x;
- data->y1 = tmp1y;
- } else {
- data->x1 = 0;
- data->y1 = 0;
- data->x2 = 0;
- data->y2 = 0;
- }
-
- #ifndef CONFIG_U8500_TSC_MULTITOUCH
- if (data->finger1_pressed == TRUE) {
- data->touch_en = TRUE;
- data->touchflag = TRUE;
- } else {
- data->touch_en = FALSE;
- data->touchflag = FALSE;
- }
- #else
- for (count = 0; count < 2; count++) {
- #ifdef CONFIG_U8500_TSC_EXT_CLK_9_6
- i = TSC_POS_X2;
- for (j = 0; j < 2; j++) {
- retval = tsc_read_byte(i2c, i, &finger2_buf[j]);
- if (retval < 0)
- return;
- i++;
- }
- tmp2x = finger2_buf[0];
- tmp2x = (tmp2x << 2) | finger2_buf[1];
- if (tmp2x != 0) {
- i = TSC_POS_Y2;
- for (j = 2; j < 4; j++) {
- retval = tsc_read_byte(i2c, i, &finger2_buf[j]);
- if (retval < 0)
- return;
- i++;
- }
- tmp2y = finger2_buf[2];
- tmp2y = (tmp2y << 2) | finger2_buf[3];
- } else
- tmp2y = 0;
- #else
- retval = tsc_read_block(i2c, TSC_POS_X2, finger2_buf, 4);
- if (retval != 0)
- return;
- tmp2x = finger2_buf[0];
- tmp2x = (tmp2x << 2) | finger2_buf[1];
- tmp2y = finger2_buf[2];
- tmp2y = (tmp2y << 2) | finger2_buf[3];
- #endif
- if (tmp2x != 0 && tmp2y != 0)
- break;
- }
- if (tmp2x != 0 && tmp2y != 0)
- data->finger2_pressed = TRUE;
- else
- data->finger2_pressed = FALSE;
-
- if (tmp2x > TOUCH_XMAX || tmp2y > TOUCH_YMAX)
- data->finger2_pressed = FALSE;
- data->finger2_count = 1;
- if (data->finger2_pressed) {
- data->x2 = tmp2x;
- data->y2 = tmp2y;
- } else {
- data->x2 = 0;
- data->y2 = 0;
- }
- if ((data->finger1_pressed == TRUE)
- || (data->finger2_pressed == TRUE)) {
- data->touch_en = TRUE;
- data->touchflag = TRUE;
- } else {
- data->touch_en = FALSE;
- data->touchflag = FALSE;
- }
-
- if ((data->finger1_pressed == FALSE)
- && (data->finger2_pressed == TRUE)) {
- data->x1 = tmp2x;
- data->y1 = tmp2y;
- data->x2 = 0;
- data->y2 = 0;
- data->finger2_pressed = FALSE;
- }
- #endif
- }
-}
-
-/**
- * get_touch_message(): Generate the gesture message
- * @data: a pointer to the device structure
- * Generate the gesture message according to the
- * information collected and returns integer.
- */
-
-int get_touch_message(struct u8500_tsc_data *data)
-{
- struct gesture_info *p_gesture_info = &data->gesture_info;
- struct i2c_client *i2c = data->client;
- unsigned int ret = TRUE;
-
- unsigned char flick_series_flag = TRUE;
- signed short x_delta, y_delta;
- unsigned char dir_left_right, dir_up_down;
- unsigned char tmp;
- signed short i;
- unsigned char dir1, dir2;
-
- static struct touch_point pre_gesture_point;
-
- unsigned long area;
- static unsigned long pre_area;
-
- p_gesture_info->gesture_kind = GES_UNKNOWN;
-
- if (i2c == NULL)
- return -1;
-
- get_touch(data);
-
- if (data->touchflag == FALSE) {
- if (data->touch_continue) {
- data->touch_continue = FALSE;
-
- /* touch end message */
- p_gesture_info->gesture_kind = GES_TOUCHEND;
-
- /* tap flag less than 2 */
- if (data->pre_tap_flag_level <= 2)
- data->pre_tap_flag_level++;
-
- data->pre_tap_flag = CLR;
- } else {
- if (!data->pinch_start) {
- if (data->flick_flag) {
- x_delta = p_gesture_info->pt[0].x - data->tap_start_point.x;
- y_delta = p_gesture_info->pt[0].y - data->tap_start_point.y;
-
- if (x_delta < 0) {
- dir_left_right = DIR_LEFT;
- x_delta = -x_delta;
- } else
- dir_left_right = DIR_RIGHT;
-
- if (y_delta < 0) {
- y_delta = -y_delta;
- dir_up_down = DIR_UP;
- } else
- dir_up_down = DIR_DOWN;
-
- if ((THRESHOLD_FLICK <= x_delta) || (THRESHOLD_FLICK <= y_delta)) {
- if (THRESHOLD_DRAGDROP <= data->touch_count) {
- p_gesture_info->gesture_kind = GES_DRAGDROP;
- p_gesture_info->speed = data->touch_count;
- p_gesture_info->pt[0].x = data->tap_start_point.x;
- p_gesture_info->pt[0].y = data->tap_start_point.y;
- p_gesture_info->pt[1].x = pre_gesture_point.x;
- p_gesture_info->pt[1].y = pre_gesture_point.y;
- } else {
- if ((THRESHOLD_FLICK_SPEED < x_delta) || (THRESHOLD_FLICK_SPEED < y_delta))
- p_gesture_info->speed = HIGHSPEED;
- else
- p_gesture_info->speed = LOWSPEED;
- p_gesture_info->gesture_kind = GES_FLICK;
- if (x_delta > y_delta)
- p_gesture_info->dir = dir_left_right;
- else
- p_gesture_info->dir = dir_up_down;
- }
- data->pre_tap_flag_level = 0;
- data->flick_flag = CLR;
- data->touch_count = STOP;
- } else {
- flick_series_flag = FALSE;
- }
- } else {
- flick_series_flag = FALSE;
- }
- if (flick_series_flag == FALSE) {
- if (THRESHOLD_TAPLIMIT <= data->touch_count) {
- p_gesture_info->gesture_kind = GES_TAP;
- p_gesture_info->times = data->pre_tap_flag_level;
- p_gesture_info->speed = data->touch_count;
- data->pre_tap_flag_level = 0;
- data->flick_flag = CLR;
- data->touch_count = STOP;
- data->dir_idx = DIRHEADER;
-
- for (i = 0; i < DIRHEADER; i++)
- data->dir_trace[i] = 0x0;
- for (i = DIRHEADER; i < DIRTRACEN; i++)
- data->dir_trace[i] = 0x05;
- } else {
- ret = FALSE;
- }
- }
- } else {
- data->pinch_start = FALSE;
- data->pre_tap_flag_level = 0;
- data->flick_flag = CLR;
- data->touch_count = STOP;
- }
- }
- } else {
- p_gesture_info->pt[0].x = data->x1;
- p_gesture_info->pt[0].y = data->y1;
- p_gesture_info->pt[1].x = data->x2;
- p_gesture_info->pt[1].y = data->y2;
- touch_calculation(p_gesture_info);
-
- if (data->touch_continue) {
- if ((data->x2 != 0) && (data->y2 != 0)) {
- x_delta = p_gesture_info->pt[0].x - p_gesture_info->pt[1].x;
- y_delta = p_gesture_info->pt[0].y - p_gesture_info->pt[1].y;
- if (x_delta < 0)
- x_delta = -x_delta;
- if (y_delta < 0)
- y_delta = -y_delta;
- x_delta++;
- y_delta++;
- area = x_delta * y_delta;
- p_gesture_info->dir = PINCH_KEEP;
- if (area != pre_area) {
- if (area > pre_area) {
- if ((area - pre_area) > THRESHOLD_PINCH) {
- p_gesture_info->dir = PINCH_OUT;
- if ((area - pre_area) < THRESHOLD_PINCH_SPEED)
- p_gesture_info->speed = LOWSPEED;
- else
- p_gesture_info->speed = HIGHSPEED;
- }
- } else {
- if ((pre_area - area) > THRESHOLD_PINCH) {
- p_gesture_info->dir = PINCH_IN;
-
- if ((pre_area - area) < THRESHOLD_PINCH_SPEED)
- p_gesture_info->speed = LOWSPEED;
- else
- p_gesture_info->speed = HIGHSPEED;
- }
- }
- }
- if (data->pinch_start == FALSE) {
- p_gesture_info->dir = PINCH_KEEP;
- pre_area = 0;
- data->pinch_start = TRUE;
- }
- p_gesture_info->gesture_kind = GES_PINCH;
- pre_area = area;
- } else {
- x_delta = p_gesture_info->pt[0].x - pre_gesture_point.x;
- y_delta = p_gesture_info->pt[0].y - pre_gesture_point.y;
- if (x_delta > 0) {
- if (x_delta < THRESHOLD_ROTATE)
- x_delta = 0;
- } else {
- if (-x_delta < THRESHOLD_ROTATE)
- x_delta = 0;
- }
- if (y_delta > 0) {
- if (y_delta < THRESHOLD_ROTATE)
- y_delta = 0;
- } else {
- if (-y_delta < THRESHOLD_ROTATE)
- y_delta = 0;
- }
- if (x_delta == y_delta)
- p_gesture_info->dir = DIR_INVALID;
- else {
- if (x_delta < 0) {
- dir_left_right = DIR_LEFT;
- x_delta = -x_delta;
- } else
- dir_left_right = DIR_RIGHT;
- if (y_delta < 0) {
- y_delta = -y_delta;
- dir_up_down = DIR_UP;
- } else
- dir_up_down = DIR_DOWN;
- if (x_delta > y_delta)
- p_gesture_info->dir = dir_left_right;
- else
- p_gesture_info->dir = dir_up_down;
- tmp = p_gesture_info->dir;
- data->dir_trace[tmp]++;
- data->dir_trace[data->dir_idx] = tmp;
- if (data->dir_idx < (THRESHOLD_ROTATE_HIST + DIRHEADER))
- data->dir_idx++;
- else
- data->dir_idx = DIRHEADER;
- data->dir_trace[data->dir_trace[data->dir_idx]]--;
- dir1 = data->dir_trace[0];
- for (dir2 = 1; dir2 < 5; dir2++) {
- if (data->dir_trace[data->dir_trace[0]]
- < data->dir_trace[dir2]) {
- data->dir_trace[0] = dir2;
- p_gesture_info->dir
- = data->rotate_data[dir1][dir2];
- if (p_gesture_info->dir)
- p_gesture_info->gesture_kind
- = GES_ROTATE;
- break;
- }
- }
- }
- if (p_gesture_info->dir == ROTATE_INVALID) {
- p_gesture_info->gesture_kind
- = GES_MOVE;
- p_gesture_info->speed
- = data->touch_count;
- }
- }
- data->flick_flag = SET;
- } else {
- p_gesture_info->gesture_kind = GES_TOUCHSTART;
- data->tap_start_point.x = p_gesture_info->pt[0].x;
- data->tap_start_point.y = p_gesture_info->pt[0].y;
- data->touch_count = START;
- }
- data->touch_continue = SET;
- pre_gesture_point.x = p_gesture_info->pt[0].x;
- pre_gesture_point.y = p_gesture_info->pt[0].y;
- }
- return ret;
-}
-
-/**
- * tsc_restart_pen_up_timer() - restart the timer
- * @data:u8500_tsc_data structure pointer
- *
- * This funtion used to run the timer and returns none.
- */
-static inline void tsc_restart_pen_up_timer(struct u8500_tsc_data *data)
-{
-#ifdef CONFIG_TOUCHP_TUNING
- mod_timer(&data->penirq_timer, jiffies + msecs_to_jiffies(penup_timer));
-#else
- mod_timer(&data->penirq_timer, jiffies + msecs_to_jiffies(PENUP_TIMEOUT));
-#endif
-}
-
-/**
- * tsc_clear_irq() - clear the tsc interrupt
- * @i2c:i2c_client structure pointer
- *
- * This funtion used to clear the
- * bu21013 controller interrupt for next Pen interrupts and returns none.
- */
-static void tsc_clear_irq(struct i2c_client *i2c)
-{
- int retval;
- retval = tsc_write_byte(i2c, TSC_INT_CLR, 0X01);
- if (retval < 0)
- dev_err(&i2c->dev, \
- "TSC_INT_CLR failed retval=0x%x \n", retval);
-}
-
-/**
- * tsc_en_irq() - Reactivate the tsc interrupt
- * @i2c:i2c_client structure pointer
- *
- * This funtion used to activate the bu21013 controller
- * interrupt for next Pen interrupts.
- */
-static void tsc_en_irq(struct i2c_client *i2c)
-{
- int retval;
- retval = tsc_write_byte(i2c, TSC_INT_CLR, 0X00);
- if (retval < 0)
- dev_err(&i2c->dev, \
- "TSC_INT_CLR failed retval=0x%x \n", retval);
-}
-/**
- * tsc_input_report() - report the touch point
- * @data:u8500_tsc_data structure pointer
- * @value:value to be passed for en down or pen up
- * This funtion calls, when we need to report the Pen down/up interrupt
- */
-static void tsc_input_report(struct u8500_tsc_data *data, unsigned int value)
-{
- if (value) {
- #ifdef CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
- input_report_abs(data->pin_dev, ABS_X,
- data->gesture_info.pt[0].x);
- input_report_abs(data->pin_dev, ABS_Y,
- data->gesture_info.pt[0].y);
- #else
- input_report_abs(data->pin_dev, ABS_X,
- data->gesture_info.pt[0].y);
- input_report_abs(data->pin_dev, ABS_Y,
- data->gesture_info.pt[0].x);
- #endif
- input_report_abs(data->pin_dev, ABS_PRESSURE, 1);
- input_report_abs(data->pin_dev, ABS_TOOL_WIDTH, 1);
- input_report_key(data->pin_dev, BTN_TOUCH, 1);
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- if (data->finger2_pressed) {
- input_report_key(data->pin_dev, BTN_2, 1);
- #ifdef CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
- input_report_abs(data->pin_dev, ABS_HAT0X,
- data->gesture_info.pt[1].x);
- input_report_abs(data->pin_dev, ABS_HAT0Y,
- data->gesture_info.pt[1].y);
- #else
- input_report_abs(data->pin_dev, ABS_HAT0X,
- data->gesture_info.pt[1].y);
- input_report_abs(data->pin_dev, ABS_HAT0Y,
- data->gesture_info.pt[1].x);
- #endif
- }
- input_report_abs(data->pin_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_key(data->pin_dev, ABS_MT_WIDTH_MAJOR, 1);
- #ifdef CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
- input_report_abs(data->pin_dev, ABS_MT_POSITION_X,
- data->gesture_info.pt[0].x);
- input_report_abs(data->pin_dev, ABS_MT_POSITION_Y,
- data->gesture_info.pt[0].y);
- #else
- input_report_abs(data->pin_dev, ABS_MT_POSITION_X,
- data->gesture_info.pt[0].y);
- input_report_abs(data->pin_dev, ABS_MT_POSITION_Y,
- data->gesture_info.pt[0].x);
- #endif
- input_mt_sync(data->pin_dev);
- if (data->finger2_pressed) {
- input_report_abs(data->pin_dev, ABS_MT_TOUCH_MAJOR, 1);
- input_report_key(data->pin_dev, ABS_MT_WIDTH_MAJOR, 1);
- #ifdef CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
- input_report_abs(data->pin_dev, ABS_MT_POSITION_X,
- data->gesture_info.pt[1].x);
- input_report_abs(data->pin_dev, ABS_MT_POSITION_Y,
- data->gesture_info.pt[1].y);
- #else
- input_report_abs(data->pin_dev, ABS_MT_POSITION_X,
- data->gesture_info.pt[1].y);
- input_report_abs(data->pin_dev, ABS_MT_POSITION_Y,
- data->gesture_info.pt[1].x);
- #endif
- input_mt_sync(data->pin_dev);
- }
-#endif
- } else {
- input_report_abs(data->pin_dev, ABS_PRESSURE, 0);
- input_report_abs(data->pin_dev, ABS_TOOL_WIDTH, 0);
- input_report_key(data->pin_dev, BTN_TOUCH, 0);
- #ifdef CONFIG_U8500_TSC_MULTITOUCH
- if (data->finger2_count > 0) {
- input_report_key(data->pin_dev, BTN_2, 0);
- input_report_abs(data->pin_dev, ABS_MT_TOUCH_MAJOR, 0);
- input_report_key(data->pin_dev, ABS_MT_WIDTH_MAJOR, 0);
- input_mt_sync(data->pin_dev);
- data->finger2_count = 0;
- }
- #endif
- }
- input_sync(data->pin_dev);
-}
-
-/**
- * tsc_callback() - callback handler for Pen down
- * @device_data:void pointer
- *
- * This funtion calls, when we get the Pen down interrupt from Egpio Pin
- * and assigns the task and returns none.
- */
-
-static void tsc_callback(void *device_data)
-{
- struct u8500_tsc_data *data = (struct u8500_tsc_data *)device_data;
- schedule_work(&data->m_tp_gpio_int_wq);
-}
-/**
- * tsc_gpio_callback() - callback handler for Pen down
- * @device_data:void pointer
- * @irq: irq value
- *
- * This funtion calls for HREF v1, when we get the Pen down interrupt from GPIO Pin
- * and assigns the task and returns irqreturn_t.
- */
-
-static irqreturn_t tsc_gpio_callback(int irq, void *device_data)
-{
- struct u8500_tsc_data *data = (struct u8500_tsc_data *)device_data;
- schedule_work(&data->m_tp_gpio_int_wq);
- return IRQ_HANDLED;
-}
-
-
-
-/**
- * tsc_timer_callback() - callback handler for Timer
- * @dev_data:touch screen data
- *
- * This callback handler used to schedule the work for Pen up
- * and Pen down interrupts and returns none
- */
-static void tsc_timer_callback(unsigned long dev_data)
-{
- struct u8500_tsc_data *data = (struct u8500_tsc_data *)dev_data;
- schedule_work(&data->m_tp_timer_int_wq);
-}
-
-/**
- * tsc_timer_wq() - Work Queue for timer handler
- * @work:work_struct structure pointer
- *
- * This work queue used to get the co-ordinates
- * of the Pen up and Pen down interrupts and returns none
- */
-static void tsc_timer_wq(struct work_struct *work)
-{
- unsigned char pin_value;
- struct u8500_tsc_data *data = container_of(work, struct u8500_tsc_data, m_tp_timer_int_wq);
- struct task_struct *tsk = current;
-
- set_task_state(tsk, TASK_INTERRUPTIBLE);
- pin_value = data->chip->pirq_read_val();
-
- get_touch_message(data);
- if (data->touch_en)
- tsc_input_report(data, 1);
- else
- tsc_input_report(data, 0);
-
- if (pin_value == 0) {
- tsc_restart_pen_up_timer(data);
- } else {
- enable_irq(data->chip->irq);
- tsc_clear_irq(data->client);
- tsc_en_irq(data->client);
- }
-}
-
-/**
- * tp_gpio_int_wq() - Work Queue for GPIO_INT handler
- * @work:work_struct structure pointer
- *
- * This work queue used to get the co-ordinates
- * of the Pen up and Pen down interrupts and returns none
- */
-static void tp_gpio_int_wq(struct work_struct *work)
-{
- unsigned char pin_value;
- struct u8500_tsc_data *tp_data = container_of(work, struct u8500_tsc_data, m_tp_gpio_int_wq);
- struct task_struct *tsk = current;
- set_task_state(tsk, TASK_INTERRUPTIBLE);
- pin_value = tp_data->chip->pirq_read_val();
- if (pin_value == 0) {
- disable_irq(tp_data->chip->irq);
- get_touch_message(tp_data);
-
- if (tp_data->touch_en)
- tsc_input_report(tp_data, 1);
- else
- tsc_input_report(tp_data, 0);
-
- tsc_clear_irq(tp_data->client);
- tsc_en_irq(tp_data->client);
- tsc_restart_pen_up_timer(tp_data);
- } else {
- tsc_input_report(tp_data, 0);
- }
-}
-/*
- * GetCaliStatus() - Get the Calibration status
- * @i2c: i2c client structure pointer
- * Get the calibration status of the touch sensor
- * and returns integer
- */
-int get_calib_status(struct i2c_client *i2c)
-{
- tsc_error retval = TSC_OK;
- unsigned int value;
- u8 i;
-
- for (i = 0x40; i <= 0x4B; i += 2) {
- retval = tsc_read_10bit(i2c, i, &value);
- if (retval < 0)
- dev_err(&i2c->dev,
- "get_calib_status:failed retval=0x%x \n", retval);
- }
- for (i = 0x54; i <= 0x69; i += 2) {
- retval = tsc_read_10bit(i2c, i, &value);
- if (retval < 0)
- dev_err(&i2c->dev,
- "get_calib_status:failed retval=0x%x \n", retval);
- }
- return retval;
-}
-/*
- * doCalibrate() - Do the software Calibration
- * @i2c: i2c_client structure pointer
- * Do the soft calibration on the touch screen
- * and returns integer
- */
-int doCalibrate(struct i2c_client *i2c)
-{
- tsc_error retval = TSC_OK;
- retval = tsc_write_byte(i2c, TSC_CALIB, 0X1);
- if (retval < 0)
- dev_err(&i2c->dev, "reset failed retval=0x%x \n", retval);
- return retval;
-}
-/*
- * check_board(): check for href v1 board
- * @data: device structure pointer
- * This function used to check_board
- */
-void check_board(struct u8500_tsc_data *data)
-{
- if (data->chip->board_href_v1)
- data->href_v1_flag = data->chip->board_href_v1();
-}
-/*
- * init_config(): Initialize the Global variables
- * @data: device structure pointer
- * This function used to initialize the device variables and returns none
- */
-void init_config(struct u8500_tsc_data *data)
-{
- signed int i;
-
- data->touch_count = STOP;
- data->touchflag = FALSE;
- data->touch_continue = CLR;
-
- data->pre_tap_flag_level = 0;
- data->pre_tap_flag = 0;
- data->flick_flag = 0;
- data->finger1_pressed = 0;
-
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- data->finger2_pressed = 0;
- data->finger2_count = 0;
-#endif
- data->x1 = 0;
- data->y1 = 0;
- data->x2 = 0;
- data->y2 = 0;
-
- data->pinch_start = FALSE;
-
- /* turning right */
- data->rotate_data[DIR_UP][DIR_RIGHT] = ROTATE_R_UR;
- data->rotate_data[DIR_RIGHT][DIR_DOWN] = ROTATE_R_RD;
- data->rotate_data[DIR_DOWN][DIR_LEFT] = ROTATE_R_DL;
- data->rotate_data[DIR_LEFT][DIR_UP] = ROTATE_R_LU;
-
- /* turning left */
- data->rotate_data[DIR_LEFT][DIR_DOWN] = ROTATE_L_LD;
- data->rotate_data[DIR_RIGHT][DIR_UP] = ROTATE_L_DR;
- data->rotate_data[DIR_DOWN][DIR_RIGHT] = ROTATE_L_RU;
- data->rotate_data[DIR_UP][DIR_LEFT] = ROTATE_L_UL;
-
- /* invalid turning */
- data->rotate_data[DIR_UP][DIR_DOWN] = DIR_INVALID;
- data->rotate_data[DIR_DOWN][DIR_UP] = DIR_INVALID;
- data->rotate_data[DIR_LEFT][DIR_RIGHT] = DIR_INVALID;
- data->rotate_data[DIR_RIGHT][DIR_LEFT] = DIR_INVALID;
- data->rotate_data[DIR_UP][DIR_UP] = DIR_INVALID;
- data->rotate_data[DIR_DOWN][DIR_DOWN] = DIR_INVALID;
- data->rotate_data[DIR_LEFT][DIR_LEFT] = DIR_INVALID;
- data->rotate_data[DIR_RIGHT][DIR_RIGHT] = DIR_INVALID;
-
- data->dir_idx = DIRHEADER;
-
- for (i = 0; i < DIRHEADER; i++)
- data->dir_trace[i] = 0x0;
-
- for (i = DIRHEADER; i < DIRTRACEN; i++)
- data->dir_trace[i] = 0x05;
-
- data->tap_start_point.x = 0x0;
- data->tap_start_point.y = 0x0;
- data->href_v1_flag = FALSE;
- return;
-}
-/**
- * bu21013_tsc_init() - Power on sequence for the bu21013 controller
- * @i2c:pointer to i2c client structure
- *
- * This funtion is used to power on
- * the bu21013 controller and returns tsc error.
- **/
-static tsc_error bu21013_tsc_init(struct i2c_client *i2c)
-{
- tsc_error retval = TSC_OK;
-
- dev_dbg(&i2c->dev, "bu21013_tsc_init start\n");
-
- retval = i2c_smbus_write_byte_data(i2c, TSC_RESET, 0x01);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "ED reg i2c smbus write byte failed\n");
- goto err;
- }
- mdelay(30);
-
- retval = i2c_smbus_write_byte_data(i2c, TSC_SENSOR_0_7, 0x3F);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F0 reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_SENSOR_8_15, 0xFC);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F1 reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_SENSOR_16_23, 0x1F);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F2 reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_POS_MODE1, 0x06);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F3 reg i2c smbus write byte failed\n");
- goto err;
- }
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- retval = i2c_smbus_write_byte_data(i2c, TSC_POS_MODE2, 0x97);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F4 reg i2c smbus write byte failed\n");
- goto err;
- }
-#else
- retval = i2c_smbus_write_byte_data(i2c, TSC_POS_MODE2, 0x17);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F4 reg i2c smbus write byte failed\n");
- goto err;
- }
-#endif
-#ifdef CONFIG_U8500_TSC_EXT_CLK_9_6
- retval = i2c_smbus_write_byte_data(i2c, TSC_CLK_MODE, TSC_CLK_MODE_VAL1);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F5 reg i2c smbus write byte failed\n");
- goto err;
- }
-#else
- retval = i2c_smbus_write_byte_data(i2c, TSC_CLK_MODE, TSC_CLK_MODE_VAL2);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "F5 reg i2c smbus write byte failed\n");
- goto err;
- }
-#endif
- retval = i2c_smbus_write_byte_data(i2c, TSC_IDLE, TSC_IDLE_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "FA reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_INT_MODE, TSC_INT_MODE_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "E9 reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_FILTER, TSC_FILTER_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "FB reg i2c smbus write byte failed\n");
- goto err;
- }
-#if (defined CONFIG_CPU_IDLE || defined CONFIG_TOUCHP_TUNING)
- retval = i2c_smbus_write_byte_data(i2c, TSC_TH_ON, th_on);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "FC reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_TH_OFF, th_off);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "FD reg i2c smbus write byte failed\n");
- goto err;
- }
-#else
- retval = i2c_smbus_write_byte_data(i2c, TSC_TH_ON, TSC_TH_ON_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "FC i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_TH_OFF, TSC_TH_OFF_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "FD i2c smbus write byte failed\n");
- goto err;
- }
-#endif
- retval = i2c_smbus_write_byte_data(i2c, TSC_GAIN, TSC_GAIN_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "EA reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_OFFSET_MODE, TSC_OFFSET_MODE_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "EB reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_XY_EDGE, TSC_XY_EDGE_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "EC reg i2c smbus write byte failed\n");
- goto err;
- }
- retval = i2c_smbus_write_byte_data(i2c, TSC_DONE, TSC_DONE_VAL);
- if (retval < TSC_OK) {
- dev_err(&i2c->dev, "EF reg i2c smbus write byte failed\n");
- goto err;
- }
-err:
- return retval;
-}
-
-/*
- * tsc_driver_register() - Used for input driver registeration
- * @pdata: pointer to u8500_tsc_data structure
- * This function used to register the
- * touch screen as input device and returns integer
- */
-static int tsc_driver_register(struct u8500_tsc_data *pdata)
-{
- int ret = TSC_OK;
-
- struct input_dev *in_dev;
- struct i2c_client *i2c = pdata->client;
- dev_dbg(&i2c->dev, "tsc_driver_register start\n");
-
- /* register the touch screen driver to input device */
- in_dev = input_allocate_device();
- pdata->pin_dev = in_dev;
- if (!in_dev) {
- ret = -ENOMEM;
- goto err;
- }
-
- in_dev->name = DRIVER_TP;
- set_bit(EV_SYN, in_dev->evbit);
- set_bit(EV_KEY, in_dev->evbit);
- set_bit(EV_ABS, in_dev->evbit);
- set_bit(BTN_TOUCH, in_dev->keybit);
-#ifdef CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
- input_set_abs_params(in_dev, ABS_X, 0, X_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_Y, 0, Y_MAX, 0, 0);
-#else
- input_set_abs_params(in_dev, ABS_X, 0, Y_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_Y, 0, X_MAX, 0, 0);
-#endif
- input_set_abs_params(in_dev, ABS_PRESSURE, 0, 1, 0, 0);
- input_set_abs_params(in_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
-#ifdef CONFIG_U8500_TSC_MULTITOUCH
- set_bit(BTN_2, in_dev->keybit);
-#ifdef CONFIG_FB_U8500_MCDE_CHANNELC0_DISPLAY_WVGA_PORTRAIT
- input_set_abs_params(in_dev, ABS_HAT0X, 0, X_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_HAT0Y, 0, Y_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, X_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, Y_MAX, 0, 0);
-#else
- input_set_abs_params(in_dev, ABS_HAT0X, 0, Y_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_HAT0Y, 0, X_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, Y_MAX, 0, 0);
- input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, X_MAX, 0, 0);
-#endif
- input_set_abs_params(in_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
- input_set_abs_params(in_dev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
-#endif
- ret = input_register_device(in_dev);
- if (ret) {
- dev_err(&i2c->dev, " could not register error \n");
- goto err;
- }
- dev_dbg(&i2c->dev, "tsc_driver_register done \n");
-err:
- return ret;
-}
-/**
- * tsc_config() - configure the touch screen controller
- * @pdev_data: pointer to u8500_tsc_data structure
- *
- * This funtion is used to configure
- * the bu21013 controller and returns tsc error.
- **/
-static tsc_error tsc_config(struct u8500_tsc_data *pdev_data)
-{
- int retval;
-
- retval = bu21013_tsc_init(pdev_data->client);
- if (retval == TSC_OK) {
- init_config(pdev_data);
- check_board(pdev_data);
- if (pdev_data->href_v1_flag == FALSE) {
- if ((pdev_data->chip->pirq_en) && (pdev_data->chip->pirq_dis)
- && (pdev_data->chip->irq_init)) {
- retval = pdev_data->chip->pirq_dis();
- if (retval < 0) {
- dev_err(&pdev_data->client->dev,
- " irq disable failed \n");
- goto err;
- }
- retval = pdev_data->chip->pirq_en();
- if (retval < 0) {
- dev_err(&pdev_data->client->dev,
- " irq en failed \n");
- goto err_init_irq;
- }
- if \
- (pdev_data->chip->irq_init \
- (tsc_callback, (void *)pdev_data)) {
- dev_err(&pdev_data->client->dev, \
- " initiate the callback handler failed \n");
- goto err_init_irq;
- }
- }
- }
- retval = get_calib_status(pdev_data->client);
- if (retval < 0) {
- dev_err(&pdev_data->client->dev,
- "u8500_tsc_probe::calibration not done \n");
- goto err_init_irq;
- }
- return retval;
- }
-err_init_irq:
- pdev_data->chip->pirq_dis();
- pdev_data->chip->irq_exit();
-err:
- pdev_data->chip->cs_dis();
- return retval;
-}
-#ifdef CONFIG_PM
-/**
- * tsc_suspend() - suspend the touch screen controller
- * @client: pointer to i2c client structure
- * @mesg: message from power manager
- *
- * This funtion is used to suspend the
- * touch panel controller and returns integer
- **/
-static int tsc_suspend(struct i2c_client *client, pm_message_t mesg)
-{
- int retval;
- struct u8500_tsc_data *tsc_data = i2c_get_clientdata(client);
- retval = tsc_data->chip->pirq_dis();
- if (retval < 0) {
- dev_err(&client->dev, "tsc_suspend:: irq disable failed \n");
- goto err;
- }
- retval = tsc_data->chip->irq_exit();
- if (retval < 0) {
- dev_err(&client->dev, "tsc_suspend:: remove \
- the callback handler failed \n");
- goto err;
- }
- return TSC_OK;
-err:
- kfree(tsc_data);
- return retval;
-}
-
-/**
- * tsc_resume() - resume the touch screen controller
- * @client: pointer to i2c client structure
- *
- * This funtion is used to resume the touch panel
- * controller and returns integer.
- **/
-static int tsc_resume(struct i2c_client *client)
-{
- int retval;
- struct u8500_tsc_data *tsc_data = i2c_get_clientdata(client);
-
- retval = tsc_config(tsc_data);
- if (retval < 0) {
- dev_err(&client->dev, "tsc_resume:: error in \
- touch panel configuration\n");
- goto err;
- }
- return TSC_OK;
-err:
- kfree(tsc_data);
- return retval;
-}
-#endif
-/**
- * tp_probe() - Initialze the i2c-client touchscreen driver
- * @i2c: i2c client structure pointer
- * @id:i2c device id pointer
- *
- * This funtion uses to Initializes the i2c-client touchscreen
- * driver and returns integer.
- **/
-static int tp_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
-{
- int retval = 0;
- struct u8500_tsc_data *tsc_data;
- struct tp_device *pdata = i2c->dev.platform_data;
- dev_dbg(&i2c->dev, "u8500_tsc_probe:: start\n");
-
- tsc_data = kzalloc(sizeof(struct u8500_tsc_data), GFP_KERNEL);
- if (!tsc_data) {
- dev_err(&i2c->dev, "tp memory allocation failed \n");
- retval = -ENOMEM;
- return retval;
- }
-
- if (!pdata) {
- dev_err(&i2c->dev, "tp platform data not defined \n");
- retval = -EINVAL;
- goto err_alloc;
- }
- tsc_data->chip = pdata;
- tsc_data->client = i2c;
-
- init_timer(&tsc_data->penirq_timer);
- tsc_data->penirq_timer.data = (unsigned long)tsc_data;
- tsc_data->penirq_timer.function = tsc_timer_callback;
-
- INIT_WORK(&tsc_data->m_tp_timer_int_wq, tsc_timer_wq);
- INIT_WORK(&tsc_data->m_tp_gpio_int_wq, tp_gpio_int_wq);
- i2c_set_clientdata(i2c, tsc_data);
- init_waitqueue_head(&tsc_data->touchp_event);
-
- /* configure the gpio pins */
- if (tsc_data->chip->cs_en) {
- retval = tsc_data->chip->cs_en();
- if (retval != TSC_OK) {
- dev_err(&tsc_data->client->dev,
- "error in tp chip initialization\n");
- goto err;
- }
- }
-
- /** configure the touch panel controller */
- retval = tsc_config(tsc_data);
- if (retval < 0) {
- dev_err(&i2c->dev, "error in tp configuration\n");
- goto err;
- } else {
- if (tsc_data->href_v1_flag) {
- retval = request_irq(tsc_data->chip->irq, tsc_gpio_callback,
- IRQF_TRIGGER_FALLING, DRIVER_TP, tsc_data);
- if (retval) {
- dev_err(&tsc_data->client->dev,
- "unable to request for the irq %d\n", tsc_data->chip->irq);
- gpio_free(tsc_data->chip->irq);
- goto err;
- }
- }
- retval = tsc_driver_register(tsc_data);
- if (retval)
- goto err_init;
- }
-#ifdef CONFIG_TOUCHP_TUNING
- /* Registering touchp device for sysfs */
- pdev_data = tsc_data;
- touchp_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
- if (touchp_kobj == NULL) {
- retval = -ENOMEM;
- goto err_init;
- }
- touchp_kobj->ktype = &ktype_touchp;
- kobject_init(touchp_kobj, touchp_kobj->ktype);
- retval = kobject_set_name(touchp_kobj, "touchp_attribute");
- if (retval) {
- kfree(touchp_kobj);
- goto err_init;
- }
- retval = kobject_add(touchp_kobj, NULL, "touchp_attribute");
- if (retval) {
- kfree(touchp_kobj);
- goto err_init;
- }
-#endif
- dev_dbg(&i2c->dev, "u8500_tsc_probe : done \n");
- return retval;
-err_init:
- input_free_device(tsc_data->pin_dev);
-err:
- del_timer_sync(&tsc_data->penirq_timer);
-err_alloc:
- kfree(tsc_data);
- return retval;
-}
-/**
- * tp_remove() - Removes the i2c-client touchscreen driver
- * @client: i2c client structure pointer
- *
- * This funtion uses to remove the i2c-client
- * touchscreen driver and returns integer.
- **/
-static int __exit tp_remove(struct i2c_client *client)
-{
- struct u8500_tsc_data *data = i2c_get_clientdata(client);
- del_timer_sync(&data->penirq_timer);
- if (data->chip != NULL) {
- data->chip->irq_exit();
- data->chip->pirq_dis();
- data->chip->cs_dis();
- }
- if (data->href_v1_flag != 0) {
- if (data->chip != NULL)
- gpio_free(data->chip->irq);
- }
- input_unregister_device(data->pin_dev);
- input_free_device(data->pin_dev);
- kfree(data);
- i2c_set_clientdata(client, NULL);
- return TSC_OK;
-}
-
-static const struct i2c_device_id tp_id[] = {
- { DRIVER_TP, 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, tp_id);
-
-static struct i2c_driver tp_driver = {
- .driver = {
- .name = DRIVER_TP,
- .owner = THIS_MODULE,
- },
- .probe = tp_probe,
-#ifdef CONFIG_PM
- .suspend = tsc_suspend,
- .resume = tsc_resume,
-#endif
- .remove = __exit_p(tp_remove),
- .id_table = tp_id,
-};
-
-/**
- * tp_init() - Initialize the paltform touchscreen driver
- *
- * This funtion uses to initialize the platform
- * touchscreen driver and returns integer.
- **/
-static int __init tp_init(void){
- return i2c_add_driver(&tp_driver);
-}
-
-/**
- * tp_exit() - De-initialize the paltform touchscreen driver
- *
- * This funtion uses to de-initialize the platform
- * touchscreen driver and returns none.
- **/
-static void __exit tp_exit(void){
- i2c_del_driver(&tp_driver);
-}
-
-module_init(tp_init);
-module_exit(tp_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("NAVEEN KUMAR G");
-MODULE_DESCRIPTION("Touch Screen driver for U8500");
diff --git a/include/linux/bu21013.h b/include/linux/bu21013.h
new file mode 100755
index 00000000000..1dcc841ff3f
--- /dev/null
+++ b/include/linux/bu21013.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2009
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#ifndef _BU21013_H
+#define _BU21013_H
+
+/*
+ * Touch screen register offsets
+ */
+#define BU21013_SENSORS_BTN_0_7 0x70
+#define BU21013_SENSORS_BTN_8_15 0x71
+#define BU21013_SENSORS_BTN_16_23 0x72
+#define BU21013_X1_POS_MSB 0x73
+#define BU21013_X1_POS_LSB 0x74
+#define BU21013_Y1_POS_MSB 0x75
+#define BU21013_Y1_POS_LSB 0x76
+#define BU21013_X2_POS_MSB 0x77
+#define BU21013_X2_POS_LSB 0x78
+#define BU21013_Y2_POS_MSB 0x79
+#define BU21013_Y2_POS_LSB 0x7A
+#define BU21013_INT_CLR 0xE8
+#define BU21013_INT_MODE 0xE9
+#define BU21013_GAIN 0xEA
+#define BU21013_OFFSET_MODE 0xEB
+#define BU21013_XY_EDGE 0xEC
+#define BU21013_RESET 0xED
+#define BU21013_CALIB 0xEE
+#define BU21013_REG_DONE 0xEF
+#define BU21013_SENSOR_0_7 0xF0
+#define BU21013_SENSOR_8_15 0xF1
+#define BU21013_SENSOR_16_23 0xF2
+#define BU21013_POS_MODE1 0xF3
+#define BU21013_POS_MODE2 0xF4
+#define BU21013_CLK_MODE 0xF5
+#define BU21013_IDLE 0xFA
+#define BU21013_FILTER 0xFB
+#define BU21013_TH_ON 0xFC
+#define BU21013_TH_OFF 0xFD
+
+/*
+ * Touch screen register offset values
+ */
+#define BU21013_INTR_CLEAR 0x01
+#define BU21013_INTR_ENABLE 0x00
+#define BU21013_CALIB_ENABLE 0x01
+
+#define BU21013_RESET_ENABLE 0x01
+
+/* Sensors Configuration */
+#define BU21013_SENSORS_EN_0_7 0x3F
+#define BU21013_SENSORS_EN_8_15 0xFC
+#define BU21013_SENSORS_EN_16_23 0x1F
+
+/* Position mode1 */
+#define BU21013_POS_MODE1_0 0x02
+#define BU21013_POS_MODE1_1 0x04
+#define BU21013_POS_MODE1_2 0x08
+
+/* Position mode2 */
+#define BU21013_POS_MODE2_ZERO 0x01
+#define BU21013_POS_MODE2_AVG1 0x02
+#define BU21013_POS_MODE2_AVG2 0x04
+#define BU21013_POS_MODE2_EN_XY 0x08
+#define BU21013_POS_MODE2_EN_RAW 0x10
+#define BU21013_POS_MODE2_MULTI 0x80
+
+/* Clock mode */
+#define BU21013_CLK_MODE_DIV 0x01
+#define BU21013_CLK_MODE_EXT 0x02
+#define BU21013_CLK_MODE_CALIB 0x80
+
+/* IDLE time */
+#define BU21013_IDLET_0 0x01
+#define BU21013_IDLET_1 0x02
+#define BU21013_IDLET_2 0x04
+#define BU21013_IDLET_3 0x08
+#define BU21013_IDLE_INTERMIT_EN 0x10
+
+/* FILTER reg values */
+#define BU21013_DELTA_0_6 0x7F
+#define BU21013_FILTER_EN 0x80
+
+/* interrupt mode */
+#define BU21013_INT_MODE_LEVEL 0x00
+#define BU21013_INT_MODE_EDGE 0x01
+
+/* Gain reg values */
+#define BU21013_GAIN_0 0x01
+#define BU21013_GAIN_1 0x02
+#define BU21013_GAIN_2 0x04
+
+/* OFFSET mode */
+#define BU21013_OFFSET_MODE_DEFAULT 0x00
+#define BU21013_OFFSET_MODE_MOVE 0x01
+#define BU21013_OFFSET_MODE_DISABLE 0x02
+
+/* Threshold ON values */
+#define BU21013_TH_ON_0 0x01
+#define BU21013_TH_ON_1 0x02
+#define BU21013_TH_ON_2 0x04
+#define BU21013_TH_ON_3 0x08
+#define BU21013_TH_ON_4 0x10
+#define BU21013_TH_ON_5 0x20
+#define BU21013_TH_ON_6 0x40
+#define BU21013_TH_ON_7 0x80
+
+#define BU21013_TH_ON_MAX 0xFF
+
+/* Threshold OFF values */
+#define BU21013_TH_OFF_0 0x01
+#define BU21013_TH_OFF_1 0x02
+#define BU21013_TH_OFF_2 0x04
+#define BU21013_TH_OFF_3 0x08
+#define BU21013_TH_OFF_4 0x10
+#define BU21013_TH_OFF_5 0x20
+#define BU21013_TH_OFF_6 0x40
+#define BU21013_TH_OFF_7 0x80
+
+#define BU21013_TH_OFF_MAX 0xFF
+
+/* FILTER reg values */
+#define BU21013_X_EDGE_0 0x01
+#define BU21013_X_EDGE_1 0x02
+#define BU21013_X_EDGE_2 0x04
+#define BU21013_X_EDGE_3 0x08
+#define BU21013_Y_EDGE_0 0x10
+#define BU21013_Y_EDGE_1 0x20
+#define BU21013_Y_EDGE_2 0x40
+#define BU21013_Y_EDGE_3 0x80
+
+#define BU21013_DONE 0x01
+
+/**
+ * struct bu21013_platform_device - Handle the platform data
+ * @cs_en: pointer to the cs enable function
+ * @cs_dis: pointer to the cs disable function
+ * @irq_init: pointer to the irq init function
+ * @irq_exit: pointer to the irq exit function
+ * @pirq_en: pointer to the pen irq en function
+ * @pirq_dis: pointer to the pen irq disable function
+ * @pirq_read_val: pointer to read the pen irq value function
+ * @board_check: pointer to the get the board version
+ * @x_max_res: xmax resolution
+ * @y_max_res: ymax resolution
+ * @touch_x_max: touch x max
+ * @touch_y_max: touch y max
+ * @tp_cntl: controller id
+ * @cs_pin: chip select pin
+ * @irq: irq pin
+ * @ext_clk_en: external clock flag
+ * @portrait: portrait mode flag
+ * @edge_mode: edge mode flag
+ * This is used to handle the platform data
+ **/
+struct bu21013_platform_device {
+ int (*cs_en)(int reset_pin);
+ int (*cs_dis)(int reset_pin);
+ int (*irq_init)(void (*callback)(void *parameter), void *p);
+ int (*irq_exit)(void);
+ int (*pirq_en) (void);
+ int (*pirq_dis)(void);
+ int (*pirq_read_val)(void);
+ bool (*board_check)(void);
+ int x_max_res;
+ int y_max_res;
+ int touch_x_max;
+ int touch_y_max;
+ int tp_cntl;
+ unsigned int cs_pin;
+ unsigned int irq;
+ bool portrait;
+ bool ext_clk;
+ bool edge_mode;
+};
+
+/**
+ * struct bu21013_touch_point - x and y co-ordinates of touch panel
+ * @x: x co-ordinate
+ * @y: y co-ordinate
+ * This is used to hold the x and y co-ordinates of touch panel
+ **/
+struct bu21013_touch_point {
+ signed short x;
+ signed short y;
+};
+
+/**
+ * struct bu21013_gesture_info - hold the gesture of the touch
+ * @gesture_kind: gesture kind variable
+ * @pt: arry to touch_point structure
+ * @dir: direction variable
+ * @times: touch times
+ * @speed: speed of the touch
+ * This is used to hold the gesture of the touch.
+ **/
+struct bu21013_gesture_info {
+ signed short gesture_kind;
+ struct bu21013_touch_point pt[2];
+ signed short dir;
+ signed short times;
+ signed short speed;
+};
+
+/**
+ * struct bu21013_ts_data - touch panel data structure
+ * @client: pointer to the i2c client
+ * @chip: pointer to the touch panel controller
+ * @pin_dev: pointer to the input device structure
+ * @penirq_timer: variable to the timer list structure
+ * @touch_en: variable for reporting the co-ordinates to input device.
+ * @finger1_pressed: variable to indicate the first co-ordinates.
+ * @finger2_pressed: variable to indicate the first co-ordinates.
+ * @tp_timer_handler: variable to work structure for timer
+ * @tp_gpio_handler: variable to work structure for gpio interrupt
+ * @gesture_info: variable to bu21013_gesture_info structure
+ * @touch_count: variable to maintain sensors input count
+ * @touchflag: variable to indicate the touch
+ * @pre_tap_flag: flag to indicate the pre tap
+ * @flick_flag: flickering flag
+ * @touch_continue: to continue the touch flag
+ * @pre_tap_flag_level: pre tap level flag
+ * @x1: x1 value
+ * @y1: y1 vlaue
+ * @x2: x2 value
+ * @y2: y2 value
+ * @pinch_start: pinch start
+ * @tap_start_point: variable to bu21013_touch_point structure
+ * @dir_trace: array for data trace
+ * @dir_idx: id for direction
+ * @rotate_data: array to maintain the rotate data
+ * @board_flag: variable to indicate the href v1 board
+ * @finger2_count: count for finger2 touches
+ * @intr_pin: interrupt pin value
+ * @last_press: sensor button pressed
+ * @prev_press_report: last reported flag
+ * @touchp_kobj: variable to kernel object for touch panel
+ * @gain: gain value
+ * @th_on: threshold on value
+ * @th_off: threshold off value
+ * @penup_timer: timeout value
+ *
+ * Tocuh panel data structure
+ */
+struct bu21013_ts_data {
+ struct i2c_client *client;
+ struct bu21013_platform_device *chip;
+ struct input_dev *pin_dev;
+ struct timer_list penirq_timer;
+ bool touch_en;
+ bool finger1_pressed;
+ bool finger2_pressed;
+ struct work_struct tp_timer_handler;
+ struct work_struct tp_gpio_handler;
+ struct bu21013_gesture_info gesture_info;
+ signed long touch_count;
+ bool touchflag;
+ bool pre_tap_flag;
+ bool flick_flag;
+ bool touch_continue;
+ unsigned char pre_tap_flag_level;
+ unsigned char pinch_start;
+ struct bu21013_touch_point tap_start_point;
+ unsigned char dir_trace[38];
+ unsigned char dir_idx;
+ unsigned char rotate_data[5][5];
+ bool board_flag;
+ u8 finger2_count;
+ unsigned int intr_pin;
+ signed short x1;
+ signed short y1;
+ signed short x2;
+ signed short y2;
+ int last_press;
+ bool prev_press_report;
+ struct kobject touchp_kobj;
+ int gain;
+ int th_on;
+ int th_off;
+ int penup_timer;
+};
+#endif