diff options
| author | Mao Li <maol@codeaurora.org> | 2014-08-11 14:19:09 +0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-08-05 04:35:02 -0700 |
| commit | 5218b8f9f8d8b7e986440b5124093cdba8efd903 (patch) | |
| tree | 1803ac6212aad76cbcb4c982895e633d91a07d20 | |
| parent | 28352998dee80f33641dd7b28479350bd480b823 (diff) | |
input: msg21xx_ts: update mstar driver to enable msg2138A
Mstar reference driver is being cleaned up to be checkpatch
compliant. Add Kconfig and Makefile changes to enable Mstar
driver's compilation. And following new features are added to
the driver:
1. Pinctrl support
2. Threaded irq support
3. Release all touches in suspend
4. Protocol B compliance
5. Explicit suspend/resume function
6. Configure gpios in suspend/resume function
7. Add device tree parser function
8. Add dtsi support for gpio, regulator, I2C address, display coords
This patch is propagated from 3.18 kernel
'commit 091a01709e12 ("input: msg21xx_ts: update mstar
driver to enable msg2138A")'
Change-Id: Ic49a18de64ec210a0636405394ba7a8f52f336a9
Signed-off-by: Mao Li <maol@codeaurora.org>
Signed-off-by: Shantanu Jain <shjain@codeaurora.org>
Signed-off-by: Sudhakar Manapati <smanap@codeaurora.org>
[abinayap@codeaurora.org: Fix checkpatch errors for 4.4 kernel
- Block comments use a trailing */ on a separate line
- Comparisons should place the constant on the right side of the test
- struct of_device_id should normally be const
- DT compatible string vendor "mstar" appears un-documented]
Signed-off-by: Abinaya P <abinayap@codeaurora.org>
| -rw-r--r-- | Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt | 60 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/vendor-prefixes.txt | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/touchscreen/msg21xx_ts.c | 3148 |
5 files changed, 1842 insertions, 1379 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt new file mode 100644 index 000000000000..26f01ca8577f --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/msg21xx-ts.txt @@ -0,0 +1,60 @@ +Mstar touch controller + +The mstar controller is connected to host processor +via i2c. The controller generates interrupts when the +user touches the panel. The host controller is expected +to read the touch coordinates over i2c and pass the coordinates +to the rest of the system. + +Required properties: + + - compatible : should be "mstar,msg21xx". + - reg : i2c slave address of the device. + - interrupt-parent : parent of interrupt. + - interrupts : touch sample interrupt to indicate presense or release + of fingers on the panel. + - vdd-supply : Power supply needed to power up the device. + - vcc_i2c-supply : Power source required to power up i2c bus. + - mstar,irq-gpio : irq gpio which is to provide interrupts to host, + same as "interrupts" node. It will also + contain active low or active high information. + - mstar,reset-gpio : reset gpio to control the reset of chip. + - mstar,display-coords : display coords in pixels. It is a four + tuple consisting of min x, min y, max x and + max y values. + - pinctrl-names : This should be defined if a target uses pinctrl framework. + See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt. + Specify the names of the configs that pinctrl can install in driver. + Following are the pinctrl configs that can be installed: + "pmx_ts_active" : Active configuration of pins, this should specify active + config defined in pin groups of interrupt and reset gpio. + "pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep + config defined in pin groups of interrupt and reset gpio. + "pmx_ts_release" : Release configuration of pins, this should specify + release config defined in pin groups of interrupt and reset gpio. + +Optional properties: + + - mstar,button-map : button map of key codes. It is a three tuple consisting of key codes. + - mstar,panel-coords : panel coords for the chip in pixels. + It is a four tuple consisting of min x, + min y, max x and max y values. + +Example: + i2c@78b9000 { /* BLSP1 QUP5 */ + mstar@26 { + compatible = "mstar,msg21xx"; + reg = <0x26>; + interrupt-parent = <&msm_gpio>; + interrupts = <13 0x2008>; + mstar,irq-gpio = <&msm_gpio 13 0x00000001>; + mstar,reset-gpio = <&msm_gpio 12 0x0>; + vdd-supply = <&pm8916_l17>; + vcc_i2c-supply = <&pm8916_l6>; + mstar,display-coords = <0 0 480 854>; + pinctrl-names = "pmx_ts_active","pmx_ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + mstar,button-map= <172 139 158>; + }; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 4097b7cd6454..aca2dd3e4ccb 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -146,6 +146,7 @@ mosaixtech Mosaix Technologies, Inc. moxa Moxa mpl MPL AG msi Micro-Star International Co. Ltd. +mstar MStar Semiconductor, Inc. mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.) mundoreader Mundo Reader S.L. murata Murata Manufacturing Co., Ltd. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 529edb16565a..69028bd45fdd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1110,6 +1110,17 @@ config TOUCHSCREEN_COLIBRI_VF50 To compile this driver as a module, choose M here: the module will be called colibri_vf50_ts. +config TOUCHSCREEN_MSTAR21XX + tristate "Mstar touchscreens" + depends on I2C + help + Say Y here if you have a mstar touchscreen. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called msg21xx_ts. + config TOUCHSCREEN_ROHM_BU21023 tristate "ROHM BU21023/24 Dual touch support resistive touchscreens" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index e04e787cea6e..e1777f11d77b 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -97,3 +97,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o +obj-$(CONFIG_TOUCHSCREEN_MSTAR21XX) += msg21xx_ts.o diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c index 4eb7fd4b1cc9..72114eb78bc4 100644 --- a/drivers/input/touchscreen/msg21xx_ts.c +++ b/drivers/input/touchscreen/msg21xx_ts.c @@ -5,6 +5,8 @@ * * Copyright (C) 2012 Bruce Ding <bruce.ding@mstarsemi.com> * + * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * * 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 @@ -20,10 +22,12 @@ #include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/input.h> +#include <linux/input/mt.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/timer.h> #include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/sysfs.h> #include <linux/init.h> @@ -40,7 +44,10 @@ #include <linux/string.h> #include <asm/unistd.h> #include <linux/cdev.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> +#include <linux/kthread.h> +#include <linux/regulator/consumer.h> + #if defined(CONFIG_HAS_EARLYSUSPEND) #include <linux/earlysuspend.h> #endif @@ -49,40 +56,37 @@ #include <linux/notifier.h> #include <linux/fb.h> #endif -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR +#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR #include <linux/input/vir_ps.h> #endif -/*=============================================================*/ -// Macro Definition -/*=============================================================*/ +/* Macro Definition */ #define TOUCH_DRIVER_DEBUG 0 #if (TOUCH_DRIVER_DEBUG == 1) -#define DBG(fmt, arg...) pr_err(fmt, ##arg) //pr_info(fmt, ##arg) +#define DBG(fmt, arg...) pr_info(fmt, ##arg) #else #define DBG(fmt, arg...) #endif -/*=============================================================*/ -// Constant Value & Variable Definition -/*=============================================================*/ +/* Constant Value & Variable Definition */ + +static struct regulator *vdd; +static struct regulator *vcc_i2c; + +#define MSTAR_VTG_MIN_UV 2800000 +#define MSTAR_VTG_MAX_UV 3300000 +#define MSTAR_I2C_VTG_MIN_UV 1800000 +#define MSTAR_I2C_VTG_MAX_UV 1800000 -#define U8 unsigned char -#define U16 unsigned short -#define U32 unsigned int -#define S8 signed char -#define S16 signed short -#define S32 signed int #define TOUCH_SCREEN_X_MIN (0) #define TOUCH_SCREEN_Y_MIN (0) -/* - * Note. - * Please change the below touch screen resolution according to the touch panel that you are using. - */ -#define TOUCH_SCREEN_X_MAX (480) -#define TOUCH_SCREEN_Y_MAX (800) + +#define MAX_BUTTONS 4 +#define FT_COORDS_ARR_SIZE 4 + + /* * Note. * Please do not change the below setting. @@ -90,62 +94,29 @@ #define TPD_WIDTH (2048) #define TPD_HEIGHT (2048) -/* - * Note. - * Please change the below GPIO pin setting to follow the platform that you are using - */ -static int int_gpio = 1; -static int reset_gpio = 0; -#define MS_TS_MSG21XX_GPIO_RST reset_gpio -#define MS_TS_MSG21XX_GPIO_INT int_gpio -//---------------------------------------------------------------------// - -//#define SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST - -#ifdef SYSFS_AUTHORITY_CHANGE_FOR_CTS_TEST -#define SYSFS_AUTHORITY (0644) -#else -#define SYSFS_AUTHORITY (0777) -#endif - -#define FIRMWARE_AUTOUPDATE #ifdef FIRMWARE_AUTOUPDATE -typedef enum { - SWID_START = 1, - SWID_TRULY = SWID_START, - SWID_NULL, -} SWID_ENUM; +enum { + SWID_START = 1, + SWID_TRULY = SWID_START, + SWID_NULL, +}; -unsigned char MSG_FIRMWARE[1][33*1024] = -{ - { - #include "msg21xx_truly_update_bin.h" - } +static unsigned char MSG_FIRMWARE[1][33*1024] = { { + #include "msg21xx_truly_update_bin.h" + } }; #endif #define CONFIG_TP_HAVE_KEY -/* - * Note. - * If the below virtual key value definition are not consistent with those that defined in key layout file of platform, - * please change the below virtual key value to follow the platform that you are using. - */ -#ifdef CONFIG_TP_HAVE_KEY -#define TOUCH_KEY_MENU (139) //229 -#define TOUCH_KEY_HOME (172) //102 -#define TOUCH_KEY_BACK (158) -#define TOUCH_KEY_SEARCH (217) - -const U16 tp_key_array[] = {TOUCH_KEY_MENU, TOUCH_KEY_HOME, TOUCH_KEY_BACK, TOUCH_KEY_SEARCH}; -#define MAX_KEY_NUM (sizeof(tp_key_array)/sizeof(tp_key_array[0])) -#endif +#define PINCTRL_STATE_ACTIVE "pmx_ts_active" +#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" +#define PINCTRL_STATE_RELEASE "pmx_ts_release" -#define SLAVE_I2C_ID_DBBUS (0xC4>>1) -#define SLAVE_I2C_ID_DWI2C (0x4C>>1) +#define SLAVE_I2C_ID_DBBUS (0xC4>>1) -#define DEMO_MODE_PACKET_LENGTH (8) -#define MAX_TOUCH_NUM (2) //5 +#define DEMO_MODE_PACKET_LENGTH (8) +#define MAX_TOUCH_NUM (2) #define TP_PRINT #ifdef TP_PRINT @@ -153,1600 +124,2020 @@ static int tp_print_proc_read(void); static void tp_print_create_entry(void); #endif -static char *fw_version = NULL; // customer firmware version -static U16 fw_version_major = 0; -static U16 fw_version_minor = 0; -static U8 temp[94][1024]; -static U32 crc32_table[256]; -static int FwDataCnt = 0; -static U8 bFwUpdating = 0; -static struct class *firmware_class = NULL; -static struct device *firmware_cmd_dev = NULL; +static char *fw_version; /* customer firmware version */ +static unsigned short fw_version_major; +static unsigned short fw_version_minor; +static unsigned char temp[94][1024]; +static unsigned int crc32_table[256]; +static int FwDataCnt; +static unsigned char bFwUpdating; +static struct class *firmware_class; +static struct device *firmware_cmd_dev; + +static struct i2c_client *i2c_client; + +static u32 button_map[MAX_BUTTONS]; + +static u32 num_buttons; + +struct msg21xx_ts_platform_data { + const char *name; + const char *fw_name; + u32 irqflags; + u32 irq_gpio; + u32 irq_gpio_flags; + u32 reset_gpio; + u32 reset_gpio_flags; + u32 family_id; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 panel_minx; + u32 panel_miny; + u32 panel_maxx; + u32 panel_maxy; + u32 group_id; + u32 hard_rst_dly; + u32 soft_rst_dly; + u32 num_max_touches; + bool fw_vkey_support; + bool no_force_update; + bool i2c_pull_up; + bool ignore_id_check; + int (*power_init)(bool); + int (*power_on)(bool); +}; + +static struct msg21xx_ts_platform_data *pdata; + +struct msg21xx_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + const struct msg21xx_ts_platform_data *pdata; + struct regulator *vdd; + struct regulator *vcc_i2c; + bool loading_fw; + u8 family_id; + struct dentry *dir; + u16 addr; + bool suspended; + char *ts_info; + u8 *tch_data; + u32 tch_data_len; + u8 fw_ver[3]; + u8 fw_vendor_id; +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + struct pinctrl *ts_pinctrl; + struct pinctrl_state *pinctrl_state_active; + struct pinctrl_state *pinctrl_state_suspend; + struct pinctrl_state *pinctrl_state_release; + struct mutex ts_mutex; +}; -static struct i2c_client *i2c_client = NULL; +static struct msg21xx_ts_data *ts_data; #if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); -static struct notifier_block msg21xx_fb_notif; -#elif defined (CONFIG_HAS_EARLYSUSPEND) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); +#elif defined(CONFIG_HAS_EARLYSUSPEND) static struct early_suspend mstar_ts_early_suspend; #endif #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR -static U8 bEnableTpProximity = 0; -static U8 bFaceClosingTp = 0; +static unsigned char bEnableTpProximity; +static unsigned char bFaceClosingTp; #endif -static U8 bTpInSuspend = 0; -static int irq_msg21xx = -1; -static struct work_struct msg21xx_wk; static struct mutex msg21xx_mutex; -static struct input_dev *input_dev = NULL; +static struct input_dev *input_dev; -/*=============================================================*/ -// Data Type Definition -/*=============================================================*/ -typedef struct -{ - U16 x; - U16 y; -} touchPoint_t; +/* Data Type Definition */ -/// max 80+1+1 = 82 bytes -typedef struct -{ - touchPoint_t point[MAX_TOUCH_NUM]; - U8 count; - U8 keycode; -} touchInfo_t; +struct touchPoint_t { + unsigned short x; + unsigned short y; +}; -enum i2c_speed -{ - I2C_SLOW = 0, - I2C_NORMAL = 1, /* Enable erasing/writing for 10 msec. */ - I2C_FAST = 2, /* Disable EWENB before 10 msec timeout. */ +struct touchInfo_t { + struct touchPoint_t point[MAX_TOUCH_NUM]; + unsigned char count; + unsigned char keycode; }; -typedef enum -{ - EMEM_ALL = 0, - EMEM_MAIN, - EMEM_INFO, -} EMEM_TYPE_t; +enum i2c_speed { + I2C_SLOW = 0, + I2C_NORMAL = 1, /* Enable erasing/writing for 10 msec. */ + I2C_FAST = 2, /* Disable EWENB before 10 msec timeout. */ +}; -/*=============================================================*/ -// Function Definition -/*=============================================================*/ +enum EMEM_TYPE_t { + EMEM_ALL = 0, + EMEM_MAIN, + EMEM_INFO, +}; -/// CRC -static U32 _CRC_doReflect(U32 ref, S8 ch) -{ - U32 value = 0; - U32 i = 0; - - for (i = 1; i < (ch + 1); i ++) - { - if (ref & 1) - { - value |= 1 << (ch - i); - } - ref >>= 1; - } - - return value; -} +/* Function Definition */ -U32 _CRC_getValue(U32 text, U32 prevCRC) +static unsigned int _CRC_doReflect(unsigned int ref, signed char ch) { - U32 ulCRC = prevCRC; + unsigned int value = 0; + unsigned int i = 0; - ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text]; + for (i = 1; i < (ch + 1); i++) { + if (ref & 1) + value |= 1 << (ch - i); + ref >>= 1; + } - return ulCRC; + return value; } -static void _CRC_initTable(void) -{ - U32 magic_number = 0x04c11db7; - U32 i, j; - - for (i = 0; i <= 0xFF; i ++) - { - crc32_table[i] = _CRC_doReflect (i, 8) << 24; - for (j = 0; j < 8; j ++) - { - crc32_table[i] = (crc32_table[i] << 1) ^ (crc32_table[i] & (0x80000000L) ? magic_number : 0); - } - crc32_table[i] = _CRC_doReflect(crc32_table[i], 32); - } -} - -static void reset_hw(void) +static unsigned int _CRC_getValue(unsigned int text, unsigned int prevCRC) { - DBG("reset_hw()\n"); + unsigned int ulCRC = prevCRC; - gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0); - mdelay(100); /* Note that the RST must be in LOW 10ms at least */ - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(100); /* Enable the interrupt service thread/routine for INT after 50ms */ -} + ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ text]; -static int read_i2c_seq(U8 addr, U8* buf, U16 size) -{ - int rc = 0; - struct i2c_msg msgs[] = - { - { - .addr = addr, - .flags = I2C_M_RD, // read flag - .len = size, - .buf = buf, - }, - }; - - /* If everything went ok (i.e. 1 msg transmitted), return #bytes - transmitted, else error code. */ - if (i2c_client != NULL) - { - rc = i2c_transfer(i2c_client->adapter, msgs, 1); - if (rc < 0) - { - DBG("read_i2c_seq() error %d\n", rc); - } - } - else - { - DBG("i2c_client is NULL\n"); - } - - return rc; + return ulCRC; } -static int write_i2c_seq(U8 addr, U8* buf, U16 size) +static void _CRC_initTable(void) { - int rc = 0; - struct i2c_msg msgs[] = - { - { - .addr = addr, - .flags = 0, // if read flag is undefined, then it means write flag. - .len = size, - .buf = buf, - }, - }; - - /* If everything went ok (i.e. 1 msg transmitted), return #bytes - transmitted, else error code. */ - if (i2c_client != NULL) - { - rc = i2c_transfer(i2c_client->adapter, msgs, 1); - if ( rc < 0 ) - { - DBG("write_i2c_seq() error %d\n", rc); - } - } - else - { - DBG("i2c_client is NULL\n"); - } - - return rc; + unsigned int magic_number = 0x04c11db7; + unsigned int i, j; + + for (i = 0; i <= 0xFF; i++) { + crc32_table[i] = _CRC_doReflect(i, 8) << 24; + for (j = 0; j < 8; j++) + crc32_table[i] = (crc32_table[i] << 1) ^ + (crc32_table[i] & (0x80000000L) ? + magic_number : 0); + crc32_table[i] = _CRC_doReflect(crc32_table[i], 32); + } } -static U16 read_reg(U8 bank, U8 addr) +static void reset_hw(void) { - U8 tx_data[3] = {0x10, bank, addr}; - U8 rx_data[2] = {0}; - - write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3); - read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2); - - return (rx_data[1] << 8 | rx_data[0]); + DBG("reset_hw()\n"); + + gpio_direction_output(pdata->reset_gpio, 1); + gpio_set_value_cansleep(pdata->reset_gpio, 0); + msleep(100); /* Note that the RST must be in LOW 10ms at least */ + gpio_set_value_cansleep(pdata->reset_gpio, 1); + /* Enable the interrupt service thread/routine for INT after 50ms */ + msleep(100); } -static void write_reg(U8 bank, U8 addr, U16 data) +static int read_i2c_seq(unsigned char addr, unsigned char *buf, + unsigned short size) { - U8 tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8}; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5); + int rc = 0; + struct i2c_msg msgs[] = { + { + .addr = addr, + .flags = I2C_M_RD, /* read flag*/ + .len = size, + .buf = buf, + }, + }; + + /* If everything went ok (i.e. 1 msg transmitted), return #bytes + * transmitted, else error code. + */ + if (i2c_client != NULL) { + rc = i2c_transfer(i2c_client->adapter, msgs, 1); + if (rc < 0) + DBG("read_i2c_seq() error %d\n", rc); + } else { + DBG("i2c_client is NULL\n"); + } + + return rc; } -static void write_reg_8bit(U8 bank, U8 addr, U8 data) +static int write_i2c_seq(unsigned char addr, unsigned char *buf, + unsigned short size) { - U8 tx_data[4] = {0x10, bank, addr, data}; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4); + int rc = 0; + struct i2c_msg msgs[] = { + { + .addr = addr, + /* if read flag is undefined, + * then it means write flag. + */ + .flags = 0, + .len = size, + .buf = buf, + }, + }; + + /* If everything went ok (i.e. 1 msg transmitted), return #bytes + * transmitted, else error code. + */ + if (i2c_client != NULL) { + rc = i2c_transfer(i2c_client->adapter, msgs, 1); + if (rc < 0) + DBG("write_i2c_seq() error %d\n", rc); + } else { + DBG("i2c_client is NULL\n"); + } + + return rc; } -void dbbusDWIICEnterSerialDebugMode(void) +static unsigned short read_reg(unsigned char bank, unsigned char addr) { - U8 data[5]; + unsigned char tx_data[3] = {0x10, bank, addr}; + unsigned char rx_data[2] = {0}; - // Enter the Serial Debug Mode - data[0] = 0x53; - data[1] = 0x45; - data[2] = 0x52; - data[3] = 0x44; - data[4] = 0x42; + write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 3); + read_i2c_seq(SLAVE_I2C_ID_DBBUS, &rx_data[0], 2); - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5); + return rx_data[1] << 8 | rx_data[0]; } -void dbbusDWIICStopMCU(void) +static void write_reg(unsigned char bank, unsigned char addr, + unsigned short data) { - U8 data[1]; - - // Stop the MCU - data[0] = 0x37; + unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8}; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); + write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5); } -void dbbusDWIICIICUseBus(void) +static void write_reg_8bit(unsigned char bank, unsigned char addr, + unsigned char data) { - U8 data[1]; + unsigned char tx_data[4] = {0x10, bank, addr, data}; - // IIC Use Bus - data[0] = 0x35; - - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); + write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4); } -void dbbusDWIICIICReshape(void) +static void dbbusDWIICEnterSerialDebugMode(void) { - U8 data[1]; + unsigned char data[5]; - // IIC Re-shape - data[0] = 0x71; + /* Enter the Serial Debug Mode */ + data[0] = 0x53; + data[1] = 0x45; + data[2] = 0x52; + data[3] = 0x44; + data[4] = 0x42; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); + write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5); } -void dbbusDWIICIICNotUseBus(void) +static void dbbusDWIICStopMCU(void) { - U8 data[1]; + unsigned char data[1]; - // IIC Not Use Bus - data[0] = 0x34; + /* Stop the MCU */ + data[0] = 0x37; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); + write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); } -void dbbusDWIICNotStopMCU(void) +static void dbbusDWIICIICUseBus(void) { - U8 data[1]; + unsigned char data[1]; - // Not Stop the MCU - data[0] = 0x36; + /* IIC Use Bus */ + data[0] = 0x35; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); + write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); } -void dbbusDWIICExitSerialDebugMode(void) +static void dbbusDWIICIICReshape(void) { - U8 data[1]; - - // Exit the Serial Debug Mode - data[0] = 0x45; + unsigned char data[1]; - write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); + /* IIC Re-shape */ + data[0] = 0x71; - // Delay some interval to guard the next transaction - //udelay ( 200 ); // delay about 0.2ms + write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1); } -//---------------------------------------------------------------------// - -static U8 get_ic_type(void) +static unsigned char get_ic_type(void) { - U8 ic_type = 0; - - reset_hw(); - dbbusDWIICEnterSerialDebugMode(); - dbbusDWIICStopMCU(); - dbbusDWIICIICUseBus(); - dbbusDWIICIICReshape(); - mdelay ( 300 ); - - // stop mcu - write_reg_8bit ( 0x0F, 0xE6, 0x01 ); - // disable watch dog - write_reg ( 0x3C, 0x60, 0xAA55 ); - // get ic type - ic_type = (0xff)&(read_reg(0x1E, 0xCC)); - - if (ic_type != 1 //msg2133 - && ic_type != 2 //msg21xxA - && ic_type != 3) //msg26xxM - { - ic_type = 0; - } - - reset_hw(); - - return ic_type; + unsigned char ic_type = 0; + + reset_hw(); + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + msleep(300); + + /* stop mcu */ + write_reg_8bit(0x0F, 0xE6, 0x01); + /* disable watch dog */ + write_reg(0x3C, 0x60, 0xAA55); + /* get ic type */ + ic_type = (0xff)&(read_reg(0x1E, 0xCC)); + + if (ic_type != 1 /* msg2133 */ + && ic_type != 2 /* msg21xxA */ + && ic_type != 3) /* msg26xxM */ { + ic_type = 0; + } + + reset_hw(); + + return ic_type; } static int get_customer_firmware_version(void) { - U8 dbbus_tx_data[3] = {0}; - U8 dbbus_rx_data[4] = {0}; - int ret = 0; + unsigned char dbbus_tx_data[3] = {0}; + unsigned char dbbus_rx_data[4] = {0}; + int ret = 0; + + DBG("get_customer_firmware_version()\n"); - DBG("get_customer_firmware_version()\n"); + dbbus_tx_data[0] = 0x53; + dbbus_tx_data[1] = 0x00; + dbbus_tx_data[2] = 0x2A; + mutex_lock(&msg21xx_mutex); + write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3); + read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4); + mutex_unlock(&msg21xx_mutex); + fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0]; + fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2]; - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = 0x00; - dbbus_tx_data[2] = 0x2A; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0]; - fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2]; + DBG("*** major = %d ***\n", fw_version_major); + DBG("*** minor = %d ***\n", fw_version_minor); - DBG("*** major = %d ***\n", fw_version_major); - DBG("*** minor = %d ***\n", fw_version_minor); + if (fw_version == NULL) + fw_version = kzalloc(sizeof(char), GFP_KERNEL); - if (fw_version == NULL) - { - fw_version = kzalloc(sizeof(char), GFP_KERNEL); - } + snprintf(fw_version, sizeof(char) - 1, "%03d%03d", + fw_version_major, fw_version_minor); - sprintf(fw_version, "%03d%03d", fw_version_major, fw_version_minor); - return ret; + return ret; } -static int firmware_erase_c33 ( EMEM_TYPE_t emem_type ) +static int firmware_erase_c33(enum EMEM_TYPE_t emem_type) { - // stop mcu - write_reg ( 0x0F, 0xE6, 0x0001 ); + /* stop mcu */ + write_reg(0x0F, 0xE6, 0x0001); - //disable watch dog - write_reg_8bit ( 0x3C, 0x60, 0x55 ); - write_reg_8bit ( 0x3C, 0x61, 0xAA ); + /* disable watch dog */ + write_reg_8bit(0x3C, 0x60, 0x55); + write_reg_8bit(0x3C, 0x61, 0xAA); - // set PROGRAM password - write_reg_8bit ( 0x16, 0x1A, 0xBA ); - write_reg_8bit ( 0x16, 0x1B, 0xAB ); + /* set PROGRAM password */ + write_reg_8bit(0x16, 0x1A, 0xBA); + write_reg_8bit(0x16, 0x1B, 0xAB); - write_reg_8bit ( 0x16, 0x18, 0x80 ); + write_reg_8bit(0x16, 0x18, 0x80); - if ( emem_type == EMEM_ALL ) - { - write_reg_8bit ( 0x16, 0x08, 0x10 ); //mark - } + if (emem_type == EMEM_ALL) + write_reg_8bit(0x16, 0x08, 0x10); - write_reg_8bit ( 0x16, 0x18, 0x40 ); - mdelay ( 10 ); + write_reg_8bit(0x16, 0x18, 0x40); + msleep(20); - // clear pce - write_reg_8bit ( 0x16, 0x18, 0x80 ); + /* clear pce */ + write_reg_8bit(0x16, 0x18, 0x80); - // erase trigger - if ( emem_type == EMEM_MAIN ) - { - write_reg_8bit ( 0x16, 0x0E, 0x04 ); //erase main - } - else - { - write_reg_8bit ( 0x16, 0x0E, 0x08 ); //erase all block - } + /* erase trigger */ + if (emem_type == EMEM_MAIN) + write_reg_8bit(0x16, 0x0E, 0x04); /* erase main */ + else + write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */ - return ( 1 ); + return 1; } -static ssize_t firmware_update_c33 ( struct device *dev, struct device_attribute *attr, - const char *buf, size_t size, EMEM_TYPE_t emem_type ) -{ - U32 i, j; - U32 crc_main, crc_main_tp; - U32 crc_info, crc_info_tp; - U16 reg_data = 0; - int update_pass = 1; - - crc_main = 0xffffffff; - crc_info = 0xffffffff; - - reset_hw(); - dbbusDWIICEnterSerialDebugMode(); - dbbusDWIICStopMCU(); - dbbusDWIICIICUseBus(); - dbbusDWIICIICReshape(); - mdelay ( 300 ); - - //erase main - firmware_erase_c33 ( EMEM_MAIN ); - mdelay ( 1000 ); - - reset_hw(); - dbbusDWIICEnterSerialDebugMode(); - dbbusDWIICStopMCU(); - dbbusDWIICIICUseBus(); - dbbusDWIICIICReshape(); - mdelay ( 300 ); - - ///////////////////////// - // Program - ///////////////////////// - - //polling 0x3CE4 is 0x1C70 - if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) - { - do - { - reg_data = read_reg ( 0x3C, 0xE4 ); - } - while ( reg_data != 0x1C70 ); - } - - switch ( emem_type ) - { - case EMEM_ALL: - write_reg ( 0x3C, 0xE4, 0xE38F ); // for all-blocks - break; - case EMEM_MAIN: - write_reg ( 0x3C, 0xE4, 0x7731 ); // for main block - break; - case EMEM_INFO: - write_reg ( 0x3C, 0xE4, 0x7731 ); // for info block - - write_reg_8bit ( 0x0F, 0xE6, 0x01 ); - - write_reg_8bit ( 0x3C, 0xE4, 0xC5 ); - write_reg_8bit ( 0x3C, 0xE5, 0x78 ); - - write_reg_8bit ( 0x1E, 0x04, 0x9F ); - write_reg_8bit ( 0x1E, 0x05, 0x82 ); - - write_reg_8bit ( 0x0F, 0xE6, 0x00 ); - mdelay ( 100 ); - break; - } - - // polling 0x3CE4 is 0x2F43 - do - { - reg_data = read_reg ( 0x3C, 0xE4 ); - } - while ( reg_data != 0x2F43 ); - - // calculate CRC 32 - _CRC_initTable (); - - for ( i = 0; i < 32; i++ ) // total 32 KB : 2 byte per R/W - { - if ( i == 31 ) - { - temp[i][1014] = 0x5A; - temp[i][1015] = 0xA5; - - for ( j = 0; j < 1016; j++ ) - { - crc_main = _CRC_getValue ( temp[i][j], crc_main); - } - } - else - { - for ( j = 0; j < 1024; j++ ) - { - crc_main = _CRC_getValue ( temp[i][j], crc_main); - } - } - - //write_i2c_seq(SLAVE_I2C_ID_DWI2C, temp[i], 1024); - for (j = 0; j < 8; j++) - { - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &temp[i][j*128], 128 ); - } - msleep (100); - - // polling 0x3CE4 is 0xD0BC - do - { - reg_data = read_reg ( 0x3C, 0xE4 ); - } - while ( reg_data != 0xD0BC ); - - write_reg ( 0x3C, 0xE4, 0x2F43 ); - } - - if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) - { - // write file done and check crc - write_reg ( 0x3C, 0xE4, 0x1380 ); - } - mdelay ( 10 ); - - if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) - { - // polling 0x3CE4 is 0x9432 - do - { - reg_data = read_reg ( 0x3C, 0xE4 ); - }while ( reg_data != 0x9432 ); - } - - crc_main = crc_main ^ 0xffffffff; - crc_info = crc_info ^ 0xffffffff; - - if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) - { - // CRC Main from TP - crc_main_tp = read_reg ( 0x3C, 0x80 ); - crc_main_tp = ( crc_main_tp << 16 ) | read_reg ( 0x3C, 0x82 ); - - // CRC Info from TP - crc_info_tp = read_reg ( 0x3C, 0xA0 ); - crc_info_tp = ( crc_info_tp << 16 ) | read_reg ( 0x3C, 0xA2 ); - } - - update_pass = 1; - if ( ( emem_type == EMEM_ALL ) || ( emem_type == EMEM_MAIN ) ) - { - if ( crc_main_tp != crc_main ) - update_pass = 0; - - /* - if ( crc_info_tp != crc_info ) - update_pass = 0; - */ - } - - if ( !update_pass ) - { - DBG( "update_C33 failed\n" ); - reset_hw(); - FwDataCnt = 0; - return 0; - } - - DBG( "update_C33 OK\n" ); - reset_hw(); - FwDataCnt = 0; - return size; +static ssize_t firmware_update_c33(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size, + enum EMEM_TYPE_t emem_type) { + unsigned int i, j; + unsigned int crc_main, crc_main_tp; + unsigned int crc_info, crc_info_tp; + unsigned short reg_data = 0; + int update_pass = 1; + + crc_main = 0xffffffff; + crc_info = 0xffffffff; + + reset_hw(); + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + msleep(300); + + /* erase main */ + firmware_erase_c33(EMEM_MAIN); + msleep(1000); + + reset_hw(); + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + msleep(300); + + /* polling 0x3CE4 is 0x1C70 */ + if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { + do { + reg_data = read_reg(0x3C, 0xE4); + } while (reg_data != 0x1C70); + } + + switch (emem_type) { + case EMEM_ALL: + write_reg(0x3C, 0xE4, 0xE38F); /* for all-blocks */ + break; + case EMEM_MAIN: + write_reg(0x3C, 0xE4, 0x7731); /* for main block */ + break; + case EMEM_INFO: + write_reg(0x3C, 0xE4, 0x7731); /* for info block */ + + write_reg_8bit(0x0F, 0xE6, 0x01); + + write_reg_8bit(0x3C, 0xE4, 0xC5); + write_reg_8bit(0x3C, 0xE5, 0x78); + + write_reg_8bit(0x1E, 0x04, 0x9F); + write_reg_8bit(0x1E, 0x05, 0x82); + + write_reg_8bit(0x0F, 0xE6, 0x00); + msleep(100); + break; + } + + /* polling 0x3CE4 is 0x2F43 */ + do { + reg_data = read_reg(0x3C, 0xE4); + } while (reg_data != 0x2F43); + + /* calculate CRC 32 */ + _CRC_initTable(); + + /* total 32 KB : 2 byte per R/W */ + for (i = 0; i < 32; i++) { + if (i == 31) { + temp[i][1014] = 0x5A; + temp[i][1015] = 0xA5; + + for (j = 0; j < 1016; j++) + crc_main = _CRC_getValue(temp[i][j], crc_main); + } else { + for (j = 0; j < 1024; j++) + crc_main = _CRC_getValue(temp[i][j], crc_main); + } + + for (j = 0; j < 8; j++) + write_i2c_seq(ts_data->client->addr, + &temp[i][j*128], 128); + msleep(100); + + /* polling 0x3CE4 is 0xD0BC */ + do { + reg_data = read_reg(0x3C, 0xE4); + } while (reg_data != 0xD0BC); + + write_reg(0x3C, 0xE4, 0x2F43); + } + + if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { + /* write file done and check crc */ + write_reg(0x3C, 0xE4, 0x1380); + } + msleep(20); + + if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { + /* polling 0x3CE4 is 0x9432 */ + do { + reg_data = read_reg(0x3C, 0xE4); + } while (reg_data != 0x9432); + } + + crc_main = crc_main ^ 0xffffffff; + crc_info = crc_info ^ 0xffffffff; + + if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { + /* CRC Main from TP */ + crc_main_tp = read_reg(0x3C, 0x80); + crc_main_tp = (crc_main_tp << 16) | read_reg(0x3C, 0x82); + + /* CRC Info from TP */ + crc_info_tp = read_reg(0x3C, 0xA0); + crc_info_tp = (crc_info_tp << 16) | read_reg(0x3C, 0xA2); + } + + update_pass = 1; + if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) { + if (crc_main_tp != crc_main) + update_pass = 0; + } + + if (!update_pass) { + DBG("update_C33 failed\n"); + reset_hw(); + FwDataCnt = 0; + return 0; + } + + DBG("update_C33 OK\n"); + reset_hw(); + FwDataCnt = 0; + return size; } - #ifdef FIRMWARE_AUTOUPDATE -unsigned short main_sw_id = 0x7FF, info_sw_id = 0x7FF; -U32 bin_conf_crc32 = 0; +static unsigned short main_sw_id = 0x7FF, info_sw_id = 0x7FF; +static unsigned int bin_conf_crc32; -static U32 _CalMainCRC32(void) +static unsigned int _CalMainCRC32(void) { - U32 ret=0; - U16 reg_data=0; + unsigned int ret = 0; + unsigned short reg_data = 0; - reset_hw(); + reset_hw(); - dbbusDWIICEnterSerialDebugMode(); - dbbusDWIICStopMCU(); - dbbusDWIICIICUseBus(); - dbbusDWIICIICReshape(); - msleep ( 100 ); + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + msleep(100); - //Stop MCU - write_reg ( 0x0F, 0xE6, 0x0001 ); + /* Stop MCU */ + write_reg(0x0F, 0xE6, 0x0001); - // Stop Watchdog - write_reg_8bit ( 0x3C, 0x60, 0x55 ); - write_reg_8bit ( 0x3C, 0x61, 0xAA ); + /* Stop Watchdog */ + write_reg_8bit(0x3C, 0x60, 0x55); + write_reg_8bit(0x3C, 0x61, 0xAA); - //cmd - write_reg ( 0x3C, 0xE4, 0xDF4C ); - write_reg ( 0x1E, 0x04, 0x7d60 ); - // TP SW reset - write_reg ( 0x1E, 0x04, 0x829F ); + /* cmd */ + write_reg(0x3C, 0xE4, 0xDF4C); + write_reg(0x1E, 0x04, 0x7d60); + /* TP SW reset */ + write_reg(0x1E, 0x04, 0x829F); - //MCU run - write_reg ( 0x0F, 0xE6, 0x0000 ); + /* MCU run */ + write_reg(0x0F, 0xE6, 0x0000); - //polling 0x3CE4 - do - { - reg_data = read_reg ( 0x3C, 0xE4 ); - }while ( reg_data != 0x9432 ); + /* polling 0x3CE4 */ + do { + reg_data = read_reg(0x3C, 0xE4); + } while (reg_data != 0x9432); - // Cal CRC Main from TP - ret = read_reg ( 0x3C, 0x80 ); - ret = ( ret << 16 ) | read_reg ( 0x3C, 0x82 ); + /* Cal CRC Main from TP */ + ret = read_reg(0x3C, 0x80); + ret = (ret << 16) | read_reg(0x3C, 0x82); - DBG("[21xxA]:Current main crc32=0x%x\n",ret); - return (ret); + DBG("[21xxA]:Current main crc32=0x%x\n", ret); + return ret; } -static void _ReadBinConfig ( void ) +static void _ReadBinConfig(void) { - U8 dbbus_tx_data[5]={0}; - U8 dbbus_rx_data[4]={0}; - U16 reg_data=0; - - reset_hw(); - - dbbusDWIICEnterSerialDebugMode(); - dbbusDWIICStopMCU(); - dbbusDWIICIICUseBus(); - dbbusDWIICIICReshape(); - msleep ( 100 ); - - //Stop MCU - write_reg ( 0x0F, 0xE6, 0x0001 ); - - // Stop Watchdog - write_reg_8bit ( 0x3C, 0x60, 0x55 ); - write_reg_8bit ( 0x3C, 0x61, 0xAA ); - - //cmd - write_reg ( 0x3C, 0xE4, 0xA4AB ); - write_reg ( 0x1E, 0x04, 0x7d60 ); - - // TP SW reset - write_reg ( 0x1E, 0x04, 0x829F ); - - //MCU run - write_reg ( 0x0F, 0xE6, 0x0000 ); - - //polling 0x3CE4 - do - { - reg_data = read_reg ( 0x3C, 0xE4 ); - } - while ( reg_data != 0x5B58 ); - - dbbus_tx_data[0] = 0x72; - dbbus_tx_data[1] = 0x7F; - dbbus_tx_data[2] = 0x55; - dbbus_tx_data[3] = 0x00; - dbbus_tx_data[4] = 0x04; - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 ); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 ); - if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39) - &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39) - &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39)) - { - main_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30); - } - - dbbus_tx_data[0] = 0x72; - dbbus_tx_data[1] = 0x7F; - dbbus_tx_data[2] = 0xFC; - dbbus_tx_data[3] = 0x00; - dbbus_tx_data[4] = 0x04; - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 ); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 ); - bin_conf_crc32 = dbbus_rx_data[0]; - bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1]; - bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2]; - bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3]; - - dbbus_tx_data[0] = 0x72; - dbbus_tx_data[1] = 0x83; - dbbus_tx_data[2] = 0x00; - dbbus_tx_data[3] = 0x00; - dbbus_tx_data[4] = 0x04; - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 5 ); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4 ); - if ((dbbus_rx_data[0]>=0x30 && dbbus_rx_data[0]<=0x39) - &&(dbbus_rx_data[1]>=0x30 && dbbus_rx_data[1]<=0x39) - &&(dbbus_rx_data[2]>=0x31 && dbbus_rx_data[2]<=0x39)) - { - info_sw_id = (dbbus_rx_data[0]-0x30)*100+(dbbus_rx_data[1]-0x30)*10+(dbbus_rx_data[2]-0x30); - } - - DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n", main_sw_id, info_sw_id, bin_conf_crc32); + unsigned char dbbus_tx_data[5] = {0}; + unsigned char dbbus_rx_data[4] = {0}; + unsigned short reg_data = 0; + + reset_hw(); + + dbbusDWIICEnterSerialDebugMode(); + dbbusDWIICStopMCU(); + dbbusDWIICIICUseBus(); + dbbusDWIICIICReshape(); + msleep(100); + + /* Stop MCU */ + write_reg(0x0F, 0xE6, 0x0001); + + /* Stop Watchdog */ + write_reg_8bit(0x3C, 0x60, 0x55); + write_reg_8bit(0x3C, 0x61, 0xAA); + + /* cmd */ + write_reg(0x3C, 0xE4, 0xA4AB); + write_reg(0x1E, 0x04, 0x7d60); + + /* TP SW reset */ + write_reg(0x1E, 0x04, 0x829F); + + /* MCU run */ + write_reg(0x0F, 0xE6, 0x0000); + + /* polling 0x3CE4 */ + do { + reg_data = read_reg(0x3C, 0xE4); + } while (reg_data != 0x5B58); + + dbbus_tx_data[0] = 0x72; + dbbus_tx_data[1] = 0x7F; + dbbus_tx_data[2] = 0x55; + dbbus_tx_data[3] = 0x00; + dbbus_tx_data[4] = 0x04; + write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5); + read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4); + if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39) + && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39) + && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) { + main_sw_id = (dbbus_rx_data[0] - 0x30) * 100 + + (dbbus_rx_data[1] - 0x30) * 10 + + (dbbus_rx_data[2] - 0x30); + } + + dbbus_tx_data[0] = 0x72; + dbbus_tx_data[1] = 0x7F; + dbbus_tx_data[2] = 0xFC; + dbbus_tx_data[3] = 0x00; + dbbus_tx_data[4] = 0x04; + write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5); + read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4); + bin_conf_crc32 = dbbus_rx_data[0]; + bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[1]; + bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[2]; + bin_conf_crc32 = (bin_conf_crc32<<8)|dbbus_rx_data[3]; + + dbbus_tx_data[0] = 0x72; + dbbus_tx_data[1] = 0x83; + dbbus_tx_data[2] = 0x00; + dbbus_tx_data[3] = 0x00; + dbbus_tx_data[4] = 0x04; + write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 5); + read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4); + if ((dbbus_rx_data[0] >= 0x30 && dbbus_rx_data[0] <= 0x39) + && (dbbus_rx_data[1] >= 0x30 && dbbus_rx_data[1] <= 0x39) + && (dbbus_rx_data[2] >= 0x31 && dbbus_rx_data[2] <= 0x39)) { + info_sw_id = (dbbus_rx_data[0] - 0x30) * 100 + + (dbbus_rx_data[1] - 0x30) * 10 + + (dbbus_rx_data[2] - 0x30); + } + + DBG("[21xxA]:main_sw_id = %d, info_sw_id = %d, bin_conf_crc32=0x%x\n", + main_sw_id, info_sw_id, bin_conf_crc32); } static int fwAutoUpdate(void *unused) { - int time = 0; - ssize_t ret = 0; - - for (time = 0; time < 5; time++) - { - DBG("fwAutoUpdate time = %d\n",time); - ret = firmware_update_c33(NULL, NULL, NULL, 1, EMEM_MAIN); - if (ret == 1) - { - DBG("AUTO_UPDATE OK!!!"); - break; - } - } - if (time == 5) - { - DBG("AUTO_UPDATE failed!!!"); - } - enable_irq(irq_msg21xx); - return 0; + int time = 0; + ssize_t ret = 0; + + for (time = 0; time < 5; time++) { + DBG("fwAutoUpdate time = %d\n", time); + ret = firmware_update_c33(NULL, NULL, NULL, 1, EMEM_MAIN); + if (ret == 1) { + DBG("AUTO_UPDATE OK!!!"); + break; + } + } + if (time == 5) + DBG("AUTO_UPDATE failed!!!"); + enable_irq(ts_data->client->irq); + return 0; } #endif -//------------------------------------------------------------------------------// static ssize_t firmware_update_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { - DBG("*** firmware_update_show() fw_version = %s ***\n", fw_version); + DBG("*** firmware_update_show() fw_version = %s ***\n", fw_version); - return sprintf(buf, "%s\n", fw_version); + return snprintf(buf, sizeof(char) - 1, "%s\n", fw_version); } static ssize_t firmware_update_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) + struct device_attribute *attr, + const char *buf, + size_t size) { - bFwUpdating = 1; - disable_irq(irq_msg21xx); + bFwUpdating = 1; + disable_irq(ts_data->client->irq); - DBG("*** update fw size = %d ***\n", FwDataCnt); - size = firmware_update_c33 (dev, attr, buf, size, EMEM_MAIN); + DBG("*** update fw size = %d ***\n", FwDataCnt); + size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN); - enable_irq(irq_msg21xx); - bFwUpdating = 0; + enable_irq(ts_data->client->irq); + bFwUpdating = 0; - return size; + return size; } -static DEVICE_ATTR(update, SYSFS_AUTHORITY, firmware_update_show, firmware_update_store); +static DEVICE_ATTR(update, (S_IRUGO | S_IWUSR), + firmware_update_show, + firmware_update_store); static ssize_t firmware_version_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { - DBG("*** firmware_version_show() fw_version = %s ***\n", fw_version); + DBG("*** firmware_version_show() fw_version = %s ***\n", fw_version); - return sprintf(buf, "%s\n", fw_version); + return snprintf(buf, sizeof(char) - 1, "%s\n", fw_version); } static ssize_t firmware_version_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) + struct device_attribute *attr, + const char *buf, + size_t size) { - get_customer_firmware_version(); + get_customer_firmware_version(); - DBG("*** firmware_version_store() fw_version = %s ***\n", fw_version); + DBG("*** firmware_version_store() fw_version = %s ***\n", fw_version); - return size; + return size; } -static DEVICE_ATTR(version, SYSFS_AUTHORITY, firmware_version_show, firmware_version_store); +static DEVICE_ATTR(version, (S_IRUGO | S_IWUSR), + firmware_version_show, + firmware_version_store); static ssize_t firmware_data_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { - DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt); + DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt); - return FwDataCnt; + return FwDataCnt; } static ssize_t firmware_data_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) + struct device_attribute *attr, + const char *buf, + size_t size) { - int count = size / 1024; - int i; + int count = size / 1024; + int i; - for (i = 0; i < count; i ++) - { - memcpy(temp[FwDataCnt], buf+(i*1024), 1024); + for (i = 0; i < count; i++) { + memcpy(temp[FwDataCnt], buf + (i * 1024), 1024); - FwDataCnt ++; - } + FwDataCnt++; + } - DBG("***FwDataCnt = %d ***\n", FwDataCnt); + DBG("***FwDataCnt = %d ***\n", FwDataCnt); - if (buf != NULL) - { - DBG("*** buf[0] = %c ***\n", buf[0]); - } + if (buf != NULL) + DBG("*** buf[0] = %c ***\n", buf[0]); - return size; + return size; } -static DEVICE_ATTR(data, SYSFS_AUTHORITY, firmware_data_show, firmware_data_store); +static DEVICE_ATTR(data, (S_IRUGO | S_IWUSR), + firmware_data_show, firmware_data_store); #ifdef TP_PRINT static ssize_t tp_print_show(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { - tp_print_proc_read(); + tp_print_proc_read(); - return sprintf(buf, "%d\n", bTpInSuspend); + return snprintf(buf, sizeof(char) - 1, "%d\n", ts_data->suspended); } static ssize_t tp_print_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) + struct device_attribute *attr, + const char *buf, + size_t size) { - DBG("*** tp_print_store() ***\n"); + DBG("*** tp_print_store() ***\n"); - return size; + return size; } -static DEVICE_ATTR(tpp, SYSFS_AUTHORITY, tp_print_show, tp_print_store); +static DEVICE_ATTR(tpp, (S_IRUGO | S_IWUSR), + tp_print_show, tp_print_store); #endif -//------------------------------------------------------------------------------// #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR -static void _msg_enable_proximity(void) +static void _msg_enable_proximity(void { - U8 tx_data[4] = {0}; - - DBG("_msg_enable_proximity!"); - tx_data[0] = 0x52; - tx_data[1] = 0x00; - tx_data[2] = 0x47; - tx_data[3] = 0xa0; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - - bEnableTpProximity = 1; + unsigned char tx_data[4] = {0}; + + DBG("_msg_enable_proximity!"); + tx_data[0] = 0x52; + tx_data[1] = 0x00; + tx_data[2] = 0x47; + tx_data[3] = 0xa0; + mutex_lock(&msg21xx_mutex); + write_i2c_seq(ts_data->client->addr, &tx_data[0], 4); + mutex_unlock(&msg21xx_mutex); + + bEnableTpProximity = 1; } static void _msg_disable_proximity(void) { - U8 tx_data[4] = {0}; - - DBG("_msg_disable_proximity!"); - tx_data[0] = 0x52; - tx_data[1] = 0x00; - tx_data[2] = 0x47; - tx_data[3] = 0xa1; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &tx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - - bEnableTpProximity = 0; - bFaceClosingTp = 0; + unsigned char tx_data[4] = {0}; + + DBG("_msg_disable_proximity!"); + tx_data[0] = 0x52; + tx_data[1] = 0x00; + tx_data[2] = 0x47; + tx_data[3] = 0xa1; + mutex_lock(&msg21xx_mutex); + write_i2c_seq(ts_data->client->addr, &tx_data[0], 4); + mutex_unlock(&msg21xx_mutex); + + bEnableTpProximity = 0; + bFaceClosingTp = 0; } -void tsps_msg21xx_enable(int en) +static void tsps_msg21xx_enable(int en) { - if (en) - { - _msg_enable_proximity(); - } - else - { - _msg_disable_proximity(); - } + if (en) + _msg_enable_proximity(); + else + _msg_disable_proximity(); } -int tsps_msg21xx_data(void) +static int tsps_msg21xx_data(void) { - return bFaceClosingTp; + return bFaceClosingTp; } #endif -static U8 calculate_checksum(U8 *msg, S32 length) +static int msg21xx_pinctrl_init(void) +{ + int retval; + + /* Get pinctrl if target uses pinctrl */ + ts_data->ts_pinctrl = devm_pinctrl_get(&(i2c_client->dev)); + if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) { + retval = PTR_ERR(ts_data->ts_pinctrl); + dev_dbg(&i2c_client->dev, + "Target does not use pinctrl %d\n", retval); + goto err_pinctrl_get; + } + + ts_data->pinctrl_state_active = pinctrl_lookup_state( + ts_data->ts_pinctrl, PINCTRL_STATE_ACTIVE); + if (IS_ERR_OR_NULL(ts_data->pinctrl_state_active)) { + retval = PTR_ERR(ts_data->pinctrl_state_active); + dev_dbg(&i2c_client->dev, + "Can't lookup %s pinstate %d\n", + PINCTRL_STATE_ACTIVE, retval); + goto err_pinctrl_lookup; + } + + ts_data->pinctrl_state_suspend = pinctrl_lookup_state( + ts_data->ts_pinctrl, PINCTRL_STATE_SUSPEND); + if (IS_ERR_OR_NULL(ts_data->pinctrl_state_suspend)) { + retval = PTR_ERR(ts_data->pinctrl_state_suspend); + dev_dbg(&i2c_client->dev, + "Can't lookup %s pinstate %d\n", + PINCTRL_STATE_SUSPEND, retval); + goto err_pinctrl_lookup; + } + + ts_data->pinctrl_state_release = pinctrl_lookup_state( + ts_data->ts_pinctrl, PINCTRL_STATE_RELEASE); + if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { + retval = PTR_ERR(ts_data->pinctrl_state_release); + dev_dbg(&i2c_client->dev, + "Can't lookup %s pinstate %d\n", + PINCTRL_STATE_RELEASE, retval); + } + + return 0; + +err_pinctrl_lookup: + devm_pinctrl_put(ts_data->ts_pinctrl); +err_pinctrl_get: + ts_data->ts_pinctrl = NULL; + return retval; +} + +static unsigned char calculate_checksum(unsigned char *msg, int length) { - S32 Checksum = 0; - S32 i; + int Checksum = 0, i; - for (i = 0; i < length; i ++) - { - Checksum += msg[i]; - } + for (i = 0; i < length; i++) + Checksum += msg[i]; - return (U8)((-Checksum) & 0xFF); + return (unsigned char)((-Checksum) & 0xFF); } -static S32 parse_info(touchInfo_t *info) +static int parse_info(struct touchInfo_t *info) { - U8 data[DEMO_MODE_PACKET_LENGTH] = {0}; - U8 checksum = 0; - U32 x = 0, y = 0; - U32 x2 = 0, y2 = 0; - U32 delta_x = 0, delta_y = 0; - - mutex_lock(&msg21xx_mutex); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &data[0], DEMO_MODE_PACKET_LENGTH); - mutex_unlock(&msg21xx_mutex); - checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1)); - DBG("check sum: [%x] == [%x]? \n", data[DEMO_MODE_PACKET_LENGTH-1], checksum); - - if(data[DEMO_MODE_PACKET_LENGTH-1] != checksum) - { - DBG("WRONG CHECKSUM\n"); - return -1; - } - - if(data[0] != 0x52) - { - DBG("WRONG HEADER\n"); - return -1; - } - - info->keycode = 0xFF; - if ((data[1] == 0xFF) && (data[2] == 0xFF) && (data[3] == 0xFF) && (data[4] == 0xFF) && (data[6] == 0xFF)) - { - if ((data[5] == 0xFF) || (data[5] == 0)) - { - info->keycode = 0xFF; - } - else if ((data[5] == 1) || (data[5] == 2) || (data[5] == 4) || (data[5] == 8)) - { - if (data[5] == 1) - { - info->keycode = 0; - } - else if (data[5] == 2) - { - info->keycode = 1; - } - else if (data[5] == 4) - { - info->keycode = 2; - } - else if (data[5] == 8) - { - info->keycode = 3; - } - } - #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - else if (bEnableTpProximity &&((data[5] == 0x80) || (data[5] == 0x40))) - { - if (data[5] == 0x80) - { - bFaceClosingTp = 1; - } - else if (data[5] == 0x40) - { - bFaceClosingTp = 0; - } - DBG("bEnableTpProximity=%d; bFaceClosingTp=%d; data[5]=%x;\n", bEnableTpProximity, bFaceClosingTp, data[5]); - return -1; - } - #endif - else - { - DBG("WRONG KEY\n"); - return -1; - } - } - else - { - x = (((data[1] & 0xF0 ) << 4) | data[2]); - y = ((( data[1] & 0x0F) << 8) | data[3]); - delta_x = (((data[4] & 0xF0) << 4 ) | data[5]); - delta_y = (((data[4] & 0x0F) << 8 ) | data[6]); - - if ((delta_x == 0) && (delta_y == 0)) - { - info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH; - info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT; - info->count = 1; - } - else - { - if (delta_x > 2048) - { - delta_x -= 4096; - } - if (delta_y > 2048) - { - delta_y -= 4096; - } - x2 = (U32)((S16)x + (S16)delta_x); - y2 = (U32)((S16)y + (S16)delta_y); - info->point[0].x = x * TOUCH_SCREEN_X_MAX / TPD_WIDTH; - info->point[0].y = y * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT; - info->point[1].x = x2 * TOUCH_SCREEN_X_MAX / TPD_WIDTH; - info->point[1].y = y2 * TOUCH_SCREEN_Y_MAX/ TPD_HEIGHT; - info->count = 2; - } - } - - return 0; + unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0}; + unsigned char checksum = 0; + unsigned int x = 0, y = 0; + unsigned int x2 = 0, y2 = 0; + unsigned int delta_x = 0, delta_y = 0; + + mutex_lock(&msg21xx_mutex); + read_i2c_seq(ts_data->client->addr, &data[0], DEMO_MODE_PACKET_LENGTH); + mutex_unlock(&msg21xx_mutex); + checksum = calculate_checksum(&data[0], (DEMO_MODE_PACKET_LENGTH-1)); + DBG("check sum: [%x] == [%x]?\n", + data[DEMO_MODE_PACKET_LENGTH-1], checksum); + + if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) { + DBG("WRONG CHECKSUM\n"); + return -EINVAL; + } + + if (data[0] != 0x52) { + DBG("WRONG HEADER\n"); + return -EINVAL; + } + + info->keycode = 0xFF; + if ((data[1] == 0xFF) && (data[2] == 0xFF) && + (data[3] == 0xFF) && (data[4] == 0xFF) && + (data[6] == 0xFF)) { + if ((data[5] == 0xFF) || (data[5] == 0)) { + info->keycode = 0xFF; + } else if ((data[5] == 1) || (data[5] == 2) || + (data[5] == 4) || (data[5] == 8)) { + info->keycode = data[5] >> 1; + + DBG("info->keycode index %d\n", info->keycode); + } + #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR + else if (bEnableTpProximity && ((data[5] == 0x80) || + (data[5] == 0x40))) { + if (data[5] == 0x80) + bFaceClosingTp = 1; + else if (data[5] == 0x40) + bFaceClosingTp = 0; + + return -EINVAL; + } + #endif + else { + DBG("WRONG KEY\n"); + return -EINVAL; + } + } else { + x = (((data[1] & 0xF0) << 4) | data[2]); + y = (((data[1] & 0x0F) << 8) | data[3]); + delta_x = (((data[4] & 0xF0) << 4) | data[5]); + delta_y = (((data[4] & 0x0F) << 8) | data[6]); + + if ((delta_x == 0) && (delta_y == 0)) { + info->point[0].x = x * pdata->x_max / TPD_WIDTH; + info->point[0].y = y * pdata->y_max / TPD_HEIGHT; + info->count = 1; + } else { + if (delta_x > 2048) + delta_x -= 4096; + + if (delta_y > 2048) + delta_y -= 4096; + + x2 = (unsigned int)((signed short)x + + (signed short)delta_x); + y2 = (unsigned int)((signed short)y + + (signed short)delta_y); + info->point[0].x = x * pdata->x_max / TPD_WIDTH; + info->point[0].y = y * pdata->y_max / TPD_HEIGHT; + info->point[1].x = x2 * pdata->x_max / TPD_WIDTH; + info->point[1].y = y2 * pdata->y_max / TPD_HEIGHT; + info->count = 2; + } + } + + return 0; } -static void touch_driver_touch_pressed(int x, int y) +static void touch_driver_touch_released(void) { - DBG("point touch pressed"); + int i; + + DBG("point touch released\n"); + + for (i = 0; i < MAX_TOUCH_NUM; i++) { + input_mt_slot(input_dev, i); + input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0); + } - input_report_key(input_dev, BTN_TOUCH, 1); - input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1); - input_report_abs(input_dev, ABS_MT_POSITION_X, x); - input_report_abs(input_dev, ABS_MT_POSITION_Y, y); - input_mt_sync(input_dev); + input_report_key(input_dev, BTN_TOUCH, 0); + input_report_key(input_dev, BTN_TOOL_FINGER, 0); + input_sync(input_dev); } -static void touch_driver_touch_released(void) +/* read data through I2C then report data to input + *sub-system when interrupt occurred + */ +static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id) +{ + struct touchInfo_t info; + int i = 0; + static int last_keycode = 0xFF; + static int last_count; + + DBG("touch_driver_do_work()\n"); + + memset(&info, 0x0, sizeof(info)); + if (parse_info(&info) == 0) { + #ifdef CONFIG_TP_HAVE_KEY + if (info.keycode != 0xFF) { /* key touch pressed */ + if (info.keycode < num_buttons) { + if (info.keycode != last_keycode) { + DBG("key touch pressed"); + + input_report_key(input_dev, + BTN_TOUCH, 1); + input_report_key(input_dev, + button_map[info.keycode], 1); + + last_keycode = info.keycode; + } else { + /* pass duplicate key-pressing */ + DBG("REPEATED KEY\n"); + } + } else { + DBG("WRONG KEY\n"); + } + } else { /* key touch released */ + if (last_keycode != 0xFF) { + DBG("key touch released"); + + input_report_key(input_dev, + BTN_TOUCH, 0); + input_report_key(input_dev, + button_map[last_keycode], + 0); + + last_keycode = 0xFF; + } + } + #endif /* CONFIG_TP_HAVE_KEY */ + + if (info.count > 0) { /* point touch pressed */ + for (i = 0; i < info.count; i++) { + input_mt_slot(input_dev, i); + input_mt_report_slot_state(input_dev, + MT_TOOL_FINGER, 1); + input_report_abs(input_dev, + ABS_MT_TOUCH_MAJOR, 1); + input_report_abs(input_dev, + ABS_MT_POSITION_X, + info.point[i].x); + input_report_abs(input_dev, + ABS_MT_POSITION_Y, + info.point[i].y); + } + last_count = info.count; + } else if (last_count > 0) { /* point touch released */ + for (i = 0; i < last_count; i++) { + input_mt_slot(input_dev, i); + input_mt_report_slot_state(input_dev, + MT_TOOL_FINGER, 0); + } + last_count = 0; + } + + input_report_key(input_dev, BTN_TOUCH, info.count > 0); + input_report_key(input_dev, BTN_TOOL_FINGER, info.count > 0); + + input_sync(input_dev); + } + + return IRQ_HANDLED; +} + + +static int msg21xx_ts_power_init(void) +{ + int rc; + + vdd = regulator_get(&i2c_client->dev, "vdd"); + if (IS_ERR(vdd)) { + rc = PTR_ERR(vdd); + dev_err(&i2c_client->dev, + "Regulator get failed vdd rc=%d\n", rc); + return rc; + } + + if (regulator_count_voltages(vdd) > 0) { + rc = regulator_set_voltage(vdd, MSTAR_VTG_MIN_UV, + MSTAR_VTG_MAX_UV); + if (rc) { + dev_err(&i2c_client->dev, + "Regulator set_vtg failed vdd rc=%d\n", rc); + goto reg_vdd_put; + } + } + + vcc_i2c = regulator_get(&i2c_client->dev, "vcc_i2c"); + if (IS_ERR(vcc_i2c)) { + rc = PTR_ERR(vcc_i2c); + dev_err(&i2c_client->dev, + "Regulator get failed vcc_i2c rc=%d\n", rc); + goto reg_vdd_set_vtg; + } + + if (regulator_count_voltages(vcc_i2c) > 0) { + rc = regulator_set_voltage(vcc_i2c, MSTAR_I2C_VTG_MIN_UV, + MSTAR_I2C_VTG_MAX_UV); + if (rc) { + dev_err(&i2c_client->dev, + "Regulator set_vtg failed vcc_i2c rc=%d\n", rc); + goto reg_vcc_i2c_put; + } + } + + return 0; + +reg_vcc_i2c_put: + regulator_put(vcc_i2c); +reg_vdd_set_vtg: + if (regulator_count_voltages(vdd) > 0) + regulator_set_voltage(vdd, 0, MSTAR_VTG_MAX_UV); +reg_vdd_put: + regulator_put(vdd); + return rc; +} + + +static int msg21xx_ts_power_deinit(void) +{ + if (regulator_count_voltages(vdd) > 0) + regulator_set_voltage(vdd, 0, MSTAR_VTG_MAX_UV); + + regulator_put(vdd); + + if (regulator_count_voltages(vcc_i2c) > 0) + regulator_set_voltage(vcc_i2c, 0, MSTAR_I2C_VTG_MAX_UV); + + regulator_put(vcc_i2c); + return 0; +} + +static int msg21xx_ts_power_on(void) { - DBG("point touch released"); + int rc; + + DBG("*** %s ***\n", __func__); + rc = regulator_enable(vdd); + if (rc) { + dev_err(&i2c_client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + return rc; + } + + rc = regulator_enable(vcc_i2c); + if (rc) { + dev_err(&i2c_client->dev, + "Regulator vcc_i2c enable failed rc=%d\n", rc); + regulator_disable(vdd); + } + + return rc; +} + +static int msg21xx_ts_power_off(void) +{ + int rc; + + DBG("*** %s ***\n", __func__); + rc = regulator_disable(vdd); + if (rc) { + dev_err(&i2c_client->dev, + "Regulator vdd disable failed rc=%d\n", rc); + return rc; + } + + rc = regulator_disable(vcc_i2c); + if (rc) { + dev_err(&i2c_client->dev, + "Regulator vcc_i2c disable failed rc=%d\n", rc); + rc = regulator_enable(vdd); + } + + return rc; +} - input_report_key(input_dev, BTN_TOUCH, 0); - input_mt_sync(input_dev); +static int msg21xx_ts_gpio_configure(bool on) +{ + int ret = 0; + + if (on) { + if (gpio_is_valid(pdata->irq_gpio)) { + ret = gpio_request(pdata->irq_gpio, "msg21xx_irq_gpio"); + if (ret) { + dev_err(&i2c_client->dev, + "Failed to request GPIO[%d], %d\n", + pdata->irq_gpio, ret); + goto err_irq_gpio_req; + } + ret = gpio_direction_input(pdata->irq_gpio); + if (ret) { + dev_err(&i2c_client->dev, + "Failed to set direction for gpio[%d], %d\n", + pdata->irq_gpio, ret); + goto err_irq_gpio_dir; + } + gpio_set_value_cansleep(pdata->irq_gpio, 1); + } else { + dev_err(&i2c_client->dev, "irq gpio not provided\n"); + goto err_irq_gpio_req; + } + + if (gpio_is_valid(pdata->reset_gpio)) { + ret = gpio_request(pdata->reset_gpio, + "msg21xx_reset_gpio"); + if (ret) { + dev_err(&i2c_client->dev, + "Failed to request GPIO[%d], %d\n", + pdata->reset_gpio, ret); + goto err_reset_gpio_req; + } + + /* power on TP */ + ret = gpio_direction_output(pdata->reset_gpio, 1); + if (ret) { + dev_err(&i2c_client->dev, + "Failed to set direction for GPIO[%d], %d\n", + pdata->reset_gpio, ret); + goto err_reset_gpio_dir; + } + msleep(100); + gpio_set_value_cansleep(pdata->reset_gpio, 0); + msleep(20); + gpio_set_value_cansleep(pdata->reset_gpio, 1); + msleep(200); + } else { + dev_err(&i2c_client->dev, "reset gpio not provided\n"); + goto err_reset_gpio_req; + } + + } else { + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_set_value_cansleep(pdata->reset_gpio, 0); + ret = gpio_direction_input(pdata->reset_gpio); + if (ret) + dev_err(&i2c_client->dev, + "Unable to set direction for gpio [%d]\n", + pdata->reset_gpio); + gpio_free(pdata->reset_gpio); + } + } + return 0; +err_reset_gpio_dir: + if (gpio_is_valid(pdata->reset_gpio)) + gpio_free(pdata->irq_gpio); +err_reset_gpio_req: +err_irq_gpio_dir: + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); +err_irq_gpio_req: + return ret; } -/* read data through I2C then report data to input sub-system when interrupt occurred */ -void touch_driver_do_work(struct work_struct *work) +#ifdef CONFIG_PM +static int msg21xx_ts_resume(struct device *dev) { - touchInfo_t info; - int i = 0; - static int last_keycode = 0xFF; - static int last_count = 0; - - DBG("touch_driver_do_work()\n"); - - memset(&info, 0x0, sizeof(info)); - if (0 == parse_info(&info)) - { - #ifdef CONFIG_TP_HAVE_KEY - if (info.keycode != 0xFF) //key touch pressed - { - DBG("touch_driver_do_work() info.keycode=%x, last_keycode=%x, tp_key_array[%d]=%d\n", info.keycode, last_keycode, info.keycode, tp_key_array[info.keycode]); - if (info.keycode < MAX_KEY_NUM) - { - if (info.keycode != last_keycode) - { - DBG("key touch pressed"); - - input_report_key(input_dev, BTN_TOUCH, 1); - input_report_key(input_dev, tp_key_array[info.keycode], 1); - - last_keycode = info.keycode; - } - else - { - /// pass duplicate key-pressing - DBG("REPEATED KEY\n"); - } - } - else - { - DBG("WRONG KEY\n"); - } - } - else //key touch released - { - if (last_keycode != 0xFF) - { - DBG("key touch released"); - - input_report_key(input_dev, BTN_TOUCH, 0); - input_report_key(input_dev, tp_key_array[last_keycode], 0); - - last_keycode = 0xFF; - } - } - #endif //CONFIG_TP_HAVE_KEY - - if (info.count > 0) //point touch pressed - { - for (i = 0; i < info.count; i ++) - { - touch_driver_touch_pressed(info.point[i].x, info.point[i].y); - } - last_count = info.count; - } - else if (last_count > 0) //point touch released - { - touch_driver_touch_released(); - last_count = 0; - } - - input_sync(input_dev); - } - - enable_irq(irq_msg21xx); + int retval; + + mutex_lock(&ts_data->ts_mutex); + if (ts_data->suspended) { + if (ts_data->ts_pinctrl) { + retval = pinctrl_select_state(ts_data->ts_pinctrl, + ts_data->pinctrl_state_active); + if (retval < 0) { + dev_err(dev, "Cannot get active pinctrl state\n"); + mutex_unlock(&ts_data->ts_mutex); + return retval; + } + } + + retval = msg21xx_ts_gpio_configure(true); + if (retval) { + dev_err(dev, "Failed to put gpios in active state %d", + retval); + mutex_unlock(&ts_data->ts_mutex); + return retval; + } + + enable_irq(ts_data->client->irq); + + retval = msg21xx_ts_power_on(); + if (retval) { + dev_err(dev, "msg21xx_ts power on failed"); + mutex_unlock(&ts_data->ts_mutex); + return retval; + } + + ts_data->suspended = 0; + } else { + dev_info(dev, "msg21xx_ts already in resume\n"); + } + mutex_unlock(&ts_data->ts_mutex); + + return 0; } -/* The interrupt service routine will be triggered when interrupt occurred */ -irqreturn_t touch_driver_isr(int irq, void *dev_id) +static int msg21xx_ts_suspend(struct device *dev) { - DBG("touch_driver_isr()\n"); + int retval; + + if (bFwUpdating) { + DBG("suspend bFwUpdating=%d\n", bFwUpdating); + return 0; + } - disable_irq_nosync(irq_msg21xx); - schedule_work(&msg21xx_wk); +#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR + if (bEnableTpProximity) { + DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity); + return 0; + } +#endif - return IRQ_HANDLED; + mutex_lock(&ts_data->ts_mutex); + if (ts_data->suspended == 0) { + disable_irq(ts_data->client->irq); + + touch_driver_touch_released(); + + retval = msg21xx_ts_power_off(); + if (retval) { + dev_err(dev, "msg21xx_ts power off failed"); + mutex_unlock(&ts_data->ts_mutex); + return retval; + } + + if (ts_data->ts_pinctrl) { + retval = pinctrl_select_state(ts_data->ts_pinctrl, + ts_data->pinctrl_state_suspend); + if (retval < 0) { + dev_err(&i2c_client->dev, "Cannot get idle pinctrl state\n"); + mutex_unlock(&ts_data->ts_mutex); + return retval; + } + } + + retval = msg21xx_ts_gpio_configure(false); + if (retval) { + dev_err(dev, "Failed to put gpios in idle state %d", + retval); + mutex_unlock(&ts_data->ts_mutex); + return retval; + } + + ts_data->suspended = 1; + } else { + dev_err(dev, "msg21xx_ts already in suspend\n"); + } + mutex_unlock(&ts_data->ts_mutex); + + + return 0; } +#else +static int msg21xx_ts_resume(struct device *dev) +{ + return 0; +} +static int msg21xx_ts_suspend(struct device *dev) +{ + return 0; +} +#endif #if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) { - struct fb_event *evdata = data; - int *blank; - - if (evdata && evdata->data && event == FB_EVENT_BLANK ) - { - blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - { - if (bTpInSuspend) - { - gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(10); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0); - mdelay(10); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(200); - - touch_driver_touch_released(); - input_sync(input_dev); - - enable_irq(irq_msg21xx); - } - bTpInSuspend = 0; - } - else if (*blank == FB_BLANK_POWERDOWN) - { - if (bFwUpdating) - { - DBG("suspend bFwUpdating=%d\n", bFwUpdating); - return 0; - } - - #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - if (bEnableTpProximity) - { - DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity); - return 0; - } - #endif - - if (bTpInSuspend == 0) - { - disable_irq(irq_msg21xx); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0); - } - bTpInSuspend = 1; - } - } - - return 0; + struct fb_event *evdata = data; + int *blank; + + if (evdata && evdata->data && event == FB_EVENT_BLANK) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + msg21xx_ts_resume(&i2c_client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + msg21xx_ts_suspend(&i2c_client->dev); + } + + return 0; } #endif #ifdef CONFIG_HAS_EARLYSUSPEND -void touch_driver_early_suspend(struct early_suspend *p) +static void touch_driver_early_suspend(struct early_suspend *p) { - DBG("touch_driver_early_suspend()\n"); + DBG("touch_driver_early_suspend()\n"); - if (bFwUpdating) - { - DBG("suspend bFwUpdating=%d\n", bFwUpdating); - return; - } + if (bFwUpdating) { + DBG("suspend bFwUpdating=%d\n", bFwUpdating); + return; + } #ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - if (bEnableTpProximity) - { - DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity); - return; - } + if (bEnableTpProximity) { + DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity); + return; + } #endif - if (bTpInSuspend == 0) - { - disable_irq(irq_msg21xx); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0); - } - bTpInSuspend = 1; + if (bTpInSuspend == 0) { + disable_irq(ts_data->client->irq); + gpio_set_value_cansleep(pdata->reset_gpio, 0); + } + + + if (msg21xx_ts_power_off()) + return; + bTpInSuspend = 1; } -void touch_driver_early_resume(struct early_suspend *p) +static void touch_driver_early_resume(struct early_suspend *p) { - DBG("touch_driver_early_resume() bTpInSuspend=%d\n", bTpInSuspend); - - if (bTpInSuspend) - { - gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(10); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0); - mdelay(10); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(200); - - touch_driver_touch_released(); - input_sync(input_dev); - - enable_irq(irq_msg21xx); - } - bTpInSuspend = 0; + DBG("touch_driver_early_resume() bTpInSuspend=%d\n", bTpInSuspend); + + if (bTpInSuspend) { + gpio_direction_output(pdata->reset_gpio, 1); + msleep(20); + gpio_set_value_cansleep(pdata->reset_gpio, 0); + msleep(20); + gpio_set_value_cansleep(pdata->reset_gpio, 1); + msleep(200); + + touch_driver_touch_released(); + input_sync(input_dev); + + enable_irq(ts_data->client->irq); + + if (msg21xx_ts_power_on()) + return; + } + bTpInSuspend = 0; } #endif -/* probe function is used for matching and initializing input device */ -static int touch_driver_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int msg21xx_get_dt_coords(struct device *dev, char *name, + struct msg21xx_ts_platform_data *pdata) +{ + u32 coords[FT_COORDS_ARR_SIZE]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + coords_size = prop->length / sizeof(u32); + if (coords_size != FT_COORDS_ARR_SIZE) { + dev_err(dev, "invalid %s\n", name); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read %s\n", name); + return rc; + } + + if (!strcmp(name, "mstar,panel-coords")) { + pdata->panel_minx = coords[0]; + pdata->panel_miny = coords[1]; + pdata->panel_maxx = coords[2]; + pdata->panel_maxy = coords[3]; + } else if (!strcmp(name, "mstar,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + dev_err(dev, "unsupported property %s\n", name); + return -EINVAL; + } + + return 0; +} + +static int msg21xx_parse_dt(struct device *dev, + struct msg21xx_ts_platform_data *pdata) { + int rc; + struct device_node *np = dev->of_node; + struct property *prop; + u32 temp_val; + + rc = msg21xx_get_dt_coords(dev, "mstar,panel-coords", pdata); + if (rc && (rc != -EINVAL)) + return rc; + + rc = msg21xx_get_dt_coords(dev, "mstar,display-coords", pdata); + if (rc) + return rc; + + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio", + 0, &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) + return pdata->reset_gpio; + + pdata->irq_gpio = of_get_named_gpio_flags(np, "mstar,irq-gpio", + 0, &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) + return pdata->irq_gpio; + + + prop = of_find_property(np, "mstar,button-map", NULL); + if (prop) { + num_buttons = prop->length / sizeof(temp_val); + if (num_buttons > MAX_BUTTONS) + return -EINVAL; + + rc = of_property_read_u32_array(np, + "mstar,button-map", button_map, + num_buttons); + if (rc) { + dev_err(dev, "Unable to read key codes\n"); + return rc; + } + } + + return 0; +} + +/* probe function is used for matching and initializing input device */ +static int msg21xx_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) { #ifdef FIRMWARE_AUTOUPDATE - unsigned short update_bin_major = 0, update_bin_minor = 0; - int i, update_flag = 0; + unsigned short update_bin_major = 0, update_bin_minor = 0; + int i, update_flag = 0; #endif - int ret = 0; - - if (input_dev != NULL) - { - DBG("input device has found\n"); - return -1; - } - - DBG("*** %s ***\n", __FUNCTION__); - - i2c_client = client; - - ret = gpio_request(MS_TS_MSG21XX_GPIO_RST, "reset"); - if (ret < 0) - { - pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_RST, ret); - goto err0; - } - - // power on TP - gpio_direction_output(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(100); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 0); - mdelay(10); - gpio_set_value(MS_TS_MSG21XX_GPIO_RST, 1); - mdelay(200); - if (0 == get_ic_type()) - { - pr_err("the currnet ic is not Mstar\n"); - ret = -1; - goto err0; - } - - mutex_init(&msg21xx_mutex); - - /* allocate an input device */ - input_dev = input_allocate_device(); - if (!input_dev) - { - ret = -ENOMEM; - pr_err("*** input device allocation failed ***\n"); - goto err1; - } - - input_dev->name = client->name; - input_dev->phys = "I2C"; - input_dev->dev.parent = &client->dev; - input_dev->id.bustype = BUS_I2C; - - /* set the supported event type for input device */ - set_bit(EV_ABS, input_dev->evbit); - set_bit(EV_SYN, input_dev->evbit); - set_bit(EV_KEY, input_dev->evbit); - set_bit(BTN_TOUCH, input_dev->keybit); - set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + int ret = 0; + + if (input_dev != NULL) { + DBG("input device has found\n"); + return -EINVAL; + } + + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct msg21xx_ts_platform_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + ret = msg21xx_parse_dt(&client->dev, pdata); + if (ret) { + dev_err(&client->dev, "DT parsing failed\n"); + return ret; + } + } else + pdata = client->dev.platform_data; + + ts_data = devm_kzalloc(&client->dev, + sizeof(struct msg21xx_ts_data), GFP_KERNEL); + if (!ts_data) + return -ENOMEM; + + DBG("*** %s ***\n", __func__); + + i2c_client = client; + + ret = msg21xx_ts_power_init(); + if (ret) + dev_err(&client->dev, "Mstar power init failed\n"); + + ret = msg21xx_ts_power_on(); + if (ret) { + dev_err(&client->dev, "Mstar power on failed\n"); + goto exit_deinit_power; + } + + ret = msg21xx_pinctrl_init(); + if (!ret && ts_data->ts_pinctrl) { + ret = pinctrl_select_state(ts_data->ts_pinctrl, + ts_data->pinctrl_state_active); + if (ret < 0) + goto exit_pinctrl_select; + } else { + goto exit_pinctrl_init; + } + + ret = msg21xx_ts_gpio_configure(true); + if (ret) { + dev_err(&client->dev, "Failed to configure gpio %d\n", ret); + goto exit_gpio_config; + } + + if (get_ic_type() == 0) { + pr_err("the currnet ic is not Mstar\n"); + ret = -1; + goto err_wrong_ic_type; + } + + mutex_init(&msg21xx_mutex); + mutex_init(&ts_data->ts_mutex); + + /* allocate an input device */ + input_dev = input_allocate_device(); + if (!input_dev) { + ret = -ENOMEM; + pr_err("*** input device allocation failed ***\n"); + goto err_input_allocate_dev; + } + + input_dev->name = client->name; + input_dev->phys = "I2C"; + input_dev->dev.parent = &client->dev; + input_dev->id.bustype = BUS_I2C; + + /* set the supported event type for input device */ + set_bit(EV_ABS, input_dev->evbit); + set_bit(EV_SYN, input_dev->evbit); + set_bit(EV_KEY, input_dev->evbit); + set_bit(BTN_TOUCH, input_dev->keybit); + set_bit(BTN_TOOL_FINGER, input_dev->keybit); + set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + + ts_data->input_dev = input_dev; + ts_data->client = client; + ts_data->pdata = pdata; + + input_set_drvdata(input_dev, ts_data); + i2c_set_clientdata(client, ts_data); #ifdef CONFIG_TP_HAVE_KEY - { - int i; - for (i = 0; i < MAX_KEY_NUM; i ++) - { - input_set_capability(input_dev, EV_KEY, tp_key_array[i]); - } - } + { + int i; + + for (i = 0; i < num_buttons; i++) + input_set_capability(input_dev, EV_KEY, button_map[i]); + } #endif - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_X, TOUCH_SCREEN_X_MIN, TOUCH_SCREEN_X_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, TOUCH_SCREEN_Y_MIN, TOUCH_SCREEN_Y_MAX, 0, 0); - - /* register the input device to input sub-system */ - ret = input_register_device(input_dev); - if (ret < 0) - { - pr_err("*** Unable to register ms-touchscreen input device ***\n"); - goto err1; - } - - /* set sysfs for firmware */ - firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); //client->name - if (IS_ERR(firmware_class)) - pr_err("Failed to create class(firmware)!\n"); - - firmware_cmd_dev = device_create(firmware_class, NULL, 0, NULL, "device"); - if (IS_ERR(firmware_cmd_dev)) - pr_err("Failed to create device(firmware_cmd_dev)!\n"); - - // version - if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0) - pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name); - // update - if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0) - pr_err("Failed to create device file(%s)!\n", dev_attr_update.attr.name); - // data - if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0) - pr_err("Failed to create device file(%s)!\n", dev_attr_data.attr.name); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, + 0, 2, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + TOUCH_SCREEN_X_MIN, pdata->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + TOUCH_SCREEN_Y_MIN, pdata->y_max, 0, 0); + input_mt_init_slots(input_dev, MAX_TOUCH_NUM, 0); + + /* register the input device to input sub-system */ + ret = input_register_device(input_dev); + if (ret < 0) { + pr_err("*** Unable to register ms-touchscreen input device ***\n"); + goto err_input_reg_dev; + } + + /* set sysfs for firmware */ + firmware_class = class_create(THIS_MODULE, "ms-touchscreen-msg20xx"); + if (IS_ERR(firmware_class)) + pr_err("Failed to create class(firmware)!\n"); + + firmware_cmd_dev = device_create(firmware_class, NULL, 0, + NULL, "device"); + if (IS_ERR(firmware_cmd_dev)) + pr_err("Failed to create device(firmware_cmd_dev)!\n"); + + /* version */ + if (device_create_file(firmware_cmd_dev, &dev_attr_version) < 0) + pr_err("Failed to create device file(%s)!\n", + dev_attr_version.attr.name); + /* update */ + if (device_create_file(firmware_cmd_dev, &dev_attr_update) < 0) + pr_err("Failed to create device file(%s)!\n", + dev_attr_update.attr.name); + /* data */ + if (device_create_file(firmware_cmd_dev, &dev_attr_data) < 0) + pr_err("Failed to create device file(%s)!\n", + dev_attr_data.attr.name); #ifdef TP_PRINT - tp_print_create_entry(); + tp_print_create_entry(); #endif - dev_set_drvdata(firmware_cmd_dev, NULL); + dev_set_drvdata(firmware_cmd_dev, NULL); - /* initialize the work queue */ - INIT_WORK(&msg21xx_wk, touch_driver_do_work); + ret = request_threaded_irq(client->irq, NULL, + msg21xx_ts_interrupt, + pdata->irq_gpio_flags | IRQF_ONESHOT, + "msg21xx", ts_data); + if (ret) + goto err_req_irq; - ret = gpio_request(MS_TS_MSG21XX_GPIO_INT, "interrupt"); - if (ret < 0) - { - pr_err("*** Failed to request GPIO %d, error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret); - goto err2; - } - gpio_direction_input(MS_TS_MSG21XX_GPIO_INT); - gpio_set_value(MS_TS_MSG21XX_GPIO_INT, 1); - - irq_msg21xx = gpio_to_irq(MS_TS_MSG21XX_GPIO_INT); - - /* request an irq and register the isr */ - ret = request_irq(irq_msg21xx, touch_driver_isr, IRQF_TRIGGER_RISING, "msg21xx", NULL); - if (ret != 0) - { - pr_err("*** Unable to claim irq %d; error %d ***\n", MS_TS_MSG21XX_GPIO_INT, ret); - goto err3; - } - - disable_irq(irq_msg21xx); + disable_irq(ts_data->client->irq); #if defined(CONFIG_FB) - msg21xx_fb_notif.notifier_call = fb_notifier_callback; - ret = fb_register_client(&msg21xx_fb_notif); -#elif defined (CONFIG_HAS_EARLYSUSPEND) - mstar_ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; - mstar_ts_early_suspend.suspend = touch_driver_early_suspend; - mstar_ts_early_suspend.resume = touch_driver_early_resume; - register_early_suspend(&mstar_ts_early_suspend); + ts_data->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts_data->fb_notif); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + mstar_ts_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; + mstar_ts_early_suspend.suspend = touch_driver_early_suspend; + mstar_ts_early_suspend.resume = touch_driver_early_resume; + register_early_suspend(&mstar_ts_early_suspend); #endif -#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR - tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, &tsps_msg21xx_data); +#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR + tsps_assist_register_callback("msg21xx", &tsps_msg21xx_enable, + &tsps_msg21xx_data); #endif #ifdef FIRMWARE_AUTOUPDATE - get_customer_firmware_version(); - _ReadBinConfig(); - - if (main_sw_id == info_sw_id) - { - if (_CalMainCRC32() == bin_conf_crc32) - { - if ((main_sw_id >= SWID_START) && (main_sw_id < SWID_NULL)) - { - update_bin_major= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f4e]; - update_bin_minor= (MSG_FIRMWARE[main_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[main_sw_id-SWID_START][0x7f50]; - - //check upgrading - if ((update_bin_major == fw_version_major) && (update_bin_minor > fw_version_minor)) - { - update_flag = 1; - } - } - DBG("MAIN sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",main_sw_id,update_flag,update_bin_major,update_bin_minor); - } - else - { - if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL)) - { - update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e]; - update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50]; - update_flag = 1; - } - DBG("INFO1 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor); - } - } - else - { - if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL)) - { - update_bin_major= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4f] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f4e]; - update_bin_minor= (MSG_FIRMWARE[info_sw_id-SWID_START][0x7f51] << 8) + MSG_FIRMWARE[info_sw_id-SWID_START][0x7f50]; - update_flag = 1; - } - DBG("INFO2 sw_id=%d,update_flag=%d,update_bin_major=%d,update_bin_minor=%d\n",info_sw_id,update_flag,update_bin_major,update_bin_minor); - } - - if (update_flag == 1) - { - DBG("MSG21XX_fw_auto_update begin....\n"); - //transfer data - for (i = 0; i < 33; i++) - { - firmware_data_store(NULL, NULL, &(MSG_FIRMWARE[info_sw_id-SWID_START][i*1024]), 1024); - } - - kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update"); - DBG("*** mstar touch screen registered ***\n"); - return 0; - } - - reset_hw(); + get_customer_firmware_version(); + _ReadBinConfig(); + + if (main_sw_id == info_sw_id) { + if (_CalMainCRC32() == bin_conf_crc32) { + if ((main_sw_id >= SWID_START) && + (main_sw_id < SWID_NULL)) { + update_bin_major = (MSG_FIRMWARE + [main_sw_id - SWID_START][0x7f4f] << 8) + + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f4e]; + update_bin_minor = (MSG_FIRMWARE + [main_sw_id - SWID_START][0x7f51] << 8) + + MSG_FIRMWARE[main_sw_id - SWID_START][0x7f50]; + + /* check upgrading */ + if ((update_bin_major == fw_version_major) && + (update_bin_minor > fw_version_minor)) { + update_flag = 1; + } + } + } else { + if ((info_sw_id >= SWID_START) && + (info_sw_id < SWID_NULL)) { + update_bin_major = (MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f4f] << 8) + + MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f4e]; + update_bin_minor = (MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f51] << 8) + + MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f50]; + update_flag = 1; + } + } + } else { + if ((info_sw_id >= SWID_START) && (info_sw_id < SWID_NULL)) { + update_bin_major = (MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f4f] << 8) + + MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f4e]; + update_bin_minor = (MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f51] << 8) + + MSG_FIRMWARE + [info_sw_id - SWID_START][0x7f50]; + update_flag = 1; + } + } + + if (update_flag == 1) { + DBG("MSG21XX_fw_auto_update begin....\n"); + /* transfer data */ + for (i = 0; i < 33; i++) { + firmware_data_store(NULL, NULL, + &(MSG_FIRMWARE[info_sw_id - SWID_START][i * 1024]), + 1024); + } + + kthread_run(fwAutoUpdate, 0, "MSG21XX_fw_auto_update"); + DBG("*** mstar touch screen registered ***\n"); + return 0; + } + + reset_hw(); #endif - DBG("*** mstar touch screen registered ***\n"); - enable_irq(irq_msg21xx); - return 0; - -err3: - free_irq(irq_msg21xx, input_dev); - -err2: - gpio_free(MS_TS_MSG21XX_GPIO_INT); - -err1: - mutex_destroy(&msg21xx_mutex); - input_unregister_device(input_dev); - input_free_device(input_dev); - input_dev = NULL; - -err0: - gpio_free(MS_TS_MSG21XX_GPIO_RST); - - return ret; + DBG("*** mstar touch screen registered ***\n"); + enable_irq(ts_data->client->irq); + return 0; + +err_req_irq: + free_irq(ts_data->client->irq, input_dev); + +err_input_reg_dev: +err_input_allocate_dev: + mutex_destroy(&msg21xx_mutex); + mutex_destroy(&ts_data->ts_mutex); + input_unregister_device(input_dev); + input_free_device(input_dev); + input_dev = NULL; + +err_wrong_ic_type: + msg21xx_ts_gpio_configure(false); +exit_gpio_config: +exit_pinctrl_select: + if (ts_data->ts_pinctrl) { + if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { + devm_pinctrl_put(ts_data->ts_pinctrl); + ts_data->ts_pinctrl = NULL; + } else { + ret = pinctrl_select_state(ts_data->ts_pinctrl, + ts_data->pinctrl_state_release); + if (ret < 0) + pr_err("Cannot get release pinctrl state\n"); + } + } +exit_pinctrl_init: + msg21xx_ts_power_off(); +exit_deinit_power: + msg21xx_ts_power_deinit(); + + return ret; } -/* remove function is triggered when the input device is removed from input sub-system */ +/* remove function is triggered when the input device is removed + *from input sub-system + */ static int touch_driver_remove(struct i2c_client *client) { - DBG("touch_driver_remove()\n"); - - free_irq(irq_msg21xx, input_dev); - gpio_free(MS_TS_MSG21XX_GPIO_INT); - gpio_free(MS_TS_MSG21XX_GPIO_RST); - input_unregister_device(input_dev); - mutex_destroy(&msg21xx_mutex); - - return 0; + int retval = 0; + + DBG("touch_driver_remove()\n"); + + free_irq(ts_data->client->irq, input_dev); + gpio_free(pdata->irq_gpio); + gpio_free(pdata->reset_gpio); + + if (ts_data->ts_pinctrl) { + if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) { + devm_pinctrl_put(ts_data->ts_pinctrl); + ts_data->ts_pinctrl = NULL; + } else { + retval = pinctrl_select_state(ts_data->ts_pinctrl, + ts_data->pinctrl_state_release); + if (retval < 0) + pr_err("Cannot get release pinctrl state\n"); + } + } + + input_unregister_device(input_dev); + mutex_destroy(&msg21xx_mutex); + mutex_destroy(&ts_data->ts_mutex); + + return retval; } -/* The I2C device list is used for matching I2C device and I2C device driver. */ -static const struct i2c_device_id touch_device_id[] = -{ - {"msg21xx", 0}, - {}, /* should not omitted */ +/* The I2C device list is used for matching I2C device + *and I2C device driver. + */ +static const struct i2c_device_id touch_device_id[] = { + {"msg21xx", 0}, + {}, /* should not omitted */ +}; + +static const struct of_device_id msg21xx_match_table[] = { + { .compatible = "mstar,msg21xx", }, + { }, }; MODULE_DEVICE_TABLE(i2c, touch_device_id); -static struct i2c_driver touch_device_driver = -{ - .driver = { - .name = "msg21xx", - .owner = THIS_MODULE, - }, - .probe = touch_driver_probe, - .remove = touch_driver_remove, - .id_table = touch_device_id, +static struct i2c_driver touch_device_driver = { + .driver = { + .name = "ms-msg21xx", + .owner = THIS_MODULE, + .of_match_table = msg21xx_match_table, + }, + .probe = msg21xx_ts_probe, + .remove = touch_driver_remove, + .id_table = touch_device_id, }; static int __init touch_driver_init(void) { - int ret; - - /* register driver */ - ret = i2c_add_driver(&touch_device_driver); - if (ret < 0) - { - DBG("add touch_device_driver i2c driver failed.\n"); - return -ENODEV; - } - DBG("add touch_device_driver i2c driver.\n"); - - return ret; + int ret; + + /* register driver */ + ret = i2c_add_driver(&touch_device_driver); + if (ret < 0) { + DBG("add touch_device_driver i2c driver failed.\n"); + return -ENODEV; + } + DBG("add touch_device_driver i2c driver.\n"); + + return ret; } static void __exit touch_driver_exit(void) { - DBG("remove touch_device_driver i2c driver.\n"); + DBG("remove touch_device_driver i2c driver.\n"); - i2c_del_driver(&touch_device_driver); + i2c_del_driver(&touch_device_driver); } #ifdef TP_PRINT #include <linux/proc_fs.h> -static U16 InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256; -static U8 row, units, cnt; +static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256; +static unsigned char row, units, cnt; static int tp_print_proc_read(void) { - U16 i, j; - U16 left, offset = 0; - U8 dbbus_tx_data[3] = {0}; - U8 u8Data; - S16 s16Data; - S32 s32Data; - char *buf = NULL; - - left = cnt*row*units; - if ((bTpInSuspend == 0) && (InfoAddr != 0x0F) && (PoolAddr != 0x10) && (left > 0)) - { - buf = kmalloc(left, GFP_KERNEL); - if (buf != NULL) - { - printk("tpp: \n"); - - while (left > 0) - { - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) & 0xFF; - dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &buf[offset], left > TransLen ? TransLen : left); - mutex_unlock(&msg21xx_mutex); - - if (left > TransLen) - { - left -= TransLen; - offset += TransLen; - } - else - { - left = 0; - } - } - - for (i = 0; i < cnt; i++) - { - printk("tpp: "); - for (j = 0; j < row; j++) - { - if (units == 1) - { - u8Data = buf[i*row*units + j*units]; - printk("%d\t", u8Data); - } - else if (units == 2) - { - s16Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8); - printk("%d\t", s16Data); - } - else if (units == 4) - { - s32Data = buf[i*row*units + j*units] + (buf[i*row*units + j*units + 1] << 8) + (buf[i*row*units + j*units + 2] << 16) + (buf[i*row*units + j*units + 3] << 24); - printk("%d\t", s32Data); - } - } - printk("\n"); - } - - kfree(buf); - } - } - - return 0; + unsigned short i, j; + unsigned short left, offset = 0; + unsigned char dbbus_tx_data[3] = {0}; + unsigned char u8Data; + signed short s16Data; + int s32Data; + char *buf = NULL; + + left = cnt*row*units; + if ((ts_data->suspended == 0) && + (InfoAddr != 0x0F) && + (PoolAddr != 0x10) && + (left > 0)) { + buf = kmalloc(left, GFP_KERNEL); + if (buf != NULL) { + + while (left > 0) { + dbbus_tx_data[0] = 0x53; + dbbus_tx_data[1] = ((PoolAddr + offset) >> 8) + & 0xFF; + dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF; + mutex_lock(&msg21xx_mutex); + write_i2c_seq(ts_data->client->addr, + &dbbus_tx_data[0], 3); + read_i2c_seq(ts_data->client->addr, + &buf[offset], + left > TransLen ? TransLen : left); + mutex_unlock(&msg21xx_mutex); + + if (left > TransLen) { + left -= TransLen; + offset += TransLen; + } else { + left = 0; + } + } + + for (i = 0; i < cnt; i++) { + for (j = 0; j < row; j++) { + if (units == 1) { + u8Data = buf[i * row * units + + j * units]; + } else if (units == 2) { + s16Data = buf[i * row * units + + j * units] + + (buf[i * row * units + + j * units + 1] << 8); + } else if (units == 4) { + s32Data = buf[i * row * units + + j * units] + + (buf[i * row * units + + j * units + 1] << 8) + + (buf[i * row * units + + j * units + 2] << 16) + + (buf[i * row * units + + j * units + 3] << 24); + } + } + } + + kfree(buf); + } + } + + return 0; } static void tp_print_create_entry(void) { - U8 dbbus_tx_data[3] = {0}; - U8 dbbus_rx_data[8] = {0}; - - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = 0x00; - dbbus_tx_data[2] = 0x58; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 4); - mutex_unlock(&msg21xx_mutex); - InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0]; - PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2]; - printk("InfoAddr=0x%X\n", InfoAddr); - printk("PoolAddr=0x%X\n", PoolAddr); - - if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) - { - msleep(10); - dbbus_tx_data[0] = 0x53; - dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF; - dbbus_tx_data[2] = InfoAddr & 0xFF; - mutex_lock(&msg21xx_mutex); - write_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_tx_data[0], 3); - read_i2c_seq(SLAVE_I2C_ID_DWI2C, &dbbus_rx_data[0], 8); - mutex_unlock(&msg21xx_mutex); - - units = dbbus_rx_data[0]; - row = dbbus_rx_data[1]; - cnt = dbbus_rx_data[2]; - TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6]; - printk("tpp: row=%d, units=%d\n", row, units); - printk("tpp: cnt=%d, TransLen=%d\n", cnt, TransLen); - - // tpp - if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0) - { - pr_err("Failed to create device file(%s)!\n", dev_attr_tpp.attr.name); - } - } + unsigned char dbbus_tx_data[3] = {0}; + unsigned char dbbus_rx_data[8] = {0}; + + dbbus_tx_data[0] = 0x53; + dbbus_tx_data[1] = 0x00; + dbbus_tx_data[2] = 0x58; + mutex_lock(&msg21xx_mutex); + write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3); + read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 4); + mutex_unlock(&msg21xx_mutex); + InfoAddr = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0]; + PoolAddr = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2]; + + if ((InfoAddr != 0x0F) && (PoolAddr != 0x10)) { + msleep(20); + dbbus_tx_data[0] = 0x53; + dbbus_tx_data[1] = (InfoAddr >> 8) & 0xFF; + dbbus_tx_data[2] = InfoAddr & 0xFF; + mutex_lock(&msg21xx_mutex); + write_i2c_seq(ts_data->client->addr, &dbbus_tx_data[0], 3); + read_i2c_seq(ts_data->client->addr, &dbbus_rx_data[0], 8); + mutex_unlock(&msg21xx_mutex); + + units = dbbus_rx_data[0]; + row = dbbus_rx_data[1]; + cnt = dbbus_rx_data[2]; + TransLen = (dbbus_rx_data[7]<<8) + dbbus_rx_data[6]; + + if (device_create_file(firmware_cmd_dev, &dev_attr_tpp) < 0) { + pr_err("Failed to create device file(%s)!\n", + dev_attr_tpp.attr.name); + } + } } #endif @@ -1754,4 +2145,3 @@ module_init(touch_driver_init); module_exit(touch_driver_exit); MODULE_AUTHOR("MStar Semiconductor, Inc."); MODULE_LICENSE("GPL v2"); - |
