summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-18 12:03:54 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-18 12:03:54 -0700
commita18fa34ff288a8df05224c95c9bd7679cf740a43 (patch)
tree910fc1f455264f8877af2f9bfc883819979bc49f /drivers/input
parent86f3aea3e0ef79b4d4500b4276bc316ceb454e36 (diff)
parentfe7a0cf51a101ebb5639ba4190dcc49d1502bf11 (diff)
Merge "input: msg21xx_ts: Mstar touch driver optimization"
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/msg21xx_ts.c1455
1 files changed, 761 insertions, 694 deletions
diff --git a/drivers/input/touchscreen/msg21xx_ts.c b/drivers/input/touchscreen/msg21xx_ts.c
index 8f2c4da578fc..fe8c6e1647f8 100644
--- a/drivers/input/touchscreen/msg21xx_ts.c
+++ b/drivers/input/touchscreen/msg21xx_ts.c
@@ -30,10 +30,8 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/delay.h>
-#include <linux/slab.h>
#include <linux/firmware.h>
-#include <linux/string.h>
-#include <linux/kthread.h>
+#include <linux/debugfs.h>
#include <linux/regulator/consumer.h>
#if defined(CONFIG_FB)
@@ -67,6 +65,13 @@
#define MSTAR_CHIPTOP_REGISTER_BANK 0x1E
#define MSTAR_CHIPTOP_REGISTER_ICTYPE 0xCC
#define MSTAR_INIT_SW_ID 0x7FF
+#define MSTAR_DEBUG_DIR_NAME "ts_debug"
+
+#define MSG_FW_FILE_MAJOR_VERSION(x) \
+ (((x)->data[0x7f4f] << 8) + ((x)->data[0x7f4e]))
+
+#define MSG_FW_FILE_MINOR_VERSION(x) \
+ (((x)->data[0x7f51] << 8) + ((x)->data[0x7f50]))
/*
* Note.
@@ -89,7 +94,6 @@ static unsigned char MSG_FIRMWARE[1][33*1024] = { {
#endif
#define CONFIG_TP_HAVE_KEY
-
#define PINCTRL_STATE_ACTIVE "pmx_ts_active"
#define PINCTRL_STATE_SUSPEND "pmx_ts_suspend"
#define PINCTRL_STATE_RELEASE "pmx_ts_release"
@@ -97,30 +101,16 @@ static unsigned char MSG_FIRMWARE[1][33*1024] = { {
#define SLAVE_I2C_ID_DBBUS (0xC4>>1)
#define DEMO_MODE_PACKET_LENGTH (8)
-#define MAX_TOUCH_NUM (2)
#define TP_PRINT
-#ifdef TP_PRINT
-static int tp_print_proc_read(void);
-static void tp_print_create_entry(void);
-#endif
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;
-
-static unsigned short update_bin_major, update_bin_minor;
+static unsigned short fw_file_major, fw_file_minor;
static unsigned short main_sw_id = MSTAR_INIT_SW_ID;
static unsigned short info_sw_id = MSTAR_INIT_SW_ID;
static unsigned int bin_conf_crc32;
@@ -128,15 +118,12 @@ static unsigned int bin_conf_crc32;
struct msg21xx_ts_platform_data {
const char *name;
char fw_name[MSTAR_FW_NAME_MAX_LEN];
- char *fw_version;
- unsigned short fw_version_major;
- unsigned short fw_version_minor;
- u32 irqflags;
+ u8 fw_version_major;
+ u8 fw_version_minor;
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;
@@ -153,26 +140,33 @@ struct msg21xx_ts_platform_data {
int (*power_on)(bool);
int (*power_init)(bool);
int (*power_on)(bool);
+ u8 ic_type;
+ u32 button_map[MAX_BUTTONS];
+ u32 num_buttons;
+ u32 hard_reset_delay_ms;
+ u32 post_hard_reset_delay_ms;
+ bool updating_fw;
+};
+
+/* Touch Data Type Definition */
+struct touchPoint_t {
+ unsigned short x;
+ unsigned short y;
};
-static struct msg21xx_ts_platform_data *pdata;
+struct touchInfo_t {
+ struct touchPoint_t *point;
+ unsigned char count;
+ unsigned char keycode;
+};
struct msg21xx_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
- const struct msg21xx_ts_platform_data *pdata;
+ 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;
#endif
@@ -181,10 +175,9 @@ struct msg21xx_ts_data {
struct pinctrl_state *pinctrl_state_suspend;
struct pinctrl_state *pinctrl_state_release;
struct mutex ts_mutex;
+ struct touchInfo_t info;
};
-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);
@@ -195,23 +188,15 @@ static unsigned char bEnableTpProximity;
static unsigned char bFaceClosingTp;
#endif
-static struct mutex msg21xx_mutex;
-static struct input_dev *input_dev;
-
-
-/* Data Type Definition */
+#ifdef TP_PRINT
+static int tp_print_proc_read(struct msg21xx_ts_data *ts_data);
+static void tp_print_create_entry(struct msg21xx_ts_data *ts_data);
+#endif
-struct touchPoint_t {
- unsigned short x;
- unsigned short y;
-};
-
-struct touchInfo_t {
- struct touchPoint_t point[MAX_TOUCH_NUM];
- unsigned char count;
- unsigned char keycode;
-};
+static void _ReadBinConfig(struct msg21xx_ts_data *ts_data);
+static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data);
+static struct mutex msg21xx_mutex;
enum EMEM_TYPE_t {
EMEM_ALL = 0,
@@ -259,26 +244,25 @@ static void _CRC_initTable(void)
}
}
-static void reset_hw(void)
+static void msg21xx_reset_hw(struct msg21xx_ts_platform_data *pdata)
{
- 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 */
+ /* Note that the RST must be in LOW 10ms at least */
+ usleep(pdata->hard_reset_delay_ms * 1000);
gpio_set_value_cansleep(pdata->reset_gpio, 1);
/* Enable the interrupt service thread/routine for INT after 50ms */
- msleep(100);
+ usleep(pdata->post_hard_reset_delay_ms * 1000);
}
-static int read_i2c_seq(unsigned char addr, unsigned char *buf,
- unsigned short size)
+static int read_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr,
+ unsigned char *buf, unsigned short size)
{
int rc = 0;
struct i2c_msg msgs[] = {
{
.addr = addr,
- .flags = I2C_M_RD, /* read flag*/
+ .flags = I2C_M_RD, /* read flag */
.len = size,
.buf = buf,
},
@@ -287,25 +271,27 @@ static int read_i2c_seq(unsigned char addr, unsigned char *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 (ts_data->client != NULL) {
+ rc = i2c_transfer(ts_data->client->adapter, msgs, 1);
if (rc < 0)
- DBG("read_i2c_seq() error %d\n", rc);
+ dev_err(&ts_data->client->dev,
+ "%s error %d\n", __func__, rc);
} else {
- DBG("i2c_client is NULL\n");
+ dev_err(&ts_data->client->dev, "ts_data->client is NULL\n");
}
return rc;
}
-static int write_i2c_seq(unsigned char addr, unsigned char *buf,
- unsigned short size)
+static int write_i2c_seq(struct msg21xx_ts_data *ts_data, unsigned char addr,
+ unsigned char *buf, unsigned short size)
{
int rc = 0;
struct i2c_msg msgs[] = {
{
.addr = addr,
- /* if read flag is undefined,
+ /*
+ * if read flag is undefined,
* then it means write flag.
*/
.flags = 0,
@@ -314,48 +300,55 @@ static int write_i2c_seq(unsigned char addr, unsigned char *buf,
},
};
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ /*
+ * 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 (ts_data->client != NULL) {
+ rc = i2c_transfer(ts_data->client->adapter, msgs, 1);
if (rc < 0)
- DBG("write_i2c_seq() error %d\n", rc);
+ dev_err(&ts_data->client->dev,
+ "%s error %d\n", __func__, rc);
} else {
- DBG("i2c_client is NULL\n");
+ dev_err(&ts_data->client->dev, "ts_data->client is NULL\n");
}
return rc;
}
-static unsigned short read_reg(unsigned char bank, unsigned char addr)
+static unsigned short read_reg(struct msg21xx_ts_data *ts_data,
+ unsigned char bank, unsigned char addr)
{
unsigned char tx_data[3] = {0x10, bank, addr};
unsigned char 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);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
+ read_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, rx_data, sizeof(rx_data));
return rx_data[1] << 8 | rx_data[0];
}
-static void write_reg(unsigned char bank, unsigned char addr,
+static void write_reg(struct msg21xx_ts_data *ts_data, unsigned char bank,
+ unsigned char addr,
unsigned short data)
{
unsigned char tx_data[5] = {0x10, bank, addr, data & 0xFF, data >> 8};
write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 5);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
}
-static void write_reg_8bit(unsigned char bank, unsigned char addr,
+static void write_reg_8bit(struct msg21xx_ts_data *ts_data, unsigned char bank,
+ unsigned char addr,
unsigned char data)
{
unsigned char tx_data[4] = {0x10, bank, addr, data};
write_i2c_seq(SLAVE_I2C_ID_DBBUS, &tx_data[0], 4);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, tx_data, sizeof(tx_data));
}
-static void dbbusDWIICEnterSerialDebugMode(void)
+static void dbbusDWIICEnterSerialDebugMode(struct msg21xx_ts_data *ts_data)
{
unsigned char data[5];
@@ -366,120 +359,109 @@ static void dbbusDWIICEnterSerialDebugMode(void)
data[3] = 0x44;
data[4] = 0x42;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 5);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
}
-static void dbbusDWIICStopMCU(void)
+static void dbbusDWIICStopMCU(struct msg21xx_ts_data *ts_data)
{
unsigned char data[1];
/* Stop the MCU */
data[0] = 0x37;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
}
-static void dbbusDWIICIICUseBus(void)
+static void dbbusDWIICIICUseBus(struct msg21xx_ts_data *ts_data)
{
unsigned char data[1];
/* IIC Use Bus */
data[0] = 0x35;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
}
-static void dbbusDWIICIICReshape(void)
+static void dbbusDWIICIICReshape(struct msg21xx_ts_data *ts_data)
{
unsigned char data[1];
/* IIC Re-shape */
data[0] = 0x71;
- write_i2c_seq(SLAVE_I2C_ID_DBBUS, data, 1);
+ write_i2c_seq(ts_data, SLAVE_I2C_ID_DBBUS, data, sizeof(data));
}
-static unsigned char get_ic_type(void)
+static unsigned char msg21xx_get_ic_type(struct msg21xx_ts_data *ts_data)
{
unsigned char ic_type = 0;
unsigned char bank;
unsigned char addr;
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
+ msg21xx_reset_hw(ts_data->pdata);
+ dbbusDWIICEnterSerialDebugMode(ts_data);
+ dbbusDWIICStopMCU(ts_data);
+ dbbusDWIICIICUseBus(ts_data);
+ dbbusDWIICIICReshape(ts_data);
msleep(300);
/* stop mcu */
- write_reg_8bit(0x0F, 0xE6, 0x01);
+ write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01);
/* disable watch dog */
- write_reg(0x3C, 0x60, 0xAA55);
+ write_reg(ts_data, 0x3C, 0x60, 0xAA55);
/* get ic type */
bank = MSTAR_CHIPTOP_REGISTER_BANK;
addr = MSTAR_CHIPTOP_REGISTER_ICTYPE;
- ic_type = (0xff)&(read_reg(bank, addr));
+ ic_type = (0xff)&(read_reg(ts_data, bank, addr));
- if (ic_type != 1 /* msg2133 */
- && ic_type != 2 /* msg21xxA */
- && ic_type != 3) /* msg26xxM */ {
+ if (ic_type != ts_data->pdata->ic_type)
ic_type = 0;
- }
- reset_hw();
+ msg21xx_reset_hw(ts_data->pdata);
return ic_type;
}
-static int msg21xx_read_firmware_id(void)
+static int msg21xx_read_firmware_id(struct msg21xx_ts_data *ts_data)
{
- unsigned char dbbus_tx_data[3] = {0};
- unsigned char dbbus_rx_data[4] = {0};
- int ret = 0;
+ unsigned char command[3] = { 0x53, 0x00, 0x2A};
+ unsigned char response[4] = { 0 };
- 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);
+ write_i2c_seq(ts_data, ts_data->client->addr, command, sizeof(command));
+ read_i2c_seq(ts_data, ts_data->client->addr, response,
+ sizeof(response));
mutex_unlock(&msg21xx_mutex);
- pdata->fw_version_major = (dbbus_rx_data[1]<<8) + dbbus_rx_data[0];
- pdata->fw_version_minor = (dbbus_rx_data[3]<<8) + dbbus_rx_data[2];
-
- dev_dbg(&i2c_client->dev, "major num = %d, minor num = %d\n",
- pdata->fw_version_major, pdata->fw_version_minor);
-
- if (pdata->fw_version == NULL)
- pdata->fw_version = kzalloc(sizeof(char), GFP_KERNEL);
+ ts_data->pdata->fw_version_major = (response[1]<<8) + response[0];
+ ts_data->pdata->fw_version_minor = (response[3]<<8) + response[2];
- snprintf(pdata->fw_version, sizeof(char) * 7, "%03d%03d",
- pdata->fw_version_major,
- pdata->fw_version_minor);
+ dev_info(&ts_data->client->dev, "major num = %d, minor num = %d\n",
+ ts_data->pdata->fw_version_major,
+ ts_data->pdata->fw_version_minor);
- return ret;
+ return 0;
}
-static int firmware_erase_c33(enum EMEM_TYPE_t emem_type)
+static int firmware_erase_c33(struct msg21xx_ts_data *ts_data,
+ enum EMEM_TYPE_t emem_type)
{
/* stop mcu */
- write_reg(0x0F, 0xE6, 0x0001);
+ write_reg(ts_data, 0x0F, 0xE6, 0x0001);
/* disable watch dog */
- write_reg_8bit(0x3C, 0x60, 0x55);
- write_reg_8bit(0x3C, 0x61, 0xAA);
+ write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
+ write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
/* set PROGRAM password */
- write_reg_8bit(0x16, 0x1A, 0xBA);
- write_reg_8bit(0x16, 0x1B, 0xAB);
+ write_reg_8bit(ts_data, 0x16, 0x1A, 0xBA);
+ write_reg_8bit(ts_data, 0x16, 0x1B, 0xAB);
- write_reg_8bit(0x16, 0x18, 0x80);
+ write_reg_8bit(ts_data, 0x16, 0x18, 0x80);
if (emem_type == EMEM_ALL)
- write_reg_8bit(0x16, 0x08, 0x10);
+ write_reg_8bit(ts_data, 0x16, 0x08, 0x10);
- write_reg_8bit(0x16, 0x18, 0x40);
+ write_reg_8bit(ts_data, 0x16, 0x18, 0x40);
msleep(20);
/* clear pce */
@@ -487,7 +469,7 @@ static int firmware_erase_c33(enum EMEM_TYPE_t emem_type)
/* erase trigger */
if (emem_type == EMEM_MAIN)
- write_reg_8bit(0x16, 0x0E, 0x04); /* erase main */
+ write_reg_8bit(ts_data, 0x16, 0x0E, 0x04); /* erase main */
else
write_reg_8bit(0x16, 0x0E, 0x08); /* erase all block */
@@ -513,7 +495,9 @@ static int check_fw_update(void)
}
}
return ret;
+ write_reg_8bit(ts_data, 0x16, 0x0E, 0x08); /* erase all block */
+ return 0;
}
static ssize_t firmware_update_c33(struct device *dev,
@@ -526,71 +510,85 @@ static ssize_t firmware_update_c33(struct device *dev,
unsigned int crc_info, crc_info_tp;
unsigned short reg_data = 0;
int update_pass = 1;
+ bool fw_upgrade = false;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
crc_main = 0xffffffff;
crc_info = 0xffffffff;
- reset_hw();
+ msg21xx_reset_hw(ts_data->pdata);
- if (!check_fw_update() && !isForce) {
- DBG("****no need to update\n");
- reset_hw();
- FwDataCnt = 0;
+ msg21xx_read_firmware_id(ts_data);
+ _ReadBinConfig(ts_data);
+ if ((main_sw_id == info_sw_id) &&
+ (_CalMainCRC32(ts_data) == bin_conf_crc32) &&
+ (fw_file_major == ts_data->pdata->fw_version_major) &&
+ (fw_file_minor > ts_data->pdata->fw_version_minor)) {
+ fw_upgrade = true;
+ }
+
+ if (!fw_upgrade && !isForce) {
+ dev_dbg(dev, "no need to update\n");
+ msg21xx_reset_hw(ts_data->pdata);
return size;
}
- reset_hw();
+ msg21xx_reset_hw(ts_data->pdata);
msleep(300);
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
+ dbbusDWIICEnterSerialDebugMode(ts_data);
+ dbbusDWIICStopMCU(ts_data);
+ dbbusDWIICIICUseBus(ts_data);
+ dbbusDWIICIICReshape(ts_data);
msleep(300);
/* erase main */
- firmware_erase_c33(EMEM_MAIN);
+ firmware_erase_c33(ts_data, EMEM_MAIN);
msleep(1000);
- reset_hw();
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
+ msg21xx_reset_hw(ts_data->pdata);
+ dbbusDWIICEnterSerialDebugMode(ts_data);
+ dbbusDWIICStopMCU(ts_data);
+ dbbusDWIICIICUseBus(ts_data);
+ dbbusDWIICIICReshape(ts_data);
msleep(300);
-
+ /*
+ * Program
+ */
/* polling 0x3CE4 is 0x1C70 */
if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
do {
- reg_data = read_reg(0x3C, 0xE4);
+ reg_data = read_reg(ts_data, 0x3C, 0xE4);
} while (reg_data != 0x1C70);
}
switch (emem_type) {
case EMEM_ALL:
- write_reg(0x3C, 0xE4, 0xE38F); /* for all-blocks */
+ write_reg(ts_data, 0x3C, 0xE4, 0xE38F); /* for all-blocks */
break;
case EMEM_MAIN:
- write_reg(0x3C, 0xE4, 0x7731); /* for main block */
+ write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for main block */
break;
case EMEM_INFO:
- write_reg(0x3C, 0xE4, 0x7731); /* for info block */
+ write_reg(ts_data, 0x3C, 0xE4, 0x7731); /* for info block */
- write_reg_8bit(0x0F, 0xE6, 0x01);
+ write_reg_8bit(ts_data, 0x0F, 0xE6, 0x01);
- write_reg_8bit(0x3C, 0xE4, 0xC5);
- write_reg_8bit(0x3C, 0xE5, 0x78);
+ write_reg_8bit(ts_data, 0x3C, 0xE4, 0xC5);
+ write_reg_8bit(ts_data, 0x3C, 0xE5, 0x78);
- write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x9F);
- write_reg_8bit(MSTAR_CHIPTOP_REGISTER_BANK, 0x05, 0x82);
+ write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK,
+ 0x04, 0x9F);
+ write_reg_8bit(ts_data, MSTAR_CHIPTOP_REGISTER_BANK,
+ 0x05, 0x82);
- write_reg_8bit(0x0F, 0xE6, 0x00);
+ write_reg_8bit(ts_data, 0x0F, 0xE6, 0x00);
msleep(100);
break;
}
/* polling 0x3CE4 is 0x2F43 */
do {
- reg_data = read_reg(0x3C, 0xE4);
+ reg_data = read_reg(ts_data, 0x3C, 0xE4);
} while (reg_data != 0x2F43);
/* calculate CRC 32 */
@@ -612,28 +610,28 @@ static ssize_t firmware_update_c33(struct device *dev,
}
for (j = 0; j < 8; j++)
- write_i2c_seq(ts_data->client->addr,
+ write_i2c_seq(ts_data, ts_data->client->addr,
&fw_bin_data[i][j * 128], 128);
msleep(100);
/* polling 0x3CE4 is 0xD0BC */
do {
- reg_data = read_reg(0x3C, 0xE4);
+ reg_data = read_reg(ts_data, 0x3C, 0xE4);
} while (reg_data != 0xD0BC);
- write_reg(0x3C, 0xE4, 0x2F43);
+ write_reg(ts_data, 0x3C, 0xE4, 0x2F43);
}
if ((emem_type == EMEM_ALL) || (emem_type == EMEM_MAIN)) {
/* write file done and check crc */
- write_reg(0x3C, 0xE4, 0x1380);
+ write_reg(ts_data, 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);
+ reg_data = read_reg(ts_data, 0x3C, 0xE4);
} while (reg_data != 0x9432);
}
@@ -642,12 +640,14 @@ static ssize_t firmware_update_c33(struct device *dev,
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_main_tp = read_reg(ts_data, 0x3C, 0x80);
+ crc_main_tp = (crc_main_tp << 16) |
+ read_reg(ts_data, 0x3C, 0x82);
/* CRC Info from TP */
- crc_info_tp = read_reg(0x3C, 0xA0);
- crc_info_tp = (crc_info_tp << 16) | read_reg(0x3C, 0xA2);
+ crc_info_tp = read_reg(ts_data, 0x3C, 0xA0);
+ crc_info_tp = (crc_info_tp << 16) |
+ read_reg(ts_data, 0x3C, 0xA2);
}
update_pass = 1;
@@ -657,94 +657,93 @@ static ssize_t firmware_update_c33(struct device *dev,
}
if (!update_pass) {
- DBG("update_C33 failed\n");
- reset_hw();
- FwDataCnt = 0;
+ dev_err(dev, "update_C33 failed\n");
+ msg21xx_reset_hw(ts_data->pdata);
return 0;
}
- DBG("update_C33 OK\n");
- reset_hw();
- FwDataCnt = 0;
+ dev_dbg(dev, "update_C33 OK\n");
+ msg21xx_reset_hw(ts_data->pdata);
return size;
}
-static unsigned int _CalMainCRC32(void)
+static unsigned int _CalMainCRC32(struct msg21xx_ts_data *ts_data)
{
unsigned int ret = 0;
unsigned short reg_data = 0;
- reset_hw();
+ msg21xx_reset_hw(ts_data->pdata);
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
+ dbbusDWIICEnterSerialDebugMode(ts_data);
+ dbbusDWIICStopMCU(ts_data);
+ dbbusDWIICIICUseBus(ts_data);
+ dbbusDWIICIICReshape(ts_data);
msleep(100);
/* Stop MCU */
- write_reg(0x0F, 0xE6, 0x0001);
+ write_reg(ts_data, 0x0F, 0xE6, 0x0001);
/* Stop Watchdog */
- write_reg_8bit(0x3C, 0x60, 0x55);
- write_reg_8bit(0x3C, 0x61, 0xAA);
+ write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
+ write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
/* cmd */
- write_reg(0x3C, 0xE4, 0xDF4C);
- write_reg(0x1E, 0x04, 0x7d60);
+ write_reg(ts_data, 0x3C, 0xE4, 0xDF4C);
+ write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
/* TP SW reset */
- write_reg(0x1E, 0x04, 0x829F);
+ write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F);
/* MCU run */
- write_reg(0x0F, 0xE6, 0x0000);
+ write_reg(ts_data, 0x0F, 0xE6, 0x0000);
/* polling 0x3CE4 */
do {
- reg_data = read_reg(0x3C, 0xE4);
+ reg_data = read_reg(ts_data, 0x3C, 0xE4);
} while (reg_data != 0x9432);
/* Cal CRC Main from TP */
- ret = read_reg(0x3C, 0x80);
- ret = (ret << 16) | read_reg(0x3C, 0x82);
+ ret = read_reg(ts_data, 0x3C, 0x80);
+ ret = (ret << 16) | read_reg(ts_data, 0x3C, 0x82);
- DBG("[21xxA]:Current main crc32=0x%x\n", ret);
+ dev_dbg(&ts_data->client->dev,
+ "[21xxA]:Current main crc32=0x%x\n", ret);
return ret;
}
-static void _ReadBinConfig(void)
+static void _ReadBinConfig(struct msg21xx_ts_data *ts_data)
{
unsigned char dbbus_tx_data[5] = {0};
unsigned char dbbus_rx_data[4] = {0};
unsigned short reg_data = 0;
- reset_hw();
+ msg21xx_reset_hw(ts_data->pdata);
- dbbusDWIICEnterSerialDebugMode();
- dbbusDWIICStopMCU();
- dbbusDWIICIICUseBus();
- dbbusDWIICIICReshape();
+ dbbusDWIICEnterSerialDebugMode(ts_data);
+ dbbusDWIICStopMCU(ts_data);
+ dbbusDWIICIICUseBus(ts_data);
+ dbbusDWIICIICReshape(ts_data);
msleep(100);
/* Stop MCU */
- write_reg(0x0F, 0xE6, 0x0001);
+ write_reg(ts_data, 0x0F, 0xE6, 0x0001);
/* Stop Watchdog */
- write_reg_8bit(0x3C, 0x60, 0x55);
- write_reg_8bit(0x3C, 0x61, 0xAA);
+ write_reg_8bit(ts_data, 0x3C, 0x60, 0x55);
+ write_reg_8bit(ts_data, 0x3C, 0x61, 0xAA);
/* cmd */
- write_reg(0x3C, 0xE4, 0xA4AB);
- write_reg(MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
+ write_reg(ts_data, 0x3C, 0xE4, 0xA4AB);
+ write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x7d60);
+
/* TP SW reset */
- write_reg(0x1E, 0x04, 0x829F);
- /* TP SW reset*/
+ write_reg(ts_data, MSTAR_CHIPTOP_REGISTER_BANK, 0x04, 0x829F);
/* MCU run */
- write_reg(0x0F, 0xE6, 0x0000);
+ write_reg(ts_data, 0x0F, 0xE6, 0x0000);
/* polling 0x3CE4 */
do {
- reg_data = read_reg(0x3C, 0xE4);
+ reg_data = read_reg(ts_data, 0x3C, 0xE4);
} while (reg_data != 0x5B58);
dbbus_tx_data[0] = 0x72;
@@ -752,8 +751,8 @@ static void _ReadBinConfig(void)
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);
+ write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data, 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)) {
@@ -767,20 +766,20 @@ static void _ReadBinConfig(void)
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];
+ write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data, ts_data->client->addr, &dbbus_rx_data[0], 4);
+ bin_conf_crc32 = (dbbus_rx_data[0] << 24) |
+ (dbbus_rx_data[1] << 16) |
+ (dbbus_rx_data[2] << 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);
+ write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 5);
+ read_i2c_seq(ts_data, 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)) {
@@ -789,18 +788,18 @@ static void _ReadBinConfig(void)
(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);
+ dev_dbg(&ts_data->client->dev,
+ "[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 ssize_t firmware_update_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- DBG("*** firmware_update_show() pdata->fw_version = %s ***\n",
- pdata->fw_version);
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
- return snprintf(buf, sizeof(char) - 1, "%s\n", pdata->fw_version);
+ return snprintf(buf, 3, "%d\n", ts_data->pdata->updating_fw);
}
static ssize_t firmware_update_store(struct device *dev,
@@ -808,14 +807,15 @@ static ssize_t firmware_update_store(struct device *dev,
const char *buf,
size_t size)
{
- bFwUpdating = 1;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
+
+ ts_data->pdata->updating_fw = true;
disable_irq(ts_data->client->irq);
- DBG("*** update fw size = %d ***\n", FwDataCnt);
size = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
enable_irq(ts_data->client->irq);
- bFwUpdating = 0;
+ ts_data->pdata->updating_fw = false;
return size;
}
@@ -830,27 +830,24 @@ static int prepare_fw_data(struct device *dev)
int i;
int ret;
const struct firmware *fw = NULL;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
- ret = request_firmware(&fw, pdata->fw_name, dev);
+ ret = request_firmware(&fw, ts_data->pdata->fw_name, dev);
if (ret < 0) {
dev_err(dev, "Request firmware failed - %s (%d)\n",
- pdata->fw_name, ret);
+ ts_data->pdata->fw_name, ret);
return ret;
}
- DBG("*** prepare_fw_data() ret = %d, size = %d***\n", ret, fw->size);
count = fw->size / 1024;
- for (i = 0; i < count; i++) {
- memcpy(fw_bin_data[FwDataCnt], fw->data + (i * 1024), 1024);
- FwDataCnt++;
- }
- update_bin_major = (fw->data[0x7f4f] << 8) + fw->data[0x7f4e];
- update_bin_minor = (fw->data[0x7f51] << 8) + fw->data[0x7f50];
- DBG("*** prepare_fw_data bin major = %d ***\n", update_bin_major);
- DBG("*** prepare_fw_data bin minor = %d ***\n", update_bin_minor);
+ for (i = 0; i < count; i++)
+ memcpy(fw_bin_data[i], fw->data + (i * 1024), 1024);
- DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+ fw_file_major = MSG_FW_FILE_MAJOR_VERSION(fw);
+ fw_file_minor = MSG_FW_FILE_MINOR_VERSION(fw);
+ dev_dbg(dev, "New firmware: %d.%d",
+ fw_file_major, fw_file_minor);
return fw->size;
}
@@ -861,22 +858,22 @@ static ssize_t firmware_update_smart_store(struct device *dev,
size_t size)
{
int ret;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
ret = prepare_fw_data(dev);
if (ret < 0) {
dev_err(dev, "Request firmware failed -(%d)\n", ret);
return ret;
}
- bFwUpdating = 1;
+ ts_data->pdata->updating_fw = true;
disable_irq(ts_data->client->irq);
- DBG("*** update fw size = %d ***\n", FwDataCnt);
ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, false);
if (ret == 0)
- DBG("*** firmware_update_c33 ret = %d ***\n", ret);
+ dev_err(dev, "firmware_update_c33 ret = %d\n", ret);
enable_irq(ts_data->client->irq);
- bFwUpdating = 0;
+ ts_data->pdata->updating_fw = false;
return ret;
}
@@ -887,22 +884,22 @@ static ssize_t firmware_force_update_smart_store(struct device *dev,
size_t size)
{
int ret;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
ret = prepare_fw_data(dev);
if (ret < 0) {
dev_err(dev, "Request firmware failed -(%d)\n", ret);
return ret;
}
- bFwUpdating = 1;
+ ts_data->pdata->updating_fw = true;
disable_irq(ts_data->client->irq);
- DBG("*** update fw size = %d ***\n", FwDataCnt);
ret = firmware_update_c33(dev, attr, buf, size, EMEM_MAIN, true);
if (ret == 0)
- DBG("*** firmware_update_c33 et = %d ***\n", ret);
+ dev_err(dev, "firmware_update_c33 et = %d\n", ret);
enable_irq(ts_data->client->irq);
- bFwUpdating = 0;
+ ts_data->pdata->updating_fw = false;
return ret;
}
@@ -919,44 +916,40 @@ static ssize_t firmware_version_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- msg21xx_read_firmware_id();
- return snprintf(buf, 8, "%s\n", pdata->fw_version);
-}
-
-static ssize_t firmware_version_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t size)
-{
- msg21xx_read_firmware_id();
- DBG("*** firmware_version_store() pdata->fw_version = %s ***\n",
- pdata->fw_version);
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
- return size;
+ msg21xx_read_firmware_id(ts_data);
+ return snprintf(buf, sizeof(char) * 8, "%03d%03d\n",
+ ts_data->pdata->fw_version_major,
+ ts_data->pdata->fw_version_minor);
}
-static DEVICE_ATTR(version, (S_IRUGO | S_IWUSR),
+static DEVICE_ATTR(version, S_IRUGO,
firmware_version_show,
- firmware_version_store);
+ NULL);
static ssize_t msg21xx_fw_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1, "%s\n", pdata->fw_name);
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, MSTAR_FW_NAME_MAX_LEN - 1,
+ "%s\n", ts_data->pdata->fw_name);
}
static ssize_t msg21xx_fw_name_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
if (size > MSTAR_FW_NAME_MAX_LEN - 1)
return -EINVAL;
- strlcpy(pdata->fw_name, buf, size);
- if (pdata->fw_name[size - 1] == '\n')
- pdata->fw_name[size - 1] = 0;
+ strlcpy(ts_data->pdata->fw_name, buf, size);
+ if (ts_data->pdata->fw_name[size - 1] == '\n')
+ ts_data->pdata->fw_name[size - 1] = 0;
return size;
}
@@ -964,15 +957,6 @@ static ssize_t msg21xx_fw_name_store(struct device *dev,
static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR),
msg21xx_fw_name_show, msg21xx_fw_name_store);
-static ssize_t firmware_data_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- DBG("*** firmware_data_show() FwDataCnt = %d ***\n", FwDataCnt);
-
- return FwDataCnt;
-}
-
static ssize_t firmware_data_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
@@ -981,31 +965,26 @@ static ssize_t firmware_data_store(struct device *dev,
int count = size / 1024;
int i;
- for (i = 0; i < count; i++) {
- memcpy(fw_bin_data[FwDataCnt], buf + (i * 1024), 1024);
-
- FwDataCnt++;
- }
-
- DBG("***FwDataCnt = %d ***\n", FwDataCnt);
+ for (i = 0; i < count; i++)
+ memcpy(fw_bin_data[i], buf + (i * 1024), 1024);
if (buf != NULL)
- DBG("*** buf[0] = %c ***\n", buf[0]);
+ dev_dbg(dev, "buf[0] = %c\n", buf[0]);
return size;
}
-static DEVICE_ATTR(data, (S_IRUGO | S_IWUSR),
- firmware_data_show, firmware_data_store);
+static DEVICE_ATTR(data, S_IWUSR, NULL, firmware_data_store);
-#ifdef TP_PRINT
static ssize_t tp_print_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- tp_print_proc_read();
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
- return snprintf(buf, sizeof(char) - 1, "%d\n", ts_data->suspended);
+ tp_print_proc_read(ts_data);
+
+ return snprintf(buf, 3, "%d\n", ts_data->suspended);
}
static ssize_t tp_print_store(struct device *dev,
@@ -1013,21 +992,17 @@ static ssize_t tp_print_store(struct device *dev,
const char *buf,
size_t size)
{
- DBG("*** tp_print_store() ***\n");
-
return size;
}
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)
{
unsigned char tx_data[4] = {0};
- DBG("_msg_enable_proximity!");
tx_data[0] = 0x52;
tx_data[1] = 0x00;
tx_data[2] = 0x47;
@@ -1043,7 +1018,6 @@ static void _msg_disable_proximity(void)
{
unsigned char tx_data[4] = {0};
- DBG("_msg_disable_proximity!");
tx_data[0] = 0x52;
tx_data[1] = 0x00;
tx_data[2] = 0x47;
@@ -1070,15 +1044,15 @@ static int tsps_msg21xx_data(void)
}
#endif
-static int msg21xx_pinctrl_init(void)
+static int msg21xx_pinctrl_init(struct msg21xx_ts_data *ts_data)
{
int retval;
/* Get pinctrl if target uses pinctrl */
- ts_data->ts_pinctrl = devm_pinctrl_get(&(i2c_client->dev));
+ ts_data->ts_pinctrl = devm_pinctrl_get(&(ts_data->client->dev));
if (IS_ERR_OR_NULL(ts_data->ts_pinctrl)) {
retval = PTR_ERR(ts_data->ts_pinctrl);
- dev_dbg(&i2c_client->dev,
+ dev_dbg(&ts_data->client->dev,
"Target does not use pinctrl %d\n", retval);
goto err_pinctrl_get;
}
@@ -1087,7 +1061,7 @@ static int msg21xx_pinctrl_init(void)
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,
+ dev_dbg(&ts_data->client->dev,
"Can't lookup %s pinstate %d\n",
PINCTRL_STATE_ACTIVE, retval);
goto err_pinctrl_lookup;
@@ -1097,7 +1071,7 @@ static int msg21xx_pinctrl_init(void)
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,
+ dev_dbg(&ts_data->client->dev,
"Can't lookup %s pinstate %d\n",
PINCTRL_STATE_SUSPEND, retval);
goto err_pinctrl_lookup;
@@ -1107,7 +1081,7 @@ static int msg21xx_pinctrl_init(void)
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,
+ dev_dbg(&ts_data->client->dev,
"Can't lookup %s pinstate %d\n",
PINCTRL_STATE_RELEASE, retval);
}
@@ -1131,7 +1105,7 @@ static unsigned char calculate_checksum(unsigned char *msg, int length)
return (unsigned char)((-checksum) & 0xFF);
}
-static int parse_info(struct touchInfo_t *info)
+static int parse_info(struct msg21xx_ts_data *ts_data)
{
unsigned char data[DEMO_MODE_PACKET_LENGTH] = {0};
unsigned char checksum = 0;
@@ -1140,33 +1114,36 @@ static int parse_info(struct touchInfo_t *info)
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);
+ read_i2c_seq(ts_data, 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",
+ dev_dbg(&ts_data->client->dev, "check sum: [%x] == [%x]?\n",
data[DEMO_MODE_PACKET_LENGTH-1], checksum);
if (data[DEMO_MODE_PACKET_LENGTH-1] != checksum) {
- DBG("WRONG CHECKSUM\n");
+ dev_err(&ts_data->client->dev, "WRONG CHECKSUM\n");
return -EINVAL;
}
if (data[0] != 0x52) {
- DBG("WRONG HEADER\n");
+ dev_err(&ts_data->client->dev, "WRONG HEADER\n");
return -EINVAL;
}
- info->keycode = 0xFF;
+ ts_data->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;
+ ts_data->info.keycode = 0xFF;
} else if ((data[5] == 1) || (data[5] == 2) ||
(data[5] == 4) || (data[5] == 8)) {
- info->keycode = data[5] >> 1;
+ ts_data->info.keycode = data[5] >> 1;
- DBG("info->keycode index %d\n", info->keycode);
+ dev_dbg(&ts_data->client->dev,
+ "ts_data->info.keycode index %d\n",
+ ts_data->info.keycode);
}
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
else if (bEnableTpProximity && ((data[5] == 0x80) ||
@@ -1180,7 +1157,7 @@ static int parse_info(struct touchInfo_t *info)
}
#endif
else {
- DBG("WRONG KEY\n");
+ dev_err(&ts_data->client->dev, "WRONG KEY\n");
return -EINVAL;
}
} else {
@@ -1190,9 +1167,11 @@ static int parse_info(struct touchInfo_t *info)
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;
+ ts_data->info.point[0].x =
+ x * ts_data->pdata->x_max / TPD_WIDTH;
+ ts_data->info.point[0].y =
+ y * ts_data->pdata->y_max / TPD_HEIGHT;
+ ts_data->info.count = 1;
} else {
if (delta_x > 2048)
delta_x -= 4096;
@@ -1204,31 +1183,34 @@ static int parse_info(struct touchInfo_t *info)
(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;
+ ts_data->info.point[0].x =
+ x * ts_data->pdata->x_max / TPD_WIDTH;
+ ts_data->info.point[0].y =
+ y * ts_data->pdata->y_max / TPD_HEIGHT;
+ ts_data->info.point[1].x =
+ x2 * ts_data->pdata->x_max / TPD_WIDTH;
+ ts_data->info.point[1].y =
+ y2 * ts_data->pdata->y_max / TPD_HEIGHT;
+ ts_data->info.count = ts_data->pdata->num_max_touches;
}
}
return 0;
}
-static void touch_driver_touch_released(void)
+static void touch_driver_touch_released(struct msg21xx_ts_data *ts_data)
{
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);
+ for (i = 0; i < ts_data->pdata->num_max_touches; i++) {
+ input_mt_slot(ts_data->input_dev, i);
+ input_mt_report_slot_state(ts_data->input_dev,
+ MT_TOOL_FINGER, 0);
}
- input_report_key(input_dev, BTN_TOUCH, 0);
- input_report_key(input_dev, BTN_TOOL_FINGER, 0);
- input_sync(input_dev);
+ input_report_key(ts_data->input_dev, BTN_TOUCH, 0);
+ input_report_key(ts_data->input_dev, BTN_TOOL_FINGER, 0);
+ input_sync(ts_data->input_dev);
}
/* read data through I2C then report data to input
@@ -1236,62 +1218,62 @@ static void touch_driver_touch_released(void)
*/
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,
+ struct msg21xx_ts_data *ts_data = dev_id;
+
+ ts_data->info.count = 0;
+ if (parse_info(ts_data) == 0) {
+ if (ts_data->info.keycode != 0xFF) { /* key touch pressed */
+ if (ts_data->info.keycode <
+ ts_data->pdata->num_buttons) {
+ if (ts_data->info.keycode != last_keycode) {
+ dev_dbg(&ts_data->client->dev,
+ "key touch pressed");
+
+ input_report_key(ts_data->input_dev,
BTN_TOUCH, 1);
- input_report_key(input_dev,
- button_map[info.keycode], 1);
+ input_report_key(ts_data->input_dev,
+ ts_data->pdata->button_map[
+ ts_data->info.keycode], 1);
- last_keycode = info.keycode;
+ last_keycode = ts_data->info.keycode;
} else {
/* pass duplicate key-pressing */
- DBG("REPEATED KEY\n");
+ dev_dbg(&ts_data->client->dev,
+ "REPEATED KEY\n");
}
} else {
- DBG("WRONG KEY\n");
+ dev_dbg(&ts_data->client->dev, "WRONG KEY\n");
}
} else { /* key touch released */
if (last_keycode != 0xFF) {
- DBG("key touch released");
+ dev_dbg(&ts_data->client->dev, "key touch released");
- input_report_key(input_dev,
+ input_report_key(ts_data->input_dev,
BTN_TOUCH, 0);
- input_report_key(input_dev,
- button_map[last_keycode],
- 0);
+ input_report_key(ts_data->input_dev,
+ ts_data->pdata->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,
+ if (ts_data->info.count > 0) { /* point touch pressed */
+ for (i = 0; i < ts_data->info.count; i++) {
+ input_mt_slot(ts_data->input_dev, i);
+ input_mt_report_slot_state(ts_data->input_dev,
MT_TOOL_FINGER, 1);
- input_report_abs(input_dev,
+ input_report_abs(ts_data->input_dev,
ABS_MT_TOUCH_MAJOR, 1);
- input_report_abs(input_dev,
+ input_report_abs(ts_data->input_dev,
ABS_MT_POSITION_X,
- info.point[i].x);
- input_report_abs(input_dev,
+ ts_data->info.point[i].x);
+ input_report_abs(ts_data->input_dev,
ABS_MT_POSITION_Y,
- info.point[i].y);
+ ts_data->info.point[i].y);
}
}
@@ -1299,60 +1281,87 @@ static irqreturn_t msg21xx_ts_interrupt(int irq, void *dev_id)
for (i = info.count; i < MAX_TOUCH_NUM; i++) {
input_mt_slot(input_dev, i);
input_mt_report_slot_state(input_dev,
+ }
+
+ if (last_count > ts_data->info.count) {
+ for (i = ts_data->info.count;
+ i < ts_data->pdata->num_max_touches;
+ i++) {
+ input_mt_slot(ts_data->input_dev, i);
+ input_mt_report_slot_state(ts_data->input_dev,
MT_TOOL_FINGER, 0);
}
}
- last_count = info.count;
+ last_count = ts_data->info.count;
- input_report_key(input_dev, BTN_TOUCH, info.count > 0);
- input_report_key(input_dev, BTN_TOOL_FINGER, info.count > 0);
+ input_report_key(ts_data->input_dev, BTN_TOUCH,
+ ts_data->info.count > 0);
+ input_report_key(ts_data->input_dev, BTN_TOOL_FINGER,
+ ts_data->info.count > 0);
- input_sync(input_dev);
+ input_sync(ts_data->input_dev);
}
return IRQ_HANDLED;
}
-
-static int msg21xx_ts_power_init(void)
+static int msg21xx_ts_power_init(struct msg21xx_ts_data *ts_data, bool init)
{
int rc;
- ts_data->vdd = regulator_get(&i2c_client->dev, "vdd");
- if (IS_ERR(ts_data->vdd)) {
- rc = PTR_ERR(ts_data->vdd);
- dev_err(&i2c_client->dev,
- "Regulator get failed vdd rc=%d\n", rc);
- return rc;
- }
+ if (init) {
+ ts_data->vdd = regulator_get(&ts_data->client->dev,
+ "vdd");
+ if (IS_ERR(ts_data->vdd)) {
+ rc = PTR_ERR(ts_data->vdd);
+ dev_err(&ts_data->client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
- if (regulator_count_voltages(ts_data->vdd) > 0) {
- rc = regulator_set_voltage(ts_data->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;
+ if (regulator_count_voltages(ts_data->vdd) > 0) {
+ rc = regulator_set_voltage(ts_data->vdd,
+ MSTAR_VTG_MIN_UV,
+ MSTAR_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&ts_data->client->dev,
+ "Regulator set_vtg failed vdd rc=%d\n",
+ rc);
+ goto reg_vdd_put;
+ }
}
- }
- ts_data->vcc_i2c = regulator_get(&i2c_client->dev, "vcc_i2c");
- if (IS_ERR(ts_data->vcc_i2c)) {
- rc = PTR_ERR(ts_data->vcc_i2c);
- dev_err(&i2c_client->dev,
- "Regulator get failed vcc_i2c rc=%d\n", rc);
- goto reg_vdd_set_vtg;
- }
+ ts_data->vcc_i2c = regulator_get(&ts_data->client->dev,
+ "vcc_i2c");
+ if (IS_ERR(ts_data->vcc_i2c)) {
+ rc = PTR_ERR(ts_data->vcc_i2c);
+ dev_err(&ts_data->client->dev,
+ "Regulator get failed vcc_i2c rc=%d\n", rc);
+ goto reg_vdd_set_vtg;
+ }
- if (regulator_count_voltages(ts_data->vcc_i2c) > 0) {
- rc = regulator_set_voltage(ts_data->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;
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(ts_data->vcc_i2c,
+ MSTAR_I2C_VTG_MIN_UV,
+ MSTAR_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&ts_data->client->dev,
+ "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+ goto reg_vcc_i2c_put;
+ }
}
+ } else {
+ if (regulator_count_voltages(ts_data->vdd) > 0)
+ regulator_set_voltage(ts_data->vdd, 0,
+ MSTAR_VTG_MAX_UV);
+
+ regulator_put(ts_data->vdd);
+
+ if (regulator_count_voltages(ts_data->vcc_i2c) > 0)
+ regulator_set_voltage(ts_data->vcc_i2c, 0,
+ MSTAR_I2C_VTG_MAX_UV);
+
+ regulator_put(ts_data->vcc_i2c);
}
return 0;
@@ -1367,59 +1376,42 @@ reg_vdd_put:
return rc;
}
-
-static int msg21xx_ts_power_deinit(void)
-{
- if (regulator_count_voltages(ts_data->vdd) > 0)
- regulator_set_voltage(ts_data->vdd, 0, MSTAR_VTG_MAX_UV);
-
- regulator_put(ts_data->vdd);
-
- if (regulator_count_voltages(ts_data->vcc_i2c) > 0)
- regulator_set_voltage(ts_data->vcc_i2c, 0,
- MSTAR_I2C_VTG_MAX_UV);
-
- regulator_put(ts_data->vcc_i2c);
- return 0;
-}
-
-static int msg21xx_ts_power_on(void)
+static int msg21xx_ts_power_on(struct msg21xx_ts_data *ts_data, bool on)
{
int rc;
+ if (!on)
+ goto power_off;
+
rc = regulator_enable(ts_data->vdd);
if (rc) {
- dev_err(&i2c_client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd enable failed rc=%d\n", rc);
return rc;
}
rc = regulator_enable(ts_data->vcc_i2c);
if (rc) {
- dev_err(&i2c_client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vcc_i2c enable failed rc=%d\n", rc);
regulator_disable(ts_data->vdd);
}
return rc;
-}
-
-static int msg21xx_ts_power_off(void)
-{
- int rc;
DBG("*** %s ***\n", __func__);
rc = regulator_disable(vdd);
+power_off:
rc = regulator_disable(ts_data->vdd);
if (rc) {
- dev_err(&i2c_client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vdd disable failed rc=%d\n", rc);
return rc;
}
rc = regulator_disable(ts_data->vcc_i2c);
if (rc) {
- dev_err(&i2c_client->dev,
+ dev_err(&ts_data->client->dev,
"Regulator vcc_i2c disable failed rc=%d\n", rc);
rc = regulator_enable(ts_data->vdd);
}
@@ -1427,57 +1419,42 @@ static int msg21xx_ts_power_off(void)
return rc;
}
-static int msg21xx_ts_gpio_configure(bool on)
+static int msg21xx_ts_gpio_configure(struct msg21xx_ts_data *ts_data, 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");
+ if (!on)
+ goto pwr_deinit;
+
+ if (gpio_is_valid(ts_data->pdata->irq_gpio)) {
+ ret = gpio_request(ts_data->pdata->irq_gpio,
+ "msg21xx_irq_gpio");
+ if (ret) {
+ dev_err(&ts_data->client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ ts_data->pdata->irq_gpio, ret);
goto err_irq_gpio_req;
}
+ ret = gpio_direction_input(ts_data->pdata->irq_gpio);
+ if (ret) {
+ dev_err(&ts_data->client->dev,
+ "Failed to set direction for gpio[%d], %d\n",
+ ts_data->pdata->irq_gpio, ret);
+ goto err_irq_gpio_dir;
+ }
+ gpio_set_value_cansleep(ts_data->pdata->irq_gpio, 1);
+ } else {
+ dev_err(&ts_data->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");
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
+ ret = gpio_request(ts_data->pdata->reset_gpio,
+ "msg21xx_reset_gpio");
+ if (ret) {
+ dev_err(&ts_data->client->dev,
+ "Failed to request GPIO[%d], %d\n",
+ ts_data->pdata->reset_gpio, ret);
goto err_reset_gpio_req;
}
@@ -1495,55 +1472,93 @@ static int msg21xx_ts_gpio_configure(bool on)
}
}
return 0;
+ /* power on TP */
+ ret = gpio_direction_output(
+ ts_data->pdata->reset_gpio, 1);
+ if (ret) {
+ dev_err(&ts_data->client->dev,
+ "Failed to set direction for GPIO[%d], %d\n",
+ ts_data->pdata->reset_gpio, ret);
+ goto err_reset_gpio_dir;
+ }
+ msleep(100);
+ gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0);
+ msleep(20);
+ gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 1);
+ msleep(200);
+ } else {
+ dev_err(&ts_data->client->dev, "reset gpio not provided\n");
+ goto err_reset_gpio_req;
+ }
+
+ return 0;
+
err_reset_gpio_dir:
- if (gpio_is_valid(pdata->reset_gpio))
- gpio_free(pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
err_reset_gpio_req:
err_irq_gpio_dir:
- if (gpio_is_valid(pdata->irq_gpio))
- gpio_free(pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
err_irq_gpio_req:
return ret;
+
+pwr_deinit:
+ if (gpio_is_valid(ts_data->pdata->irq_gpio))
+ gpio_free(ts_data->pdata->irq_gpio);
+ if (gpio_is_valid(ts_data->pdata->reset_gpio)) {
+ gpio_set_value_cansleep(ts_data->pdata->reset_gpio, 0);
+ ret = gpio_direction_input(ts_data->pdata->reset_gpio);
+ if (ret)
+ dev_err(&ts_data->client->dev,
+ "Unable to set direction for gpio [%d]\n",
+ ts_data->pdata->reset_gpio);
+ gpio_free(ts_data->pdata->reset_gpio);
+ }
+ return 0;
}
#ifdef CONFIG_PM
static int msg21xx_ts_resume(struct device *dev)
{
int retval;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
- 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;
- }
- }
+ if (!ts_data->suspended) {
+ dev_info(dev, "msg21xx_ts already in resume\n");
+ return 0;
+ }
- 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;
- }
+ mutex_lock(&ts_data->ts_mutex);
- enable_irq(ts_data->client->irq);
+ retval = msg21xx_ts_power_on(ts_data, true);
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power on failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
- retval = msg21xx_ts_power_on();
- if (retval) {
- dev_err(dev, "msg21xx_ts power on failed");
+ 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;
}
+ }
- ts_data->suspended = 0;
- } else {
- dev_info(dev, "msg21xx_ts already in resume\n");
+ retval = msg21xx_ts_gpio_configure(ts_data, 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);
+ ts_data->suspended = false;
+
mutex_unlock(&ts_data->ts_mutex);
return 0;
@@ -1552,56 +1567,61 @@ static int msg21xx_ts_resume(struct device *dev)
static int msg21xx_ts_suspend(struct device *dev)
{
int retval;
+ struct msg21xx_ts_data *ts_data = dev_get_drvdata(dev);
- if (bFwUpdating) {
- DBG("suspend bFwUpdating=%d\n", bFwUpdating);
+ if (ts_data->pdata->updating_fw) {
+ dev_info(dev, "Firmware loading in progress\n");
+ return 0;
+ }
+
+ if (ts_data->suspended) {
+ dev_info(dev, "msg21xx_ts already in suspend\n");
return 0;
}
#ifdef CONFIG_TOUCHSCREEN_PROXIMITY_SENSOR
if (bEnableTpProximity) {
- DBG("suspend bEnableTpProximity=%d\n", bEnableTpProximity);
+ dev_dbg(dev, "suspend bEnableTpProximity=%d\n",
+ bEnableTpProximity);
return 0;
}
#endif
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;
- }
+ disable_irq(ts_data->client->irq);
- 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;
- }
- }
+ touch_driver_touch_released(ts_data);
- retval = msg21xx_ts_gpio_configure(false);
- if (retval) {
- dev_err(dev, "Failed to put gpios in idle state %d",
- retval);
+ if (ts_data->ts_pinctrl) {
+ retval = pinctrl_select_state(ts_data->ts_pinctrl,
+ ts_data->pinctrl_state_suspend);
+ if (retval < 0) {
+ dev_err(dev, "Cannot get idle pinctrl state %d\n",
+ retval);
mutex_unlock(&ts_data->ts_mutex);
return retval;
}
+ }
- ts_data->suspended = 1;
- } else {
- dev_err(dev, "msg21xx_ts already in suspend\n");
+ retval = msg21xx_ts_gpio_configure(ts_data, false);
+ if (retval) {
+ dev_err(dev, "Failed to put gpios in idle state %d",
+ retval);
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
+ }
+
+ retval = msg21xx_ts_power_on(ts_data, false);
+ if (retval) {
+ dev_err(dev, "msg21xx_ts power off failed");
+ mutex_unlock(&ts_data->ts_mutex);
+ return retval;
}
- mutex_unlock(&ts_data->ts_mutex);
+ ts_data->suspended = true;
+
+ mutex_unlock(&ts_data->ts_mutex);
return 0;
}
@@ -1616,19 +1636,52 @@ static int msg21xx_ts_suspend(struct device *dev)
}
#endif
+static int msg21xx_debug_suspend_set(void *_data, u64 val)
+{
+ struct msg21xx_ts_data *data = _data;
+
+ mutex_lock(&data->input_dev->mutex);
+
+ if (val)
+ msg21xx_ts_suspend(&data->client->dev);
+ else
+ msg21xx_ts_resume(&data->client->dev);
+
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+static int msg21xx_debug_suspend_get(void *_data, u64 *val)
+{
+ struct msg21xx_ts_data *data = _data;
+
+ mutex_lock(&data->input_dev->mutex);
+ *val = data->suspended;
+ mutex_unlock(&data->input_dev->mutex);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, msg21xx_debug_suspend_get,
+ msg21xx_debug_suspend_set, "%lld\n");
+
+
#if defined(CONFIG_FB)
static int fb_notifier_callback(struct notifier_block *self,
unsigned long event, void *data)
{
struct fb_event *evdata = data;
int *blank;
+ struct msg21xx_ts_data *ts_data =
+ container_of(self, struct msg21xx_ts_data, fb_notif);
if (evdata && evdata->data && event == FB_EVENT_BLANK) {
blank = evdata->data;
if (*blank == FB_BLANK_UNBLANK)
- msg21xx_ts_resume(&i2c_client->dev);
+ msg21xx_ts_resume(&ts_data->client->dev);
else if (*blank == FB_BLANK_POWERDOWN)
- msg21xx_ts_suspend(&i2c_client->dev);
+ msg21xx_ts_suspend(&ts_data->client->dev);
}
return 0;
@@ -1695,6 +1748,20 @@ static int msg21xx_parse_dt(struct device *dev,
if (rc)
return rc;
+ rc = of_property_read_u32(np, "mstar,hard-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->hard_reset_delay_ms = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "mstar,post-hard-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->post_hard_reset_delay_ms = temp_val;
+ else
+ return rc;
+
/* reset, irq gpio info */
pdata->reset_gpio = of_get_named_gpio_flags(np, "mstar,reset-gpio",
0, &pdata->reset_gpio_flags);
@@ -1706,16 +1773,27 @@ static int msg21xx_parse_dt(struct device *dev,
if (pdata->irq_gpio < 0)
return pdata->irq_gpio;
+ rc = of_property_read_u32(np, "mstar,ic-type", &temp_val);
+ if (rc && (rc != -EINVAL))
+ return rc;
+
+ pdata->ic_type = temp_val;
+
+ rc = of_property_read_u32(np, "mstar,num-max-touches", &temp_val);
+ if (!rc)
+ pdata->num_max_touches = temp_val;
+ else
+ return rc;
prop = of_find_property(np, "mstar,button-map", NULL);
if (prop) {
- num_buttons = prop->length / sizeof(temp_val);
- if (num_buttons > MAX_BUTTONS)
+ pdata->num_buttons = prop->length / sizeof(temp_val);
+ if (pdata->num_buttons > MAX_BUTTONS)
return -EINVAL;
rc = of_property_read_u32_array(np,
- "mstar,button-map", button_map,
- num_buttons);
+ "mstar,button-map", pdata->button_map,
+ pdata->num_buttons);
if (rc) {
dev_err(dev, "Unable to read key codes\n");
return rc;
@@ -1729,12 +1807,11 @@ static int msg21xx_parse_dt(struct device *dev,
static int msg21xx_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id) {
- int ret = 0;
-
- if (input_dev != NULL) {
- DBG("input device has found\n");
- return -EINVAL;
- }
+ int ret = 0, i;
+ struct dentry *temp, *dir;
+ struct input_dev *input_dev;
+ struct msg21xx_ts_data *ts_data;
+ struct msg21xx_ts_platform_data *pdata;
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev,
@@ -1750,43 +1827,80 @@ static int msg21xx_ts_probe(struct i2c_client *client,
} else
pdata = client->dev.platform_data;
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C not supported\n");
+ return -ENODEV;
+ }
+
ts_data = devm_kzalloc(&client->dev,
sizeof(struct msg21xx_ts_data), GFP_KERNEL);
if (!ts_data)
return -ENOMEM;
- DBG("*** %s ***\n", __func__);
+ ts_data->client = client;
+ ts_data->info.point = devm_kzalloc(&client->dev,
+ sizeof(struct touchPoint_t) * pdata->num_max_touches,
+ GFP_KERNEL);
+ if (!ts_data->info.point) {
+ dev_err(&client->dev, "Not enough memory\n");
+ return -ENOMEM;
+ }
- i2c_client = client;
+ /* allocate an input device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ ret = -ENOMEM;
+ dev_err(&client->dev, "input device allocation failed\n");
+ goto err_input_allocate_dev;
+ }
- ret = msg21xx_ts_power_init();
- if (ret)
+ input_dev->name = client->name;
+ input_dev->phys = "I2C";
+ input_dev->dev.parent = &client->dev;
+ input_dev->id.bustype = BUS_I2C;
+
+ 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);
+
+ ret = msg21xx_ts_power_init(ts_data, true);
+ if (ret) {
dev_err(&client->dev, "Mstar power init failed\n");
+ return ret;
+ }
- ret = msg21xx_ts_power_on();
+ ret = msg21xx_ts_power_on(ts_data, true);
if (ret) {
dev_err(&client->dev, "Mstar power on failed\n");
goto exit_deinit_power;
}
- ret = msg21xx_pinctrl_init();
+ ret = msg21xx_pinctrl_init(ts_data);
if (!ret && ts_data->ts_pinctrl) {
+ /*
+ * Pinctrl handle is optional. If pinctrl handle is found
+ * let pins to be configured in active state. If not
+ * found continue further without error.
+ */
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;
+ dev_err(&client->dev,
+ "Failed to select %s pinatate %d\n",
+ PINCTRL_STATE_ACTIVE, ret);
}
- ret = msg21xx_ts_gpio_configure(true);
+ ret = msg21xx_ts_gpio_configure(ts_data, 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");
+ if (msg21xx_get_ic_type(ts_data) == 0) {
+ dev_err(&client->dev, "The current IC is not Mstar\n");
ret = -1;
goto err_wrong_ic_type;
}
@@ -1794,19 +1908,6 @@ static int msg21xx_ts_probe(struct i2c_client *client,
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);
@@ -1815,9 +1916,8 @@ static int msg21xx_ts_probe(struct i2c_client *client,
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;
+ for (i = 0; i < pdata->num_buttons; i++)
+ input_set_capability(input_dev, EV_KEY, pdata->button_map[i]);
input_set_drvdata(input_dev, ts_data);
i2c_set_clientdata(client, ts_data);
@@ -1833,64 +1933,82 @@ static int msg21xx_ts_probe(struct i2c_client *client,
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, 2, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
0, pdata->y_max, 0, 0);
- ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM, 0);
+ ret = input_mt_init_slots(input_dev, pdata->num_max_touches, 0);
if (ret) {
- pr_err("Error %d initialising slots\n", ret);
+ dev_err(&client->dev,
+ "Error %d initialising slots\n", ret);
goto err_free_mem;
}
/* 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");
+ dev_err(&client->dev,
+ "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-msg21xx");
- 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);
+ if (device_create_file(&client->dev, &dev_attr_version) < 0) {
+ dev_err(&client->dev,
+ "Failed to create device file(%s)!\n",
+ dev_attr_version.attr.name);
+ goto err_create_fw_ver_file;
+ }
/* 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);
+ if (device_create_file(&client->dev, &dev_attr_update) < 0) {
+ dev_err(&client->dev,
+ "Failed to create device file(%s)!\n",
+ dev_attr_update.attr.name);
+ goto err_create_fw_update_file;
+ }
/* 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);
- /* fw name*/
- if (device_create_file(firmware_cmd_dev, &dev_attr_fw_name) < 0)
- pr_err("Failed to create device file(%s)!\n",
- dev_attr_fw_name.attr.name);
- /* smart fw update*/
- if (device_create_file(firmware_cmd_dev, &dev_attr_update_fw) < 0)
- pr_err("Failed to create device file(%s)!\n",
- dev_attr_update_fw.attr.name);
- /* smart fw force update*/
- if (device_create_file(firmware_cmd_dev, &dev_attr_force_update_fw) < 0)
- pr_err("Failed to create device file(%s)!\n",
- dev_attr_force_update_fw.attr.name);
+ if (device_create_file(&client->dev, &dev_attr_data) < 0) {
+ dev_err(&client->dev,
+ "Failed to create device file(%s)!\n",
+ dev_attr_data.attr.name);
+ goto err_create_fw_data_file;
+ }
+ /* fw name */
+ if (device_create_file(&client->dev, &dev_attr_fw_name) < 0) {
+ dev_err(&client->dev,
+ "Failed to create device file(%s)!\n",
+ dev_attr_fw_name.attr.name);
+ goto err_create_fw_name_file;
+ }
+ /* smart fw update */
+ if (device_create_file(&client->dev, &dev_attr_update_fw) < 0) {
+ dev_err(&client->dev,
+ "Failed to create device file(%s)!\n",
+ dev_attr_update_fw.attr.name);
+ goto err_create_update_fw_file;
+ }
+ /* smart fw force update */
+ if (device_create_file(&client->dev,
+ &dev_attr_force_update_fw) < 0) {
+ dev_err(&client->dev,
+ "Failed to create device file(%s)!\n",
+ dev_attr_force_update_fw.attr.name);
+ goto err_create_force_update_fw_file;
+ }
+ dir = debugfs_create_dir(MSTAR_DEBUG_DIR_NAME, NULL);
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, dir,
+ ts_data, &debug_suspend_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ dev_err(&client->dev,
+ "debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+ goto free_debug_dir;
+ }
#ifdef TP_PRINT
- tp_print_create_entry();
+ tp_print_create_entry(ts_data);
#endif
- dev_set_drvdata(firmware_cmd_dev, NULL);
-
ret = request_threaded_irq(client->irq, NULL,
msg21xx_ts_interrupt,
pdata->irq_gpio_flags | IRQF_ONESHOT,
@@ -1898,7 +2016,7 @@ static int msg21xx_ts_probe(struct i2c_client *client,
if (ret)
goto err_req_irq;
- disable_irq(ts_data->client->irq);
+ disable_irq(client->irq);
#if defined(CONFIG_FB)
ts_data->fb_notif.notifier_call = fb_notifier_callback;
@@ -1910,91 +2028,38 @@ static int msg21xx_ts_probe(struct i2c_client *client,
&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;
- }
- }
- } 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(ts_data->client->irq);
+ dev_dbg(&client->dev, "mstar touch screen registered\n");
+ enable_irq(client->irq);
return 0;
err_req_irq:
- free_irq(ts_data->client->irq, ts_data);
+ free_irq(client->irq, ts_data);
+ device_remove_file(&client->dev, &dev_attr_data);
+free_debug_dir:
+ debugfs_remove_recursive(dir);
+err_create_fw_data_file:
+ device_remove_file(&client->dev, &dev_attr_update);
+err_create_fw_update_file:
+ device_remove_file(&client->dev, &dev_attr_version);
+err_create_fw_name_file:
+ device_remove_file(&client->dev, &dev_attr_fw_name);
+err_create_update_fw_file:
+ device_remove_file(&client->dev, &dev_attr_update_fw);
+err_create_force_update_fw_file:
+ device_remove_file(&client->dev, &dev_attr_force_update_fw);
+err_create_fw_ver_file:
+ input_unregister_device(input_dev);
err_input_reg_dev:
+ input_free_device(input_dev);
+ input_dev = NULL;
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);
+ msg21xx_ts_gpio_configure(ts_data, 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);
@@ -2003,13 +2068,13 @@ exit_pinctrl_select:
ret = pinctrl_select_state(ts_data->ts_pinctrl,
ts_data->pinctrl_state_release);
if (ret < 0)
- pr_err("Cannot get release pinctrl state\n");
+ dev_err(&ts_data->client->dev,
+ "Cannot get release pinctrl state\n");
}
}
-exit_pinctrl_init:
- msg21xx_ts_power_off();
+ msg21xx_ts_power_on(ts_data, false);
exit_deinit_power:
- msg21xx_ts_power_deinit();
+ msg21xx_ts_power_init(ts_data, false);
err_free_mem:
input_free_device(input_dev);
@@ -2022,12 +2087,11 @@ err_free_mem:
static int touch_driver_remove(struct i2c_client *client)
{
int retval = 0;
-
- DBG("touch_driver_remove()\n");
+ struct msg21xx_ts_data *ts_data = i2c_get_clientdata(client);
free_irq(ts_data->client->irq, ts_data);
- gpio_free(pdata->irq_gpio);
- gpio_free(pdata->reset_gpio);
+ gpio_free(ts_data->pdata->irq_gpio);
+ gpio_free(ts_data->pdata->reset_gpio);
if (ts_data->ts_pinctrl) {
if (IS_ERR_OR_NULL(ts_data->pinctrl_state_release)) {
@@ -2037,11 +2101,12 @@ static int touch_driver_remove(struct i2c_client *client)
retval = pinctrl_select_state(ts_data->ts_pinctrl,
ts_data->pinctrl_state_release);
if (retval < 0)
- pr_err("Cannot get release pinctrl state\n");
+ dev_err(&ts_data->client->dev,
+ "Cannot get release pinctrl state\n");
}
}
- input_unregister_device(input_dev);
+ input_unregister_device(ts_data->input_dev);
mutex_destroy(&msg21xx_mutex);
mutex_destroy(&ts_data->ts_mutex);
@@ -2082,7 +2147,7 @@ module_i2c_driver(touch_device_driver);
static unsigned short InfoAddr = 0x0F, PoolAddr = 0x10, TransLen = 256;
static unsigned char row, units, cnt;
-static int tp_print_proc_read(void)
+static int tp_print_proc_read(struct msg21xx_ts_data *ts_data)
{
unsigned short i, j;
unsigned short left, offset = 0;
@@ -2106,9 +2171,9 @@ static int tp_print_proc_read(void)
& 0xFF;
dbbus_tx_data[2] = (PoolAddr + offset) & 0xFF;
mutex_lock(&msg21xx_mutex);
- write_i2c_seq(ts_data->client->addr,
+ write_i2c_seq(ts_data, ts_data->client->addr,
&dbbus_tx_data[0], 3);
- read_i2c_seq(ts_data->client->addr,
+ read_i2c_seq(ts_data, ts_data->client->addr,
&buf[offset],
left > TransLen ? TransLen : left);
mutex_unlock(&msg21xx_mutex);
@@ -2151,7 +2216,7 @@ static int tp_print_proc_read(void)
return 0;
}
-static void tp_print_create_entry(void)
+static void tp_print_create_entry(struct msg21xx_ts_data *ts_data)
{
unsigned char dbbus_tx_data[3] = {0};
unsigned char dbbus_rx_data[8] = {0};
@@ -2160,8 +2225,8 @@ static void tp_print_create_entry(void)
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);
+ write_i2c_seq(ts_data, ts_data->client->addr, &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data, 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];
@@ -2172,8 +2237,10 @@ static void tp_print_create_entry(void)
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);
+ write_i2c_seq(ts_data, ts_data->client->addr,
+ &dbbus_tx_data[0], 3);
+ read_i2c_seq(ts_data, ts_data->client->addr,
+ &dbbus_rx_data[0], 8);
mutex_unlock(&msg21xx_mutex);
units = dbbus_rx_data[0];
@@ -2181,10 +2248,10 @@ static void tp_print_create_entry(void)
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",
+ if (device_create_file(&ts_data->client->dev,
+ &dev_attr_tpp) < 0)
+ dev_err(&ts_data->client->dev, "Failed to create device file(%s)!\n",
dev_attr_tpp.attr.name);
- }
}
}
#endif