From d0273dd2e778b3d61c0f37f735474e1dfcca195c Mon Sep 17 00:00:00 2001 From: kfx Date: Mon, 20 Aug 2012 13:16:32 +0800 Subject: [PATCH] rk2928: a720: touchscren && camera && sdmmc && usb wifi support --- arch/arm/configs/rk2928_a720_defconfig | 9 +- .../mach-rk2928/board-rk2928-a720-camera.c | 448 ++++++ arch/arm/mach-rk2928/board-rk2928-a720.c | 118 +- arch/arm/mach-rk2928/include/mach/board.h | 10 + drivers/input/touchscreen/Kconfig | 7 +- drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/sitronix_ts_a720.c | 1233 +++++++++++++++++ drivers/input/touchscreen/sitronix_ts_a720.h | 175 +++ 8 files changed, 1993 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-rk2928/board-rk2928-a720-camera.c create mode 100755 drivers/input/touchscreen/sitronix_ts_a720.c create mode 100755 drivers/input/touchscreen/sitronix_ts_a720.h diff --git a/arch/arm/configs/rk2928_a720_defconfig b/arch/arm/configs/rk2928_a720_defconfig index bb5d2ec4d623..e4af82c036e9 100644 --- a/arch/arm/configs/rk2928_a720_defconfig +++ b/arch/arm/configs/rk2928_a720_defconfig @@ -202,6 +202,7 @@ CONFIG_PHYLIB=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set CONFIG_WLAN_80211=y +CONFIG_RTL8188EU=y CONFIG_USB_USBNET=y CONFIG_PPP=y CONFIG_PPP_MULTILINK=y @@ -221,6 +222,7 @@ CONFIG_INPUT_KEYRESET=y CONFIG_INPUT_JOYSTICK=y CONFIG_INPUT_TABLET=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SITRONIX_A720=y CONFIG_INPUT_MISC=y CONFIG_INPUT_KEYCHORD=y CONFIG_INPUT_UINPUT=y @@ -250,6 +252,12 @@ CONFIG_MFD_TPS65090=y CONFIG_REGULATOR=y CONFIG_REGULATOR_TPS65910=y CONFIG_RK30_PWM_REGULATOR=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_VIDEO_DEV=y +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_OV2659=y +CONFIG_VIDEO_RK29=y +CONFIG_VIDEO_RK29_CAMMEM_ION=y CONFIG_ION=y CONFIG_ION_ROCKCHIP=y CONFIG_FB=y @@ -350,7 +358,6 @@ CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_EMBEDDED_SDIO=y CONFIG_MMC_PARANOID_SD_INIT=y CONFIG_SDMMC_RK29=y -# CONFIG_SDMMC0_RK29 is not set # CONFIG_SDMMC1_RK29 is not set CONFIG_SWITCH=y CONFIG_SWITCH_GPIO=y diff --git a/arch/arm/mach-rk2928/board-rk2928-a720-camera.c b/arch/arm/mach-rk2928/board-rk2928-a720-camera.c new file mode 100644 index 000000000000..b92e6b28428e --- /dev/null +++ b/arch/arm/mach-rk2928/board-rk2928-a720-camera.c @@ -0,0 +1,448 @@ +#ifdef CONFIG_VIDEO_RK29 +/*---------------- Camera Sensor Macro Define Begin ------------------------*/ +/*---------------- Camera Sensor Configuration Macro Begin ------------------------*/ +#define CONFIG_SENSOR_0 RK29_CAM_SENSOR_OV5642 /* back camera sensor */ +#define CONFIG_SENSOR_IIC_ADDR_0 0 +#define CONFIG_SENSOR_IIC_ADAPTER_ID_0 0 +#define CONFIG_SENSOR_CIF_INDEX_0 0 +#define CONFIG_SENSOR_ORIENTATION_0 90 +#define CONFIG_SENSOR_POWER_PIN_0 INVALID_GPIO +#define CONFIG_SENSOR_RESET_PIN_0 INVALID_GPIO +#define CONFIG_SENSOR_POWERDN_PIN_0 INVALID_GPIO//RK2928_PIN3_PB3 +#define CONFIG_SENSOR_FALSH_PIN_0 INVALID_GPIO +#define CONFIG_SENSOR_POWERACTIVE_LEVEL_0 RK29_CAM_POWERACTIVE_L +#define CONFIG_SENSOR_RESETACTIVE_LEVEL_0 RK29_CAM_RESETACTIVE_L +#define CONFIG_SENSOR_POWERDNACTIVE_LEVEL_0 RK29_CAM_POWERDNACTIVE_H +#define CONFIG_SENSOR_FLASHACTIVE_LEVEL_0 RK29_CAM_FLASHACTIVE_L + +#define CONFIG_SENSOR_QCIF_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_240X160_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_QVGA_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_CIF_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_VGA_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_480P_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_SVGA_FPS_FIXED_0 15000 +#define CONFIG_SENSOR_720P_FPS_FIXED_0 30000 + +#define CONFIG_SENSOR_01 RK29_CAM_SENSOR_OV5642 /* back camera sensor 1 */ +#define CONFIG_SENSOR_IIC_ADDR_01 0x00 +#define CONFIG_SENSOR_CIF_INDEX_01 0 +#define CONFIG_SENSOR_IIC_ADAPTER_ID_01 4 +#define CONFIG_SENSOR_ORIENTATION_01 90 +#define CONFIG_SENSOR_POWER_PIN_01 INVALID_GPIO +#define CONFIG_SENSOR_RESET_PIN_01 INVALID_GPIO +#define CONFIG_SENSOR_POWERDN_PIN_01 INVALID_GPIO//RK2928_PIN3_PB3 +#define CONFIG_SENSOR_FALSH_PIN_01 INVALID_GPIO +#define CONFIG_SENSOR_POWERACTIVE_LEVEL_01 RK29_CAM_POWERACTIVE_L +#define CONFIG_SENSOR_RESETACTIVE_LEVEL_01 RK29_CAM_RESETACTIVE_L +#define CONFIG_SENSOR_POWERDNACTIVE_LEVEL_01 RK29_CAM_POWERDNACTIVE_H +#define CONFIG_SENSOR_FLASHACTIVE_LEVEL_01 RK29_CAM_FLASHACTIVE_L + +#define CONFIG_SENSOR_QCIF_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_240X160_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_QVGA_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_CIF_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_VGA_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_480P_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_SVGA_FPS_FIXED_01 15000 +#define CONFIG_SENSOR_720P_FPS_FIXED_01 30000 + +#define CONFIG_SENSOR_02 RK29_CAM_SENSOR_OV5640 /* back camera sensor 2 */ +#define CONFIG_SENSOR_IIC_ADDR_02 0x00 +#define CONFIG_SENSOR_CIF_INDEX_02 0 +#define CONFIG_SENSOR_IIC_ADAPTER_ID_02 4 +#define CONFIG_SENSOR_ORIENTATION_02 90 +#define CONFIG_SENSOR_POWER_PIN_02 INVALID_GPIO +#define CONFIG_SENSOR_RESET_PIN_02 INVALID_GPIO +#define CONFIG_SENSOR_POWERDN_PIN_02 INVALID_GPIO//RK2928_PIN3_PB3 +#define CONFIG_SENSOR_FALSH_PIN_02 INVALID_GPIO +#define CONFIG_SENSOR_POWERACTIVE_LEVEL_02 RK29_CAM_POWERACTIVE_L +#define CONFIG_SENSOR_RESETACTIVE_LEVEL_02 RK29_CAM_RESETACTIVE_L +#define CONFIG_SENSOR_POWERDNACTIVE_LEVEL_02 RK29_CAM_POWERDNACTIVE_H +#define CONFIG_SENSOR_FLASHACTIVE_LEVEL_02 RK29_CAM_FLASHACTIVE_L + +#define CONFIG_SENSOR_QCIF_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_240X160_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_QVGA_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_CIF_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_VGA_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_480P_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_SVGA_FPS_FIXED_02 15000 +#define CONFIG_SENSOR_720P_FPS_FIXED_02 30000 + +#define CONFIG_SENSOR_1 RK29_CAM_SENSOR_OV2659 /* front camera sensor 0 */ +#define CONFIG_SENSOR_IIC_ADDR_1 0x60 +#define CONFIG_SENSOR_IIC_ADAPTER_ID_1 1 +#define CONFIG_SENSOR_CIF_INDEX_1 0 +#define CONFIG_SENSOR_ORIENTATION_1 270 +#define CONFIG_SENSOR_POWER_PIN_1 INVALID_GPIO +#define CONFIG_SENSOR_RESET_PIN_1 INVALID_GPIO +#define CONFIG_SENSOR_POWERDN_PIN_1 RK2928_PIN3_PB3 +#define CONFIG_SENSOR_FALSH_PIN_1 INVALID_GPIO +#define CONFIG_SENSOR_POWERACTIVE_LEVEL_1 RK29_CAM_POWERACTIVE_L +#define CONFIG_SENSOR_RESETACTIVE_LEVEL_1 RK29_CAM_RESETACTIVE_L +#define CONFIG_SENSOR_POWERDNACTIVE_LEVEL_1 RK29_CAM_POWERDNACTIVE_H +#define CONFIG_SENSOR_FLASHACTIVE_LEVEL_1 RK29_CAM_FLASHACTIVE_L + +#define CONFIG_SENSOR_QCIF_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_240X160_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_QVGA_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_CIF_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_VGA_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_480P_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_SVGA_FPS_FIXED_1 15000 +#define CONFIG_SENSOR_720P_FPS_FIXED_1 30000 + +#define CONFIG_SENSOR_11 RK29_CAM_SENSOR_OV2659 /* front camera sensor 1 */ +#define CONFIG_SENSOR_IIC_ADDR_11 0x00 +#define CONFIG_SENSOR_IIC_ADAPTER_ID_11 3 +#define CONFIG_SENSOR_CIF_INDEX_11 0 +#define CONFIG_SENSOR_ORIENTATION_11 270 +#define CONFIG_SENSOR_POWER_PIN_11 INVALID_GPIO +#define CONFIG_SENSOR_RESET_PIN_11 INVALID_GPIO +#define CONFIG_SENSOR_POWERDN_PIN_11 INVALID_GPIO +#define CONFIG_SENSOR_FALSH_PIN_11 INVALID_GPIO +#define CONFIG_SENSOR_POWERACTIVE_LEVEL_11 RK29_CAM_POWERACTIVE_L +#define CONFIG_SENSOR_RESETACTIVE_LEVEL_11 RK29_CAM_RESETACTIVE_L +#define CONFIG_SENSOR_POWERDNACTIVE_LEVEL_11 RK29_CAM_POWERDNACTIVE_H +#define CONFIG_SENSOR_FLASHACTIVE_LEVEL_11 RK29_CAM_FLASHACTIVE_L + +#define CONFIG_SENSOR_QCIF_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_240X160_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_QVGA_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_CIF_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_VGA_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_480P_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_SVGA_FPS_FIXED_11 15000 +#define CONFIG_SENSOR_720P_FPS_FIXED_11 30000 + +#define CONFIG_SENSOR_12 RK29_CAM_SENSOR_OV2659//RK29_CAM_SENSOR_OV2655 /* front camera sensor 2 */ +#define CONFIG_SENSOR_IIC_ADDR_12 0x00 +#define CONFIG_SENSOR_IIC_ADAPTER_ID_12 3 +#define CONFIG_SENSOR_CIF_INDEX_12 0 +#define CONFIG_SENSOR_ORIENTATION_12 270 +#define CONFIG_SENSOR_POWER_PIN_12 INVALID_GPIO +#define CONFIG_SENSOR_RESET_PIN_12 INVALID_GPIO +#define CONFIG_SENSOR_POWERDN_PIN_12 INVALID_GPIO +#define CONFIG_SENSOR_FALSH_PIN_12 INVALID_GPIO +#define CONFIG_SENSOR_POWERACTIVE_LEVEL_12 RK29_CAM_POWERACTIVE_L +#define CONFIG_SENSOR_RESETACTIVE_LEVEL_12 RK29_CAM_RESETACTIVE_L +#define CONFIG_SENSOR_POWERDNACTIVE_LEVEL_12 RK29_CAM_POWERDNACTIVE_H +#define CONFIG_SENSOR_FLASHACTIVE_LEVEL_12 RK29_CAM_FLASHACTIVE_L + +#define CONFIG_SENSOR_QCIF_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_240X160_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_QVGA_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_CIF_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_VGA_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_480P_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_SVGA_FPS_FIXED_12 15000 +#define CONFIG_SENSOR_720P_FPS_FIXED_12 30000 + + +#endif //#ifdef CONFIG_VIDEO_RK29 +/*---------------- Camera Sensor Configuration Macro End------------------------*/ +#include "../../../drivers/media/video/rk2928_camera.c" +/*---------------- Camera Sensor Macro Define End ---------*/ + +#define PMEM_CAM_SIZE PMEM_CAM_NECESSARY +/***************************************************************************************** + * camera devices + * author: ddl@rock-chips.com + *****************************************************************************************/ +#ifdef CONFIG_VIDEO_RK29 +#define CONFIG_SENSOR_POWER_IOCTL_USR 0 //define this refer to your board layout +#define CONFIG_SENSOR_RESET_IOCTL_USR 0 +#define CONFIG_SENSOR_POWERDOWN_IOCTL_USR 0 +#define CONFIG_SENSOR_FLASH_IOCTL_USR 0 + +static void rk_cif_power(int on) +{ + struct regulator *ldo_18,*ldo_28; + ldo_28 = regulator_get(NULL, "ldo7"); // vcc28_cif + ldo_18 = regulator_get(NULL, "ldo1"); // vcc18_cif + if (ldo_28 == NULL || IS_ERR(ldo_28) || ldo_18 == NULL || IS_ERR(ldo_18)){ + printk("get cif ldo failed!\n"); + return; + } + if(on == 0){ + regulator_disable(ldo_28); + regulator_put(ldo_28); + regulator_disable(ldo_18); + regulator_put(ldo_18); + mdelay(500); + } + else{ + regulator_set_voltage(ldo_28, 2800000, 2800000); + regulator_enable(ldo_28); + // printk("%s set ldo7 vcc28_cif=%dmV end\n", __func__, regulator_get_voltage(ldo_28)); + regulator_put(ldo_28); + + regulator_set_voltage(ldo_18, 1800000, 1800000); + // regulator_set_suspend_voltage(ldo, 1800000); + regulator_enable(ldo_18); + // printk("%s set ldo1 vcc18_cif=%dmV end\n", __func__, regulator_get_voltage(ldo_18)); + regulator_put(ldo_18); + } +} + +#if CONFIG_SENSOR_POWER_IOCTL_USR +static int sensor_power_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + //#error "CONFIG_SENSOR_POWER_IOCTL_USR is 1, sensor_power_usr_cb function must be writed!!"; + rk_cif_power(on); +} +#endif + +#if CONFIG_SENSOR_RESET_IOCTL_USR +static int sensor_reset_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + #error "CONFIG_SENSOR_RESET_IOCTL_USR is 1, sensor_reset_usr_cb function must be writed!!"; +} +#endif + +#if CONFIG_SENSOR_POWERDOWN_IOCTL_USR +static int sensor_powerdown_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + #error "CONFIG_SENSOR_POWERDOWN_IOCTL_USR is 1, sensor_powerdown_usr_cb function must be writed!!"; +} +#endif + +#if CONFIG_SENSOR_FLASH_IOCTL_USR +static int sensor_flash_usr_cb (struct rk29camera_gpio_res *res,int on) +{ + #error "CONFIG_SENSOR_FLASH_IOCTL_USR is 1, sensor_flash_usr_cb function must be writed!!"; +} +#endif + +static struct rk29camera_platform_ioctl_cb sensor_ioctl_cb = { + #if CONFIG_SENSOR_POWER_IOCTL_USR + .sensor_power_cb = sensor_power_usr_cb, + #else + .sensor_power_cb = NULL, + #endif + + #if CONFIG_SENSOR_RESET_IOCTL_USR + .sensor_reset_cb = sensor_reset_usr_cb, + #else + .sensor_reset_cb = NULL, + #endif + + #if CONFIG_SENSOR_POWERDOWN_IOCTL_USR + .sensor_powerdown_cb = sensor_powerdown_usr_cb, + #else + .sensor_powerdown_cb = NULL, + #endif + + #if CONFIG_SENSOR_FLASH_IOCTL_USR + .sensor_flash_cb = sensor_flash_usr_cb, + #else + .sensor_flash_cb = NULL, + #endif +}; + +#if CONFIG_SENSOR_IIC_ADDR_0 +static struct reginfo_t rk_init_data_sensor_reg_0[] = +{ + {0x0000, 0x00,0,0} + }; +static struct reginfo_t rk_init_data_sensor_winseqreg_0[] ={ + {0x0000, 0x00,0,0} + }; +#endif + +#if CONFIG_SENSOR_IIC_ADDR_1 +static struct reginfo_t rk_init_data_sensor_reg_1[] = +{ + {0x0000, 0x00,0,0} +}; +static struct reginfo_t rk_init_data_sensor_winseqreg_1[] = +{ + {0x0000, 0x00,0,0} +}; +#endif +#if CONFIG_SENSOR_IIC_ADDR_01 +static struct reginfo_t rk_init_data_sensor_reg_01[] = +{ + {0x0000, 0x00,0,0} +}; +static struct reginfo_t rk_init_data_sensor_winseqreg_01[] = +{ + {0x0000, 0x00,0,0} +}; +#endif +#if CONFIG_SENSOR_IIC_ADDR_02 +static struct reginfo_t rk_init_data_sensor_reg_02[] = +{ + {0x0000, 0x00,0,0} +}; +static struct reginfo_t rk_init_data_sensor_winseqreg_02[] = +{ + {0x0000, 0x00,0,0} +}; +#endif +#if CONFIG_SENSOR_IIC_ADDR_11 +static struct reginfo_t rk_init_data_sensor_reg_11[] = +{ + {0x0000, 0x00,0,0} +}; +static struct reginfo_t rk_init_data_sensor_winseqreg_11[] = +{ + {0x0000, 0x00,0,0} +}; +#endif +#if CONFIG_SENSOR_IIC_ADDR_12 +static struct reginfo_t rk_init_data_sensor_reg_12[] = +{ + {0x0000, 0x00,0,0} +}; +static struct reginfo_t rk_init_data_sensor_winseqreg_12[] = +{ + {0x0000, 0x00,0,0} +}; +#endif +static rk_sensor_user_init_data_s rk_init_data_sensor[RK_CAM_NUM] = +{ + #if CONFIG_SENSOR_IIC_ADDR_0 + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = rk_init_data_sensor_reg_0, + .rk_sensor_init_winseq = rk_init_data_sensor_winseqreg_0, + .rk_sensor_winseq_size = sizeof(rk_init_data_sensor_winseqreg_0) / sizeof(struct reginfo_t), + .rk_sensor_init_data_size = sizeof(rk_init_data_sensor_reg_0) / sizeof(struct reginfo_t), + }, + #else + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = NULL, + .rk_sensor_init_winseq = NULL, + .rk_sensor_winseq_size = 0, + .rk_sensor_init_data_size = 0, + }, + #endif + #if CONFIG_SENSOR_IIC_ADDR_1 + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = rk_init_data_sensor_reg_1, + .rk_sensor_init_winseq = rk_init_data_sensor_winseqreg_1, + .rk_sensor_winseq_size = sizeof(rk_init_data_sensor_winseqreg_1) / sizeof(struct reginfo_t), + .rk_sensor_init_data_size = sizeof(rk_init_data_sensor_reg_1) / sizeof(struct reginfo_t), + }, + #else + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = NULL, + .rk_sensor_init_winseq = NULL, + .rk_sensor_winseq_size = 0, + .rk_sensor_init_data_size = 0, + }, + #endif + #if CONFIG_SENSOR_IIC_ADDR_01 + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = rk_init_data_sensor_reg_01, + .rk_sensor_init_winseq = rk_init_data_sensor_winseqreg_01, + .rk_sensor_winseq_size = sizeof(rk_init_data_sensor_winseqreg_01) / sizeof(struct reginfo_t), + .rk_sensor_init_data_size = sizeof(rk_init_data_sensor_reg_01) / sizeof(struct reginfo_t), + }, + #else + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = NULL, + .rk_sensor_init_winseq = NULL, + .rk_sensor_winseq_size = 0, + .rk_sensor_init_data_size = 0, + }, + #endif + #if CONFIG_SENSOR_IIC_ADDR_02 + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = rk_init_data_sensor_reg_02, + .rk_sensor_init_winseq = rk_init_data_sensor_winseqreg_02, + .rk_sensor_winseq_size = sizeof(rk_init_data_sensor_winseqreg_02) / sizeof(struct reginfo_t), + .rk_sensor_init_data_size = sizeof(rk_init_data_sensor_reg_02) / sizeof(struct reginfo_t), + }, + #else + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = NULL, + .rk_sensor_init_winseq = NULL, + .rk_sensor_winseq_size = 0, + .rk_sensor_init_data_size = 0, + }, + #endif + #if CONFIG_SENSOR_IIC_ADDR_11 + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = rk_init_data_sensor_reg_11, + .rk_sensor_init_winseq = rk_init_data_sensor_winseqreg_11, + .rk_sensor_winseq_size = sizeof(rk_init_data_sensor_winseqreg_11) / sizeof(struct reginfo_t), + .rk_sensor_init_data_size = sizeof(rk_init_data_sensor_reg_11) / sizeof(struct reginfo_t), + }, + #else + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = NULL, + .rk_sensor_init_winseq = NULL, + .rk_sensor_winseq_size = 0, + .rk_sensor_init_data_size = 0, + }, + #endif + #if CONFIG_SENSOR_IIC_ADDR_12 + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = rk_init_data_sensor_reg_12, + .rk_sensor_init_winseq = rk_init_data_sensor_winseqreg_12, + .rk_sensor_winseq_size = sizeof(rk_init_data_sensor_winseqreg_12) / sizeof(struct reginfo_t), + .rk_sensor_init_data_size = sizeof(rk_init_data_sensor_reg_12) / sizeof(struct reginfo_t), + }, + #else + { + .rk_sensor_init_width = INVALID_VALUE, + .rk_sensor_init_height = INVALID_VALUE, + .rk_sensor_init_bus_param = INVALID_VALUE, + .rk_sensor_init_pixelcode = INVALID_VALUE, + .rk_sensor_init_data = NULL, + .rk_sensor_init_winseq = NULL, + .rk_sensor_winseq_size = 0, + .rk_sensor_init_data_size = 0, + }, + #endif + + }; +#include "../../../drivers/media/video/rk2928_camera.c" + +#endif /* CONFIG_VIDEO_RK29 */ diff --git a/arch/arm/mach-rk2928/board-rk2928-a720.c b/arch/arm/mach-rk2928/board-rk2928-a720.c index 5808b81359cb..0bc1895fc61b 100755 --- a/arch/arm/mach-rk2928/board-rk2928-a720.c +++ b/arch/arm/mach-rk2928/board-rk2928-a720.c @@ -54,6 +54,7 @@ #include "../../../drivers/spi/rk29_spim.h" #endif +#include "board-rk2928-a720-camera.c" #include "board-rk2928-a720-key.c" #ifdef CONFIG_THREE_FB_BUFFER @@ -259,13 +260,51 @@ static struct platform_device device_ion = { }; #endif + +#if defined(CONFIG_TOUCHSCREEN_SITRONIX_A720) + +#define TOUCH_RESET_PIN RK2928_PIN1_PA3 +#define TOUCH_INT_PIN RK2928_PIN1_PB3 +int ft5306_init_platform_hw(void) +{ + + //printk("ft5306_init_platform_hw\n"); + if(gpio_request(TOUCH_RESET_PIN,NULL) != 0){ + gpio_free(TOUCH_RESET_PIN); + printk("ft5306_init_platform_hw gpio_request error\n"); + return -EIO; + } + + if(gpio_request(TOUCH_INT_PIN,NULL) != 0){ + gpio_free(TOUCH_INT_PIN); + printk("ift5306_init_platform_hw gpio_request error\n"); + return -EIO; + } + gpio_direction_output(TOUCH_RESET_PIN, GPIO_HIGH); + mdelay(10); + gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW); + mdelay(10); + gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH); + msleep(300); + return 0; + +} + +struct ft5x0x_platform_data sitronix_info = { + .model = 5007, + .init_platform_hw= ft5306_init_platform_hw, +}; + +#endif + + /*MMA7660 gsensor*/ #if defined (CONFIG_GS_MMA7660) #define MMA7660_INT_PIN RK2928_PIN1_PB1 static int mma7660_init_platform_hw(void) { - rk30_mux_api_set(GPIO4C0_SMCDATA0_TRACEDATA0_NAME, GPIO4C_GPIO4C0); + rk30_mux_api_set(GPIO1B1_SPI_TXD_UART1_SOUT_NAME, GPIO1B_GPIO1B1); return 0; } @@ -332,8 +371,70 @@ struct platform_device pwm_regulator_device[1] = { } }, }; +#endif +/************************************************************************************************** + * SDMMC devices, include the module of SD,MMC,and sdio.noted by xbw at 2012-03-05 +**************************************************************************************************/ +#ifdef CONFIG_SDMMC_RK29 +#include "board-rk2928-sdk-sdmmc.c" + +#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) +#define SDMMC0_WRITE_PROTECT_PIN RK2928_PIN1_PA7 //According to your own project to set the value of write-protect-pin. +#endif + +#if defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT) +#define SDMMC1_WRITE_PROTECT_PIN RK2928_PIN0_PD5 //According to your own project to set the value of write-protect-pin. +#endif + +#define RK29SDK_WIFI_SDIO_CARD_DETECT_N RK2928_PIN0_PB2 + +#endif //endif ---#ifdef CONFIG_SDMMC_RK29 + +#ifdef CONFIG_SDMMC0_RK29 +static int rk29_sdmmc0_cfg_gpio(void) +{ + rk29_sdmmc_set_iomux(0, 0xFFFF); + + rk30_mux_api_set(GPIO1C1_MMC0_DETN_NAME, GPIO1C_MMC0_DETN); + +#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) + gpio_request(SDMMC0_WRITE_PROTECT_PIN, "sdmmc-wp"); + gpio_direction_input(SDMMC0_WRITE_PROTECT_PIN); #endif + return 0; +} + +#define CONFIG_SDMMC0_USE_DMA +struct rk29_sdmmc_platform_data default_sdmmc0_data = { + .host_ocr_avail = + (MMC_VDD_25_26 | MMC_VDD_26_27 | MMC_VDD_27_28 | MMC_VDD_28_29 | + MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | + MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36), + .host_caps = + (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED), + .io_init = rk29_sdmmc0_cfg_gpio, + +#if !defined(CONFIG_SDMMC_RK29_OLD) + .set_iomux = rk29_sdmmc_set_iomux, +#endif + + .dma_name = "sd_mmc", +#ifdef CONFIG_SDMMC0_USE_DMA + .use_dma = 1, +#else + .use_dma = 0, +#endif + .detect_irq = RK2928_PIN1_PC1, // INVALID_GPIO + .enable_sd_wakeup = 0, + +#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) + .write_prt = SDMMC0_WRITE_PROTECT_PIN, +#else + .write_prt = INVALID_GPIO, +#endif +}; +#endif // CONFIG_SDMMC0_RK29 static struct platform_device *devices[] __initdata = { #ifdef CONFIG_BACKLIGHT_RK29_BL @@ -380,6 +481,15 @@ static struct i2c_board_info __initdata i2c1_info[] = { #endif #ifdef CONFIG_I2C2_RK30 static struct i2c_board_info __initdata i2c2_info[] = { +#if defined (CONFIG_TOUCHSCREEN_SITRONIX_A720) +{ + .type ="sitronix", + .addr = 0x38, + .flags = 0, + .irq = TOUCH_INT_PIN, + .platform_data = &sitronix_info, +}, +#endif }; #endif #ifdef CONFIG_I2C3_RK30 @@ -426,7 +536,7 @@ static void __init rk30_i2c_register_board_info(void) } //end of i2c -#define POWER_ON_PIN RK2928_PIN1_PA4 //power_hold +#define POWER_ON_PIN RK2928_PIN1_PA2 //power_hold static void rk2928_pm_power_off(void) { printk(KERN_ERR "rk2928_pm_power_off start...\n"); @@ -481,8 +591,8 @@ static struct dvfs_arm_table dvfs_cpu_logic_table[] = { {.frequency = 600 * 1000, .cpu_volt = 1200 * 1000, .logic_volt = 1200 * 1000},//1.025V/1.050V {.frequency = 696 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.000V/1.025V {.frequency = 816 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V - {.frequency = 912 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V - {.frequency = 1008 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V + //{.frequency = 912 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V + //{.frequency = 1008 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V #if 0 {.frequency = 1104 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V {.frequency = 1200 * 1000, .cpu_volt = 1400 * 1000, .logic_volt = 1200 * 1000},//1.100V/1.050V diff --git a/arch/arm/mach-rk2928/include/mach/board.h b/arch/arm/mach-rk2928/include/mach/board.h index 9292adca4591..f6d6e99b2bdd 100644 --- a/arch/arm/mach-rk2928/include/mach/board.h +++ b/arch/arm/mach-rk2928/include/mach/board.h @@ -57,6 +57,16 @@ struct eeti_egalax_platform_data{ }; #endif +#if defined (CONFIG_TOUCHSCREEN_SITRONIX_A720) +struct ft5x0x_platform_data{ + u16 model; + int (*get_pendown_state)(void); + int (*init_platform_hw)(void); + int (*ft5x0x_platform_sleep)(void); + int (*ft5x0x_platform_wakeup)(void); + void (*exit_platform_hw)(void); +}; +#endif enum _periph_pll { periph_pll_1485mhz = 148500000, periph_pll_297mhz = 297000000, diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 6e95e5098039..50d915718bcc 100755 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -969,9 +969,6 @@ config LAIBAO_TS config TOUCHSCREEN_GT801_IIC tristate "GT801_IIC based touchscreens" depends on I2C2_RK29 -config TOUCHSCREEN_GT82X_IIC - tristate "GT82x_IIC based touchscreens" - depends on I2C2_RK30 config TOUCHSCREEN_GT818_IIC tristate "GT818_IIC based touchscreens" @@ -1002,6 +999,10 @@ config TOUCHSCREEN_FT5306 tristate "FT5306 based touchscreens: FT5306 Interface" depends on I2C2_RK29 || I2C2_RK30 +config TOUCHSCREEN_SITRONIX_A720 + tristate "SITRONIX based touchscreens: SITRONIX Interface for a720" + depends on I2C2_RK29 || I2C2_RK30 + config TOUCHSCREEN_FT5306_WPX2 tristate "FT5306 based touchscreens: FT5306 Interface,only used for umeox wpx2 board" depends on I2C2_RK29 || I2C2_RK30 diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index d64b4a9063f5..7b28f1998469 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_D70_L3188A) += goodix_touch.o obj-$(CONFIG_TOUCHSCREEN_GT8XX) += rk29_i2c_goodix.o obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5406_ts.o obj-$(CONFIG_TOUCHSCREEN_FT5306) += ft5306_ts.o +obj-$(CONFIG_TOUCHSCREEN_SITRONIX_A720) += sitronix_ts_a720.o obj-$(CONFIG_TOUCHSCREEN_FT5306_WPX2) += ft5306_ts_wpx2.o obj-$(CONFIG_TOUCHSCREEN_GT819) += gt819.o obj-$(CONFIG_TOUCHSCREEN_NAS) += nas_ts.o diff --git a/drivers/input/touchscreen/sitronix_ts_a720.c b/drivers/input/touchscreen/sitronix_ts_a720.c new file mode 100755 index 000000000000..7e8922dec869 --- /dev/null +++ b/drivers/input/touchscreen/sitronix_ts_a720.c @@ -0,0 +1,1233 @@ +/* + * drivers/input/touchscreen/sitronix_i2c_touch.c + * + * Touchscreen driver for Sitronix (I2C bus) + * + * Copyright (C) 2011 Sitronix Technology Co., Ltd. + * Rudy Huang + */ +/* + * 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 +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif // CONFIG_HAS_EARLYSUSPEND +#include "sitronix_ts_a720.h" +#ifdef SITRONIX_FW_UPGRADE_FEATURE +#include +#include +#endif // SITRONIX_FW_UPGRADE_FEATURE +#include +#include +#include +#include // to be compatible with linux kernel 3.2.15 +#include +#include +#include + +#ifdef SITRONIX_MONITOR_THREAD +#include +//#include +#endif // SITRONIX_MONITOR_THREAD + +#define DRIVER_AUTHOR "Sitronix, Inc." +#define DRIVER_NAME "sitronix" +#define DRIVER_DESC "Sitronix I2C touch" +#define DRIVER_DATE "20120507" +#define DRIVER_MAJOR 2 +#define DRIVER_MINOR 9 +#define DRIVER_PATCHLEVEL 1 + +MODULE_AUTHOR("Rudy Huang "); +MODULE_DESCRIPTION("Sitronix I2C multitouch panels"); +MODULE_LICENSE("GPL"); + +#ifdef SITRONIX_SENSOR_KEY +#define SITRONIX_NUMBER_SENSOR_KEY 3 +int sitronix_sensor_key[SITRONIX_NUMBER_SENSOR_KEY] = { + KEY_BACK, // bit 0 + KEY_HOMEPAGE,//KEY_HOME, // bit 1 + KEY_MENU, // bit 2 +}; +#endif // SITRONIX_SENSOR_KEY + +#ifdef SITRONIX_TOUCH_KEY +#define SITRONIX_NUMBER_TOUCH_KEY 4 + +#ifdef SITRONIX_KEY_BOUNDARY_MANUAL_SPECIFY +#define SITRONIX_TOUCH_RESOLUTION_X 480 /* max of X value in display area */ +#define SITRONIX_TOUCH_RESOLUTION_Y 854 /* max of Y value in display area */ +#define SITRONIX_TOUCH_GAP_Y 10 /* Gap between bottom of display and top of touch key */ +#define SITRONIX_TOUCH_MAX_Y 915 /* resolution of y axis of touch ic */ +struct sitronix_AA_key sitronix_key_array[SITRONIX_NUMBER_TOUCH_KEY] = { + {15, 105, SITRONIX_TOUCH_RESOLUTION_Y + SITRONIX_TOUCH_GAP_Y, SITRONIX_TOUCH_MAX_Y, KEY_MENU}, /* MENU */ + {135, 225, SITRONIX_TOUCH_RESOLUTION_Y + SITRONIX_TOUCH_GAP_Y, SITRONIX_TOUCH_MAX_Y, KEY_HOME}, + {255, 345, SITRONIX_TOUCH_RESOLUTION_Y + SITRONIX_TOUCH_GAP_Y, SITRONIX_TOUCH_MAX_Y, KEY_BACK}, /* KEY_EXIT */ + {375, 465, SITRONIX_TOUCH_RESOLUTION_Y + SITRONIX_TOUCH_GAP_Y, SITRONIX_TOUCH_MAX_Y, KEY_SEARCH}, +}; +#else +#define SCALE_KEY_HIGH_Y 15 +struct sitronix_AA_key sitronix_key_array[SITRONIX_NUMBER_TOUCH_KEY] = { + {0, 0, 0, 0, KEY_MENU}, /* MENU */ + {0, 0, 0, 0, KEY_HOME}, + {0, 0, 0, 0, KEY_BACK}, /* KEY_EXIT */ + {0, 0, 0, 0, KEY_SEARCH}, +}; + +#endif // SITRONIX_KEY_BOUNDARY_MANUAL_SPECIFY +#endif // SITRONIX_TOUCH_KEY +struct sitronix_ts_data { + uint16_t addr; + struct i2c_client *client; + struct input_dev *input_dev; +#if defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + struct input_dev *keyevent_input; +#endif // defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + int use_irq; + struct hrtimer timer; +#ifndef SITRONIX_INT_POLLING_MODE + struct work_struct work; +#else + struct delayed_work work; +#endif // SITRONIX_INT_POLLING_MODE + void (*reset_ic)(void); +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif // CONFIG_HAS_EARLYSUSPEND + uint8_t fw_revision[4]; + int resolution_x; + int resolution_y; + uint8_t max_touches; + uint8_t touch_protocol_type; + uint8_t pixel_length; + int suspend_state; +}; + +static unsigned char initkey_code[] = +{ + KEY_BACK, KEY_HOMEPAGE, KEY_MENU +}; + +static int i2cErrorCount = 0; + +#ifdef SITRONIX_MONITOR_THREAD +static struct task_struct * SitronixMonitorThread = NULL; +static int gMonitorThreadSleepInterval = 300; // 0.3 sec +static atomic_t iMonitorThreadPostpone = ATOMIC_INIT(0); + +static uint8_t PreCheckData[4] ; +static int StatusCheckCount = 0; +static int sitronix_ts_monitor_thread(void *data); +static int sitronix_ts_delay_monitor_thread_start = DELAY_MONITOR_THREAD_START_PROBE; +#endif // SITRONIX_MONITOR_THREAD + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void sitronix_ts_early_suspend(struct early_suspend *h); +static void sitronix_ts_late_resume(struct early_suspend *h); +#endif // CONFIG_HAS_EARLYSUSPEND + +static MTD_STRUCTURE sitronix_ts_gMTDPreStructure[SITRONIX_MAX_SUPPORTED_POINT]={{0}}; + +static struct sitronix_ts_data *sitronix_ts_gpts = NULL; +static int sitronix_ts_irq_on = 0; + +#ifdef SITRONIX_FW_UPGRADE_FEATURE +int sitronix_release(struct inode *, struct file *); +int sitronix_open(struct inode *, struct file *); +ssize_t sitronix_write(struct file *file, const char *buf, size_t count, loff_t *ppos); +ssize_t sitronix_read(struct file *file, char *buf, size_t count, loff_t *ppos); +long sitronix_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +static struct cdev sitronix_cdev; +static struct class *sitronix_class; +static int sitronix_major = 0; + +int sitronix_open(struct inode *inode, struct file *filp) +{ + return 0; +} +EXPORT_SYMBOL(sitronix_open); + +int sitronix_release(struct inode *inode, struct file *filp) +{ + return 0; +} +EXPORT_SYMBOL(sitronix_release); + +ssize_t sitronix_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + int ret; + char *tmp; + + if (count > 8192) + count = 8192; + + tmp = (char *)kmalloc(count,GFP_KERNEL); + if (tmp==NULL) + return -ENOMEM; + if (copy_from_user(tmp,buf,count)) { + kfree(tmp); + return -EFAULT; + } + UpgradeMsg("writing %zu bytes.\n", count); + + ret = i2c_master_send(sitronix_ts_gpts->client, tmp, count); + kfree(tmp); + return ret; +} +EXPORT_SYMBOL(sitronix_write); + +ssize_t sitronix_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + char *tmp; + int ret; + + if (count > 8192) + count = 8192; + + tmp = (char *)kmalloc(count,GFP_KERNEL); + if (tmp==NULL) + return -ENOMEM; + + UpgradeMsg("reading %zu bytes.\n", count); + + ret = i2c_master_recv(sitronix_ts_gpts->client, tmp, count); + if (ret >= 0) + ret = copy_to_user(buf,tmp,count)?-EFAULT:ret; + kfree(tmp); + return ret; +} +EXPORT_SYMBOL(sitronix_read); + +static int sitronix_ts_resume(struct i2c_client *client); +static int sitronix_ts_suspend(struct i2c_client *client, pm_message_t mesg); +long sitronix_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int err = 0; + int retval = 0; + uint8_t temp[4]; + + if (_IOC_TYPE(cmd) != SMT_IOC_MAGIC) return -ENOTTY; + if (_IOC_NR(cmd) > SMT_IOC_MAXNR) return -ENOTTY; + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE,(void __user *)arg,\ + _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ,(void __user *)arg,\ + _IOC_SIZE(cmd)); + if (err) return -EFAULT; + + switch(cmd) { + case IOCTL_SMT_GET_DRIVER_REVISION: + UpgradeMsg("IOCTL_SMT_GET_DRIVER_REVISION\n"); + temp[0] = SITRONIX_TOUCH_DRIVER_VERSION; + if(copy_to_user((uint8_t __user *)arg, &temp[0], 1)){ + UpgradeMsg("fail to get driver version\n"); + retval = -EFAULT; + } + break; + case IOCTL_SMT_GET_FW_REVISION: + UpgradeMsg("IOCTL_SMT_GET_FW_REVISION\n"); + if(copy_to_user((uint8_t __user *)arg, &sitronix_ts_gpts->fw_revision[0], 4)) + retval = -EFAULT; + break; + case IOCTL_SMT_ENABLE_IRQ: + UpgradeMsg("IOCTL_SMT_ENABLE_IRQ\n"); + if(!sitronix_ts_irq_on){ + sitronix_ts_irq_on = 1; + enable_irq(sitronix_ts_gpts->client->irq); +#ifdef SITRONIX_MONITOR_THREAD + atomic_set(&iMonitorThreadPostpone,1); + SitronixMonitorThread = kthread_run(sitronix_ts_monitor_thread,"Sitronix","Monitorthread"); + if(IS_ERR(SitronixMonitorThread)) + SitronixMonitorThread = NULL; +#endif // SITRONIX_MONITOR_THREAD + } + break; + case IOCTL_SMT_DISABLE_IRQ: + UpgradeMsg("IOCTL_SMT_DISABLE_IRQ\n"); + if(sitronix_ts_irq_on){ + sitronix_ts_irq_on = 0; + disable_irq_nosync(sitronix_ts_gpts->client->irq); +#ifdef SITRONIX_MONITOR_THREAD + if(SitronixMonitorThread){ + kthread_stop(SitronixMonitorThread); + SitronixMonitorThread = NULL; + } +#endif // SITRONIX_MONITOR_THREAD + } + break; + case IOCTL_SMT_RESUME: + UpgradeMsg("IOCTL_SMT_RESUME\n"); + sitronix_ts_resume(sitronix_ts_gpts->client); + break; + case IOCTL_SMT_SUSPEND: + UpgradeMsg("IOCTL_SMT_SUSPEND\n"); + sitronix_ts_suspend(sitronix_ts_gpts->client, PMSG_SUSPEND); + break; + case IOCTL_SMT_HW_RESET: + UpgradeMsg("IOCTL_SMT_HW_RESET\n"); + if(sitronix_ts_gpts->reset_ic) + sitronix_ts_gpts->reset_ic(); + break; + default: + retval = -ENOTTY; + } + + return retval; +} +EXPORT_SYMBOL(sitronix_ioctl); +#endif // SITRONIX_FW_UPGRADE_FEATURE + +static int sitronix_get_fw_revision(struct sitronix_ts_data *ts) +{ + int ret = 0; + uint8_t buffer[4]; + + buffer[0] = FIRMWARE_REVISION_3; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send fw revision command error (%d)\n", ret); + return ret; + } + ret = i2c_master_recv(ts->client, buffer, 4); + if (ret < 0){ + printk("read fw revision error (%d)\n", ret); + return ret; + }else{ + memcpy(ts->fw_revision, buffer, 4); + printk("fw revision (hex) = %x %x %x %x\n", buffer[0], buffer[1], buffer[2], buffer[3]); + } + return 0; +} + +static int sitronix_get_max_touches(struct sitronix_ts_data *ts) +{ + int ret = 0; + uint8_t buffer[1]; + + buffer[0] = MAX_NUM_TOUCHES; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send max touches command error (%d)\n", ret); + return ret; + } + ret = i2c_master_recv(ts->client, buffer, 1); + if (ret < 0){ + printk("read max touches error (%d)\n", ret); + return ret; + }else{ + ts->max_touches = buffer[0]; + printk("max touches = %d \n",ts->max_touches); + } + return 0; +} + +static int sitronix_get_protocol_type(struct sitronix_ts_data *ts) +{ + int ret = 0; + uint8_t buffer[1]; + + buffer[0] = I2C_PROTOCOL; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send i2c protocol command error (%d)\n", ret); + return ret; + } + ret = i2c_master_recv(ts->client, buffer, 1); + if (ret < 0){ + printk("read i2c protocol error (%d)\n", ret); + return ret; + }else{ + ts->touch_protocol_type = buffer[0] & I2C_PROTOCOL_BMSK; + if(ts->touch_protocol_type == SITRONIX_A_TYPE) + ts->pixel_length = PIXEL_DATA_LENGTH_A; + else if(ts->touch_protocol_type == SITRONIX_B_TYPE) + ts->pixel_length = PIXEL_DATA_LENGTH_B; + else + ts->pixel_length = PIXEL_DATA_LENGTH_A; + printk("i2c protocol = %d \n", ts->touch_protocol_type); + } + return 0; +} + +static int sitronix_get_resolution(struct sitronix_ts_data *ts) +{ + int ret = 0; + uint8_t buffer[3]; + + buffer[0] = XY_RESOLUTION_HIGH; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send resolution command error (%d)\n", ret); + return ret; + } + ret = i2c_master_recv(ts->client, buffer, 3); + if (ret < 0){ + printk("read resolution error (%d)\n", ret); + return ret; + }else{ + ts->resolution_x = ((buffer[0] & (X_RES_H_BMSK << X_RES_H_SHFT)) << 4) | buffer[1]; + ts->resolution_y = ((buffer[0] & Y_RES_H_BMSK) << 8) | buffer[2]; + printk("resolution = %d x %d\n", ts->resolution_x, ts->resolution_y); + } + return 0; +} + +static int sitronix_ts_set_powerdown_bit(struct sitronix_ts_data *ts, int value) +{ + int ret = 0; + uint8_t buffer[2]; + + DbgMsg("%s, value = %d\n", __FUNCTION__, value); + buffer[0] = DEVICE_CONTROL_REG; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send device control command error (%d)\n", ret); + return ret; + } + + ret = i2c_master_recv(ts->client, buffer, 1); + if (ret < 0){ + printk("read device control status error (%d)\n", ret); + return ret; + }else{ + DbgMsg("dev status = %d \n", buffer[0]); + } + + if(value == 0) + buffer[1] = buffer[0] & 0xfd; + else + buffer[1] = buffer[0] | 0x2; + + buffer[0] = DEVICE_CONTROL_REG; + ret = i2c_master_send(ts->client, buffer, 2); + if (ret < 0){ + printk("write power down error (%d)\n", ret); + return ret; + } + + return 0; +} + +static int sitronix_ts_get_touch_info(struct sitronix_ts_data *ts) +{ + int ret = 0; + ret = sitronix_get_resolution(ts); + if(ret < 0) + return ret; + ret = sitronix_get_fw_revision(ts); + if(ret < 0) + return ret; + if((ts->fw_revision[0] == 0) && (ts->fw_revision[1] == 0)){ + ts->touch_protocol_type = SITRONIX_B_TYPE; + ts->pixel_length = PIXEL_DATA_LENGTH_B; + ts->max_touches = 2; + printk("i2c protocol = %d \n", ts->touch_protocol_type); + printk("max touches = %d \n",ts->max_touches); + }else{ + ret = sitronix_get_protocol_type(ts); + if(ret < 0) + return ret; + if(ts->touch_protocol_type == SITRONIX_B_TYPE){ + ts->max_touches = 2; + printk("max touches = %d \n",ts->max_touches); + }else{ + ret = sitronix_get_max_touches(ts); + if(ret < 0) + return ret; + } + } + return 0; +} + +static int sitronix_ts_get_device_status(struct sitronix_ts_data *ts, uint8_t *dev_status) +{ + int ret = 0; + uint8_t buffer[8]; + + DbgMsg("%s\n", __FUNCTION__); + buffer[0] = STATUS_REG; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send status reg command error (%d)\n", ret); + return ret; + } + + ret = i2c_master_recv(ts->client, buffer, 8); + if (ret < 0){ + printk("read status reg error (%d)\n", ret); + return ret; + }else{ + DbgMsg("status reg = %d \n", buffer[0]); + } + + *dev_status = buffer[0] & 0xf; + + return 0; +} + +static int sitronix_ts_Enhance_Function_control(struct sitronix_ts_data *ts, uint8_t *value) +{ + int ret = 0; + uint8_t buffer[4]; + + DbgMsg("%s\n", __FUNCTION__); + buffer[0] = 0xF0; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send Enhance Function command error (%d)\n", ret); + return ret; + } + + ret = i2c_master_recv(ts->client, buffer, 1); + if (ret < 0){ + printk("read Enhance Functions status error (%d)\n", ret); + return ret; + }else{ + DbgMsg("Enhance Functions status = %d \n", buffer[0]); + } + + *value = buffer[0] & 0x4; + + return 0; +} + +static int sitronix_ts_FW_Bank_Select(struct sitronix_ts_data *ts, uint8_t value) +{ + int ret = 0; + uint8_t buffer[1]; + + DbgMsg("%s\n", __FUNCTION__); + buffer[0] = 0xF1; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send FW Bank Select command error (%d)\n", ret); + return ret; + } + + ret = i2c_master_recv(ts->client, buffer, 1); + if (ret < 0){ + printk("read FW Bank Select status error (%d)\n", ret); + return ret; + }else{ + DbgMsg("FW Bank Select status = %d \n", buffer[0]); + } + + buffer[1] = ((buffer[0] & 0xfc) | value); + buffer[0] = 0xF1; + ret = i2c_master_send(ts->client, buffer, 2); + if (ret < 0){ + printk("send FW Bank Select command error (%d)\n", ret); + return ret; + } + + return 0; +} + +static int sitronix_get_id_info(struct sitronix_ts_data *ts, uint8_t *id_info) +{ + int ret = 0; + uint8_t buffer[4]; + + buffer[0] = 0x0C; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0){ + printk("send id info command error (%d)\n", ret); + return ret; + } + ret = i2c_master_recv(ts->client, buffer, 4); + if (ret < 0){ + printk("read id info error (%d)\n", ret); + return ret; + }else{ + memcpy(id_info, buffer, 4); + } + return 0; +} + +static int sitronix_ts_identify(struct sitronix_ts_data *ts) +{ + int ret = 0; + uint8_t id[4]; + uint8_t Enhance_Function = 0; + + ret = sitronix_ts_FW_Bank_Select(ts, 1); + if(ret < 0) + return ret; + ret = sitronix_ts_Enhance_Function_control(ts, &Enhance_Function); + if(ret < 0) + return ret; + if(Enhance_Function == 0x4){ + ret = sitronix_get_id_info(ts, &id[0]); + if(ret < 0) + return ret; + printk("id (hex) = %x %x %x %x\n", id[0], id[1], id[2], id[3]); + if((id[0] == 1)&&(id[1] == 2)&&(id[2] == 0xb)&&(id[3] == 1)){ + return 0; + }else{ + printk("Error: It is not Sitronix IC\n"); + return -1; + } + }else{ + printk("Error: Can not get ID of Sitronix IC\n"); + return -1; + } +} + +#ifdef SITRONIX_MONITOR_THREAD +static int sitronix_ts_monitor_thread(void *data) +{ + int ret = 0; + uint8_t buffer[4]; + int result = 0; + int once = 1; + DbgMsg("%s:\n", __FUNCTION__); + + printk("delay %d ms\n", sitronix_ts_delay_monitor_thread_start); + msleep(sitronix_ts_delay_monitor_thread_start); + while(!kthread_should_stop()){ + DbgMsg("%s:\n", "Sitronix_ts_monitoring"); + if(atomic_read(&iMonitorThreadPostpone)){ + atomic_set(&iMonitorThreadPostpone,0); + }else{ + if(once == 1){ + buffer[0] = DEVICE_CONTROL_REG; + ret = i2c_master_send(sitronix_ts_gpts->client, buffer, 1); + if (ret < 0){ + DbgMsg("send device control command error (%d)\n", ret); + goto exit_i2c_invalid; + } + ret = i2c_master_recv(sitronix_ts_gpts->client, buffer, 1); + if (ret < 0){ + DbgMsg("read device control status error (%d)\n", ret); + goto exit_i2c_invalid; + }else{ + DbgMsg("read DEVICE_CONTROL_REG status = %d \n", buffer[0]); + } + buffer[0] &= 0xf3; + ret = i2c_master_send(sitronix_ts_gpts->client, buffer, 1); + if (ret < 0){ + DbgMsg("write power down error (%d)\n", ret); + goto exit_i2c_invalid; + } + once = 0; + } + buffer[0] = 0x40; + ret = i2c_master_send(sitronix_ts_gpts->client, buffer, 1); + if (ret < 0){ + DbgMsg("send device control command error (%d)\n", ret); + goto exit_i2c_invalid; + } + ret = i2c_master_recv(sitronix_ts_gpts->client, buffer, 4); + if (ret < 0){ + DbgMsg("read device 1D data error (%d)\n", ret); + goto exit_i2c_invalid; + }else{ + DbgMsg("1D data h40-43 = %d, %d, %d, %d \n", buffer[0], buffer[1], buffer[2], buffer[3]); + result = 1; + if ((PreCheckData[0] == buffer[0]) && (PreCheckData[1] == buffer[1]) && + (PreCheckData[2] == buffer[2]) && (PreCheckData[3] == buffer[3])) + StatusCheckCount ++; + else + StatusCheckCount =0; + PreCheckData[0] = buffer[0]; + PreCheckData[1] = buffer[1]; + PreCheckData[2] = buffer[2]; + PreCheckData[3] = buffer[3]; + if (3 <= StatusCheckCount){ + DbgMsg("IC Status doesn't update! \n"); + result = -1; + StatusCheckCount = 0; + } + } + if (-1 == result){ + printk("Chip abnormal, reset it!\n"); + if(sitronix_ts_gpts->reset_ic) + sitronix_ts_gpts->reset_ic(); + i2cErrorCount = 0; + StatusCheckCount = 0; + } +exit_i2c_invalid: + if(0 == result){ + i2cErrorCount ++; + if ((2 <= i2cErrorCount)){ + printk("I2C abnormal, reset it!\n"); + if(sitronix_ts_gpts->reset_ic) + sitronix_ts_gpts->reset_ic(); + i2cErrorCount = 0; + StatusCheckCount = 0; + } + }else + i2cErrorCount = 0; + } + msleep(gMonitorThreadSleepInterval); + } + DbgMsg("%s exit\n", __FUNCTION__); + return 0; +} +#endif // SITRONIX_MONITOR_THREAD + +static void sitronix_ts_work_func(struct work_struct *work) +{ + int tmp = 0, i = 0; +#ifdef SITRONIX_TOUCH_KEY + int j; +#endif // SITRONIX_TOUCH_KEY + int ret; +#ifndef SITRONIX_INT_POLLING_MODE + struct sitronix_ts_data *ts = container_of(work, struct sitronix_ts_data, work); +#else + struct sitronix_ts_data *ts = container_of(to_delayed_work(work), struct sitronix_ts_data, work); +#endif // SITRONIX_INT_POLLING_MODE + uint8_t buffer[2+ SITRONIX_MAX_SUPPORTED_POINT * PIXEL_DATA_LENGTH_A]; + static MTD_STRUCTURE MTDStructure[SITRONIX_MAX_SUPPORTED_POINT]={{0}}; + uint8_t PixelCount = 0; + static uint8_t all_clear = 1; + + DbgMsg("%s\n", __FUNCTION__); + if(ts->suspend_state){ + goto exit_invalid_data; + } + + // get finger count + buffer[0] = FINGERS; + ret = i2c_master_send(ts->client, buffer, 1); + if (ret < 0) + printk("send finger command error (%d)\n", ret); + ret = i2c_master_recv(ts->client, buffer, 2 + ts->max_touches * ts->pixel_length); + if (ret < 0) { + printk("read finger error (%d)\n", ret); + i2cErrorCount ++; + goto exit_invalid_data; + }else{ + i2cErrorCount = 0; +#ifdef SITRONIX_FINGER_COUNT_REG_ENABLE + PixelCount = buffer[0] & FINGERS_BMSK ; +#else + for(i = 0; i < ts->max_touches; i++){ + if(buffer[2 + i * ts->pixel_length] >= 0x80) + PixelCount++; + } +#endif // SITRONIX_FINGER_COUNT_REG_ENABLE + DbgMsg("fingers = %d\n", PixelCount); + } + DbgMsg("key buffer[1] = %d\n", buffer[1]); +#ifdef SITRONIX_SENSOR_KEY + if (PixelCount == 0) + { + for(i = 0; i < SITRONIX_NUMBER_SENSOR_KEY; i++){ + if(buffer[1] & (1 << i)){ + DbgMsg("key[%d] down\n", i); + input_event(ts->input_dev, EV_KEY, sitronix_sensor_key[i], 1); + }else{ + DbgMsg("key[%d] up\n", i); + input_event(ts->input_dev, EV_KEY, sitronix_sensor_key[i], 0); + } + } + } +#endif // SITRONIX_SENSOR_KEY + + for(i = 0; i < ts->max_touches; i++){ +#ifndef SITRONIX_TOUCH_KEY + if((buffer[2 + ts->pixel_length * i] >> X_COORD_VALID_SHFT) == 1){ + MTDStructure[i].Pixel_X = ((buffer[2 + ts->pixel_length * i] & (X_COORD_H_BMSK << X_COORD_H_SHFT)) << 4) | (buffer[2 + ts->pixel_length * i + X_COORD_L]); + MTDStructure[i].Pixel_Y = ((buffer[2 + ts->pixel_length * i] & Y_COORD_H_BMSK) << 8) | (buffer[2 + ts->pixel_length * i + Y_COORD_L]); + MTDStructure[i].Current_Pressed_area = AREA_DISPLAY; + }else + MTDStructure[i].Current_Pressed_area = AREA_NONE; +#endif // SITRONIX_TOUCH_KEY + } + + if(PixelCount != 0) + { + for(i = 0; i < ts->max_touches; i++) + { +#ifndef SITRONIX_TOUCH_KEY + if(MTDStructure[i].Current_Pressed_area == AREA_DISPLAY) + { + tmp = MTDStructure[i].Pixel_X; + MTDStructure[i].Pixel_X = MTDStructure[i].Pixel_Y; + MTDStructure[i].Pixel_Y = tmp; + + MTDStructure[i].Pixel_X = MTDStructure[i].Pixel_X < 50 ? 3 + MTDStructure[i].Pixel_X : MTDStructure[i].Pixel_X*97/100; + MTDStructure[i].Pixel_Y = MTDStructure[i].Pixel_Y < 50 ? 3 + MTDStructure[i].Pixel_Y : MTDStructure[i].Pixel_Y*98/100; + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 200); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, MTDStructure[i].Pixel_X); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, 480 - MTDStructure[i].Pixel_Y); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + DbgMsg("lr[%d](%d, %d)+\n", i, MTDStructure[i].Pixel_X, MTDStructure[i].Pixel_Y); + }else if(MTDStructure[i].Current_Pressed_area == AREA_NONE){ + DbgMsg("lr[%d](%d, %d)-\n", i, MTDStructure[i].Pixel_X, MTDStructure[i].Pixel_Y); + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); + } + memcpy(&sitronix_ts_gMTDPreStructure[i], &MTDStructure[i], sizeof(MTD_STRUCTURE)); +#endif // SITRONIX_TOUCH_KEY + } + all_clear = 0; +#ifdef SITRONIX_INT_POLLING_MODE +#ifdef SITRONIX_MONITOR_THREAD + atomic_set(&iMonitorThreadPostpone,1); +#endif // SITRONIX_MONITOR_THREAD + schedule_delayed_work(&ts->work, msecs_to_jiffies(INT_POLLING_MODE_INTERVAL)); +#endif // SITRONIX_INT_POLLING_MODE + } + else + { + if(all_clear == 0) + { + DbgMsg("lr: all_clear\n"); + for(i = 0; i < ts->max_touches; i++) + { + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); + } + all_clear = 1; + } + else + { + DbgMsg("ignore dummy finger leave\n"); + } +#ifdef SITRONIX_INT_POLLING_MODE + if (ts->use_irq){ + sitronix_ts_irq_on = 1; + enable_irq(ts->client->irq); + } +#endif // SITRONIX_INT_POLLING_MODE + } + input_sync(ts->input_dev); + +exit_invalid_data: +#if defined(SITRONIX_LEVEL_TRIGGERED) + if (ts->use_irq){ + sitronix_ts_irq_on = 1; + enable_irq(ts->client->irq); + } +#endif // defined(SITRONIX_LEVEL_TRIGGERED) + if ((2 <= i2cErrorCount)){ + printk("I2C abnormal in work_func(), reset it!\n"); + if(sitronix_ts_gpts->reset_ic) + sitronix_ts_gpts->reset_ic(); + i2cErrorCount = 0; +#ifdef SITRONIX_MONITOR_THREAD + StatusCheckCount = 0; +#endif // SITRONIX_MONITOR_THREAD + } +} + + +static irqreturn_t sitronix_ts_irq_handler(int irq, void *dev_id) +{ + struct sitronix_ts_data *ts = dev_id; + +// DbgMsg("%s\n", __FUNCTION__); +// printk("lr:%s\n", __FUNCTION__); +#if defined(SITRONIX_LEVEL_TRIGGERED) || defined(SITRONIX_INT_POLLING_MODE) + sitronix_ts_irq_on = 0; + disable_irq_nosync(ts->client->irq); +#endif // defined(SITRONIX_LEVEL_TRIGGERED) || defined(SITRONIX_INT_POLLING_MODE) +#ifdef SITRONIX_MONITOR_THREAD + atomic_set(&iMonitorThreadPostpone,1); +#endif // SITRONIX_MONITOR_THREAD +#ifndef SITRONIX_INT_POLLING_MODE + schedule_work(&ts->work); +#else + schedule_delayed_work(&ts->work, msecs_to_jiffies(0)); +#endif // SITRONIX_INT_POLLING_MODE + return IRQ_HANDLED; +} + +static int sitronix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ +#if defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + int i; +#endif // defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + struct sitronix_ts_data *ts; + int ret = 0; + uint16_t max_x = 0, max_y = 0; + struct ft5x0x_platform_data *pdata; + uint8_t dev_status = 0; + + printk("lr------> %s start ------\n", __FUNCTION__); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + ret = -ENODEV; + goto err_check_functionality_failed; + } + + ts = kzalloc(sizeof(*ts), GFP_KERNEL); + if (ts == NULL) { + ret = -ENOMEM; + goto err_alloc_data_failed; + } +#ifndef SITRONIX_INT_POLLING_MODE + INIT_WORK(&ts->work, sitronix_ts_work_func); +#else + INIT_DELAYED_WORK(&ts->work, sitronix_ts_work_func); +#endif // SITRONIX_INT_POLLING_MODE + ts->client = client; + i2c_set_clientdata(client, ts); + pdata = client->dev.platform_data; +#if 0 + if(pdata->reset_ic){ + ts->reset_ic = pdata->reset_ic; + pdata->reset_ic(); + mdelay(SITRONIX_TS_CHANGE_MODE_DELAY); + } +#endif + if(pdata->init_platform_hw) + pdata->init_platform_hw(); + + sitronix_ts_gpts = ts; + + ret = sitronix_ts_get_device_status(ts, &dev_status); + if((ret < 0) || (dev_status == 0x6)) + goto err_device_info_error; + + ret = sitronix_ts_get_touch_info(ts); + if(ret < 0) + goto err_device_info_error; + + //ret = sitronix_ts_identify(ts); + //if(ret < 0) + // goto err_device_info_error; + +#ifdef SITRONIX_MONITOR_THREAD + //== Add thread to monitor chip + atomic_set(&iMonitorThreadPostpone,1); + SitronixMonitorThread = kthread_run(sitronix_ts_monitor_thread,"Sitronix","Monitorthread"); + if(IS_ERR(SitronixMonitorThread)) + SitronixMonitorThread = NULL; +#endif // SITRONIX_MONITOR_THREAD + + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL){ + printk("Can not allocate memory for input device."); + ret = -ENOMEM; + goto err_input_dev_alloc_failed; + } + + ts->input_dev->name = "sitronix-i2c-touch-mt"; + //set_bit(EV_KEY, ts->input_dev->evbit); + //set_bit(BTN_TOUCH, ts->input_dev->keybit); + //set_bit(EV_ABS, ts->input_dev->evbit); + +#if defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + ts->keyevent_input = input_allocate_device(); + if (ts->keyevent_input == NULL){ + printk("Can not allocate memory for key input device."); + ret = -ENOMEM; + goto err_input_dev_alloc_failed; + } + ts->keyevent_input->name = "sitronix-i2c-touch-key"; + //set_bit(EV_KEY, ts->keyevent_input->evbit); +#endif // defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) +#if defined(SITRONIX_SENSOR_KEY) + for(i = 0; i < SITRONIX_NUMBER_SENSOR_KEY; i++){ + //set_bit(sitronix_sensor_key[i], ts->keyevent_input->keybit); + } +#endif // defined(SITRONIX_SENSOR_KEY) + +#ifndef SITRONIX_TOUCH_KEY + max_x = ts->resolution_x; + max_y = ts->resolution_y; +#else +#ifdef SITRONIX_KEY_BOUNDARY_MANUAL_SPECIFY + for(i = 0; i < SITRONIX_NUMBER_TOUCH_KEY; i++){ + //set_bit(sitronix_key_array[i].code, ts->keyevent_input->keybit); + } + max_x = SITRONIX_TOUCH_RESOLUTION_X; + max_y = SITRONIX_TOUCH_RESOLUTION_Y; +#else + for(i = 0; i < SITRONIX_NUMBER_TOUCH_KEY; i++){ + sitronix_key_array[i].x_low = ((ts->resolution_x / SITRONIX_NUMBER_TOUCH_KEY ) * i ) + 15; + sitronix_key_array[i].x_high = ((ts->resolution_x / SITRONIX_NUMBER_TOUCH_KEY ) * (i + 1)) - 15; + sitronix_key_array[i].y_low = ts->resolution_y - ts->resolution_y / SCALE_KEY_HIGH_Y; + sitronix_key_array[i].y_high = ts->resolution_y; + DbgMsg("key[%d] %d, %d, %d, %d\n", i, sitronix_key_array[i].x_low, sitronix_key_array[i].x_high, sitronix_key_array[i].y_low, sitronix_key_array[i].y_high); + //set_bit(sitronix_key_array[i].code, ts->keyevent_input->keybit); + + } + max_x = ts->resolution_x; + max_y = ts->resolution_y - ts->resolution_y / SCALE_KEY_HIGH_Y; +#endif // SITRONIX_KEY_BOUNDARY_MANUAL_SPECIFY +#endif // SITRONIX_TOUCH_KEY +#if defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + ret = input_register_device(ts->keyevent_input); + if(ret < 0){ + printk("Can not register key input device."); + goto err_input_register_device_failed; + } +#endif // defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + + __set_bit(EV_ABS, ts->input_dev->evbit); + __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); + set_bit(ABS_MT_POSITION_X, ts->input_dev->absbit); + set_bit(ABS_MT_POSITION_Y, ts->input_dev->absbit); + set_bit(ABS_MT_TOUCH_MAJOR, ts->input_dev->absbit); + set_bit(ABS_MT_WIDTH_MAJOR, ts->input_dev->absbit); + ts->max_touches = 5; + + input_mt_init_slots(ts->input_dev, ts->max_touches); + + input_set_abs_params(ts->input_dev,ABS_MT_POSITION_X, 0, 800, 0, 0); + input_set_abs_params(ts->input_dev,ABS_MT_POSITION_Y, 0, 480, 0, 0); + input_set_abs_params(ts->input_dev,ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + + for (i = 0; i < ARRAY_SIZE(initkey_code); i++) { + input_set_capability(ts->input_dev, EV_KEY, initkey_code[i]); + } + + ret = input_register_device(ts->input_dev); + if(ret < 0){ + printk("Can not register input device."); + goto err_input_register_device_failed; + } + + ts->suspend_state = 0; + if (client->irq){ +#ifdef SITRONIX_LEVEL_TRIGGERED + ret = request_irq(client->irq, sitronix_ts_irq_handler, IRQF_TRIGGER_LOW | IRQF_DISABLED, client->name, ts); +#else + ret = request_irq(client->irq, sitronix_ts_irq_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED, client->name, ts); +#endif // SITRONIX_LEVEL_TRIGGERED + if (ret == 0){ + sitronix_ts_irq_on = 1; + ts->use_irq = 1; + }else + dev_err(&client->dev, "request_irq failed\n"); + } +#ifdef CONFIG_HAS_EARLYSUSPEND + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = sitronix_ts_early_suspend; + ts->early_suspend.resume = sitronix_ts_late_resume; + register_early_suspend(&ts->early_suspend); +#endif // CONFIG_HAS_EARLYSUSPEND + + printk("lr------> %s end ------\n", __FUNCTION__); + + return 0; + +err_input_register_device_failed: + input_free_device(ts->input_dev); +#if defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + input_free_device(ts->keyevent_input); +#endif // defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) +err_input_dev_alloc_failed: + kfree(ts); +err_alloc_data_failed: +err_check_functionality_failed: +#ifdef SITRONIX_MONITOR_THREAD + if(SitronixMonitorThread){ + kthread_stop(SitronixMonitorThread); + SitronixMonitorThread = NULL; + } +#endif // SITRONIX_MONITOR_THREAD +err_device_info_error: + gpio_free(RK2928_PIN1_PA3); + gpio_free(RK2928_PIN1_PB3); + + return ret; +} + +static int sitronix_ts_remove(struct i2c_client *client) +{ + struct sitronix_ts_data *ts = i2c_get_clientdata(client); +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&ts->early_suspend); +#endif // CONFIG_HAS_EARLYSUSPEND +#ifdef SITRONIX_MONITOR_THREAD + if(SitronixMonitorThread){ + kthread_stop(SitronixMonitorThread); + SitronixMonitorThread = NULL; + } +#endif // SITRONIX_MONITOR_THREAD + if (ts->use_irq) + free_irq(client->irq, ts); + else + hrtimer_cancel(&ts->timer); + input_unregister_device(ts->input_dev); +#if defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + input_unregister_device(ts->keyevent_input); +#endif // defined(SITRONIX_SENSOR_KEY) || defined (SITRONIX_TOUCH_KEY) + kfree(ts); + return 0; +} + +static int sitronix_ts_suspend(struct i2c_client *client, pm_message_t mesg) +{ + int ret = 0, i = 0; + struct sitronix_ts_data *ts = i2c_get_clientdata(client); + + DbgMsg("%s\n", __FUNCTION__); +#ifdef SITRONIX_MONITOR_THREAD + if(SitronixMonitorThread){ + kthread_stop(SitronixMonitorThread); + SitronixMonitorThread = NULL; + } + sitronix_ts_delay_monitor_thread_start = DELAY_MONITOR_THREAD_START_RESUME; +#endif // SITRONIX_MONITOR_THREAD + if(ts->use_irq){ + sitronix_ts_irq_on = 0; + disable_irq_nosync(ts->client->irq); + } + ts->suspend_state = 1; + + ret = sitronix_ts_set_powerdown_bit(ts, 1); +#ifdef SITRONIX_WAKE_UP_TOUCH_BY_INT + gpio_direction_output(irq_to_gpio(client->irq), 1); +#endif // SITRONIX_WAKE_UP_TOUCH_BY_INT + DbgMsg("%s return\n", __FUNCTION__); + + for(i = 0; i < ts->max_touches; i++) + { + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); + } + input_sync(ts->input_dev); + + return 0; +} + +static int sitronix_ts_resume(struct i2c_client *client) +{ +#ifdef SITRONIX_WAKE_UP_TOUCH_BY_INT + unsigned int gpio; +#else + int ret; +#endif // SITRONIX_WAKE_UP_TOUCH_BY_INT + struct sitronix_ts_data *ts = i2c_get_clientdata(client); + + DbgMsg("%s\n", __FUNCTION__); + +#ifdef SITRONIX_WAKE_UP_TOUCH_BY_INT + gpio = irq_to_gpio(client->irq); + gpio_set_value(gpio, 0); + gpio_direction_input(gpio); +#else + ret = sitronix_ts_set_powerdown_bit(ts, 0); +#endif // SITRONIX_WAKE_UP_TOUCH_BY_INT + + ts->suspend_state = 0; + if(ts->use_irq){ + sitronix_ts_irq_on = 1; + enable_irq(ts->client->irq); + } +#ifdef SITRONIX_MONITOR_THREAD + atomic_set(&iMonitorThreadPostpone,1); + SitronixMonitorThread = kthread_run(sitronix_ts_monitor_thread,"Sitronix","Monitorthread"); + if(IS_ERR(SitronixMonitorThread)) + SitronixMonitorThread = NULL; +#endif // SITRONIX_MONITOR_THREAD + DbgMsg("%s return\n", __FUNCTION__); + + return 0; +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void sitronix_ts_early_suspend(struct early_suspend *h) +{ + struct sitronix_ts_data *ts; + DbgMsg("%s\n", __FUNCTION__); + ts = container_of(h, struct sitronix_ts_data, early_suspend); + sitronix_ts_suspend(ts->client, PMSG_SUSPEND); +} + +static void sitronix_ts_late_resume(struct early_suspend *h) +{ + struct sitronix_ts_data *ts; + DbgMsg("%s\n", __FUNCTION__); + ts = container_of(h, struct sitronix_ts_data, early_suspend); + sitronix_ts_resume(ts->client); +} +#endif // CONFIG_HAS_EARLYSUSPEND + +static const struct i2c_device_id sitronix_ts_id[] = { + { SITRONIX_I2C_TOUCH_DRV_NAME, 0 }, + { } +}; + +static struct i2c_driver sitronix_ts_driver = { + .probe = sitronix_ts_probe, + .remove = sitronix_ts_remove, + .id_table = sitronix_ts_id, + .driver = { + .name = SITRONIX_I2C_TOUCH_DRV_NAME, + }, +}; + +#ifdef SITRONIX_FW_UPGRADE_FEATURE +static struct file_operations nc_fops = { + .owner = THIS_MODULE, + .write = sitronix_write, + .read = sitronix_read, + .open = sitronix_open, + .unlocked_ioctl = sitronix_ioctl, + .release = sitronix_release, +}; +#endif // SITRONIX_FW_UPGRADE_FEATURE + +static int __devinit sitronix_ts_init(void) +{ +#ifdef SITRONIX_FW_UPGRADE_FEATURE + int result; + int err = 0; +#endif // SITRONIX_FW_UPGRADE_FEATURE + printk("Sitronix touch driver %d.%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR, DRIVER_PATCHLEVEL); + printk("Release date: %s\n", DRIVER_DATE); +#ifdef SITRONIX_FW_UPGRADE_FEATURE + dev_t devno = MKDEV(sitronix_major, 0); + result = alloc_chrdev_region(&devno, 0, 1, SITRONIX_I2C_TOUCH_DEV_NAME); + if(result < 0){ + printk("fail to allocate chrdev (%d) \n", result); + return 0; + } + sitronix_major = MAJOR(devno); + cdev_init(&sitronix_cdev, &nc_fops); + sitronix_cdev.owner = THIS_MODULE; + sitronix_cdev.ops = &nc_fops; + err = cdev_add(&sitronix_cdev, devno, 1); + if(err){ + printk("fail to add cdev (%d) \n", err); + return 0; + } + + sitronix_class = class_create(THIS_MODULE, SITRONIX_I2C_TOUCH_DEV_NAME); + if (IS_ERR(sitronix_class)) { + result = PTR_ERR(sitronix_class); + unregister_chrdev(sitronix_major, SITRONIX_I2C_TOUCH_DEV_NAME); + printk("fail to create class (%d) \n", result); + return result; + } + device_create(sitronix_class, NULL, MKDEV(sitronix_major, 0), NULL, SITRONIX_I2C_TOUCH_DEV_NAME); +#endif // SITRONIX_FW_UPGRADE_FEATURE + return i2c_add_driver(&sitronix_ts_driver); +} + +static void __exit sitronix_ts_exit(void) +{ +#ifdef SITRONIX_FW_UPGRADE_FEATURE + dev_t dev_id = MKDEV(sitronix_major, 0); +#endif // SITRONIX_FW_UPGRADE_FEATURE + i2c_del_driver(&sitronix_ts_driver); +#ifdef SITRONIX_FW_UPGRADE_FEATURE + cdev_del(&sitronix_cdev); + + device_destroy(sitronix_class, dev_id); //delete device node under /dev + class_destroy(sitronix_class); //delete class created by us + unregister_chrdev_region(dev_id, 1); +#endif // SITRONIX_FW_UPGRADE_FEATURE +} + +module_init(sitronix_ts_init); +module_exit(sitronix_ts_exit); + +MODULE_DESCRIPTION("Sitronix Multi-Touch Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/sitronix_ts_a720.h b/drivers/input/touchscreen/sitronix_ts_a720.h new file mode 100755 index 000000000000..cb651c1027d1 --- /dev/null +++ b/drivers/input/touchscreen/sitronix_ts_a720.h @@ -0,0 +1,175 @@ +/* + * drivers/input/touchscreen/sitronix_i2c_touch.h + * + * Touchscreen driver for Sitronix + * + * Copyright (C) 2011 Sitronix Technology Co., Ltd. + * Rudy Huang + */ +/* + * 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 __SITRONIX_I2C_TOUCH_h +#define __SITRONIX_I2C_TOUCH_h + +#include /* needed for the _IOW etc stuff used later */ + +#define SITRONIX_TOUCH_DRIVER_VERSION 0x03 +#define SITRONIX_MAX_SUPPORTED_POINT 5 +#define SITRONIX_I2C_TOUCH_DRV_NAME "sitronix" +#define SITRONIX_I2C_TOUCH_DEV_NAME "sitronixDev" + +//#define SITRONIX_WAKE_UP_TOUCH_BY_INT + +//#define SITRONIX_MONITOR_THREAD +#define DELAY_MONITOR_THREAD_START_PROBE 10000 +#define DELAY_MONITOR_THREAD_START_RESUME 3000 +#define SITRONIX_FW_UPGRADE_FEATURE +#define SITRONIX_LEVEL_TRIGGERED +// When enable_irq() is invoked, irq will be sent once while INT is not triggered if CONFIG_HARDIRQS_SW_RESEND is set. +// This behavior is implemented by linux kernel, it is used to prevent irq from losting when irq is edge-triggered mode. +#ifndef SITRONIX_LEVEL_TRIGGERED +#define SITRONIX_INT_POLLING_MODE +#define INT_POLLING_MODE_INTERVAL 14 +#endif // SITRONIX_LEVEL_TRIGGERED +#define SITRONIX_FINGER_COUNT_REG_ENABLE + +//#define EnableDbgMsg 0 +//#define EnableUpgradeMsg 1 + +#ifdef EnableDbgMsg +#define DbgMsg(arg...) printk(arg) +#else +#define DbgMsg(arg...) +#endif + +#ifdef EnableUpgradeMsg +#define UpgradeMsg(arg...) printk(arg) +#else +#define UpgradeMsg(arg...) +#endif + +typedef enum{ + FIRMWARE_VERSION, + STATUS_REG, + DEVICE_CONTROL_REG, + TIMEOUT_TO_IDLE_REG, + XY_RESOLUTION_HIGH, + X_RESOLUTION_LOW, + Y_RESOLUTION_LOW, + FIRMWARE_REVISION_3 = 0x0C, + FIRMWARE_REVISION_2, + FIRMWARE_REVISION_1, + FIRMWARE_REVISION_0, + FINGERS, + KEYS_REG, + XY0_COORD_H, + X0_COORD_L, + Y0_COORD_L, + I2C_PROTOCOL = 0x3E, + MAX_NUM_TOUCHES, + DATA_0_HIGH, + DATA_0_LOW, + + PAGE_REG = 0xff, +}RegisterOffset; + +#define SITRONIX_TS_CHANGE_MODE_DELAY 150 + +typedef enum{ + XY_COORD_H, + X_COORD_L, + Y_COORD_L, + PIXEL_DATA_LENGTH_B, + PIXEL_DATA_LENGTH_A, +}PIXEL_DATA_FORMAT; + +#define X_RES_H_SHFT 4 +#define X_RES_H_BMSK 0xf +#define Y_RES_H_SHFT 0 +#define Y_RES_H_BMSK 0xf +#define FINGERS_SHFT 0 +#define FINGERS_BMSK 0xf +#define X_COORD_VALID_SHFT 7 +#define X_COORD_VALID_BMSK 0x1 +#define X_COORD_H_SHFT 4 +#define X_COORD_H_BMSK 0x7 +#define Y_COORD_H_SHFT 0 +#define Y_COORD_H_BMSK 0x7 + +typedef enum{ + SITRONIX_A_TYPE = 1, + SITRONIX_B_TYPE, +}I2C_PROTOCOL_TYPE; + +#define I2C_PROTOCOL_SHFT 0x0 +#define I2C_PROTOCOL_BMSK 0x3 + +#define SMT_IOC_MAGIC 0xf1 + +enum{ + SMT_GET_DRIVER_REVISION = 1, + SMT_GET_FW_REVISION, + SMT_ENABLE_IRQ, + SMT_DISABLE_IRQ, + SMT_RESUME, + SMT_SUSPEND, + SMT_HW_RESET, + SMT_IOC_MAXNR, +}; + +#define IOCTL_SMT_GET_DRIVER_REVISION _IOC(_IOC_READ, SMT_IOC_MAGIC, SMT_GET_DRIVER_REVISION, 1) +#define IOCTL_SMT_GET_FW_REVISION _IOC(_IOC_READ, SMT_IOC_MAGIC, SMT_GET_FW_REVISION, 4) +#define IOCTL_SMT_ENABLE_IRQ _IOC(_IOC_NONE, SMT_IOC_MAGIC, SMT_ENABLE_IRQ, 0) +#define IOCTL_SMT_DISABLE_IRQ _IOC(_IOC_NONE, SMT_IOC_MAGIC, SMT_DISABLE_IRQ, 0) +#define IOCTL_SMT_RESUME _IOC(_IOC_NONE, SMT_IOC_MAGIC, SMT_RESUME, 0) +#define IOCTL_SMT_SUSPEND _IOC(_IOC_NONE, SMT_IOC_MAGIC, SMT_SUSPEND, 0) +#define IOCTL_SMT_HW_RESET _IOC(_IOC_NONE, SMT_IOC_MAGIC, SMT_HW_RESET, 0) + +#define SITRONIX_SENSOR_KEY +//#define SITRONIX_TOUCH_KEY +//#define SITRONIX_KEY_BOUNDARY_MANUAL_SPECIFY + +typedef struct _tag_MTD_STRUCTURE{ + u16 Pixel_X; + u16 Pixel_Y; + u8 First_Pressed_area; /* 0: no press; 1: display; 2: touch key */ + u8 Current_Pressed_area; /* 0: no press; 1: display; 2: touch key */ + unsigned int First_key_index; + unsigned int Current_key_index; +}MTD_STRUCTURE, *PMTD_STRUCTURE; + +#ifndef SITRONIX_TOUCH_KEY +enum{ + AREA_NONE, + AREA_DISPLAY, +}; +#else +enum{ + AREA_NONE, + AREA_DISPLAY, + AREA_KEY, + AREA_INVALID, +}; + +struct sitronix_AA_key{ + int x_low; + int x_high; + int y_low; + int y_high; + unsigned int code; +}; +#endif // SITRONIX_TOUCH_KEY + +struct sitronix_i2c_touch_platform_data { + uint32_t version; /* Use this entry for panels with */ + /* (major << 8 | minor) version or above. */ + /* If non-zero another array entry follows */ + void (*reset_ic)(void); +}; + +#endif // __SITRONIX_I2C_TOUCH_h -- 2.34.1