aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/mms152_ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/mms152_ts.c')
-rw-r--r--drivers/input/touchscreen/mms152_ts.c634
1 files changed, 457 insertions, 177 deletions
diff --git a/drivers/input/touchscreen/mms152_ts.c b/drivers/input/touchscreen/mms152_ts.c
index 37b772c..fa1d295 100644
--- a/drivers/input/touchscreen/mms152_ts.c
+++ b/drivers/input/touchscreen/mms152_ts.c
@@ -88,6 +88,7 @@ enum {
/* each address addresses 4-byte words */
#define ISP_MAX_FW_SIZE (0x1F00 * 4)
#define ISP_IC_INFO_ADDR 0x1F00
+#define ISP_CAL_DATA_SIZE 256
#ifdef SEC_TSP_FW_UPDATE
@@ -168,8 +169,8 @@ int touch_is_pressed;
#define ISC_DL_MODE 1
/* 5.55" OCTA LCD */
-#define FW_VERSION_L 0x18
-#define FW_VERSION_M 0x17
+#define FW_VERSION_L 0x29
+#define FW_VERSION_M 0x50
#define MAX_FW_PATH 255
#define TSP_FW_FILENAME "melfas_fw.bin"
@@ -180,7 +181,7 @@ int touch_is_pressed;
*/
#define DEFAULT_SLAVE_ADDR 0x48
-#define SECTION_NUM 4
+#define SECTION_NUM 3
#define SECTION_NAME_LEN 5
#define PAGE_HEADER 3
@@ -216,7 +217,7 @@ int touch_is_pressed;
#define ISC_MAX(x, y) (((x) > (y)) ? (x) : (y))
static const char section_name[SECTION_NUM][SECTION_NAME_LEN] = {
- "BOOT", "CORE", "PRIV", "PUBL"
+ "BOOT", "CORE", "CONF"
};
static const unsigned char crc0_buf[31] = {
@@ -271,8 +272,7 @@ enum {
SEC_NONE = -1,
SEC_BOOTLOADER = 0,
SEC_CORE,
- SEC_PRIVATE_CONFIG,
- SEC_PUBLIC_CONFIG,
+ SEC_CONFIG,
SEC_LIMIT
};
@@ -307,6 +307,12 @@ struct tsp_callbacks {
void (*inform_charger)(struct tsp_callbacks *tsp_cb, bool mode);
};
+#ifdef CONFIG_LCD_FREQ_SWITCH
+struct tsp_lcd_callbacks {
+ void (*inform_lcd)(struct tsp_lcd_callbacks *tsp_cb, bool en);
+};
+#endif
+
struct mms_ts_info {
struct i2c_client *client;
struct input_dev *input_dev;
@@ -339,8 +345,14 @@ struct mms_ts_info {
enum fw_flash_mode fw_flash_mode;
void (*register_cb)(void *);
struct tsp_callbacks callbacks;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ void (*register_lcd_cb)(void *);
+ struct tsp_lcd_callbacks lcd_callback;
+ bool tsp_lcdfreq_flag;
+#endif
bool ta_status;
bool noise_mode;
+ bool sleep_wakeup_ta_check;
#if defined(SEC_TSP_DEBUG)
unsigned char finger_state[MAX_FINGERS];
@@ -718,6 +730,7 @@ static void mms_set_noise_mode(struct mms_ts_info *info)
} else {
dev_notice(&client->dev, "noise_mode & TA disconnect!!!\n");
i2c_smbus_write_byte_data(info->client, 0x30, 0x2);
+ info->noise_mode = 0;
}
}
@@ -736,18 +749,21 @@ static void reset_mms_ts(struct mms_ts_info *info)
release_all_fingers(info);
mms_pwr_on_reset(info);
- enable_irq(info->irq);
- info->enabled = true;
- if (info->ta_status) {
- dev_notice(&client->dev, "TA connect!!!\n");
- i2c_smbus_write_byte_data(info->client, 0x33, 0x1);
- } else {
- dev_notice(&client->dev, "TA disconnect!!!\n");
- i2c_smbus_write_byte_data(info->client, 0x33, 0x2);
+ info->enabled = true;
+ if (info->fw_ic_ver < 0x18) {
+ if (info->ta_status) {
+ dev_notice(&client->dev, "TA connect!!!\n");
+ i2c_smbus_write_byte_data(info->client, 0x33, 0x1);
+ } else {
+ dev_notice(&client->dev, "TA disconnect!!!\n");
+ i2c_smbus_write_byte_data(info->client, 0x33, 0x2);
+ }
}
mms_set_noise_mode(info);
+ enable_irq(info->irq);
+
dev_notice(&client->dev, "%s--\n", __func__);
}
@@ -777,6 +793,41 @@ static void melfas_ta_cb(struct tsp_callbacks *cb, bool ta_status)
*/
}
+#ifdef CONFIG_LCD_FREQ_SWITCH
+static void melfas_lcd_cb(struct tsp_lcd_callbacks *cb, bool en)
+{
+ struct mms_ts_info *info =
+ container_of(cb, struct mms_ts_info, lcd_callback);
+
+ if (info->enabled == false) {
+ dev_err(&info->client->dev,
+ "[TSP] do not excute %s.(touch off)\n", __func__);
+ return;
+ }
+
+ if (info->fw_ic_ver < 0x21) {
+ dev_err(&info->client->dev,
+ "[TSP] Do not support firmware LCD framerate changing(ver = 0x%x)\n",
+ info->fw_ic_ver);
+ return;
+ }
+
+ if (en) {
+ if (info->tsp_lcdfreq_flag == 0) {
+ info->tsp_lcdfreq_flag = 1;
+ dev_info(&info->client->dev, "[TSP] LCD framerate to 40 Hz\n");
+ i2c_smbus_write_byte_data(info->client, 0x34, 0x1);
+ }
+ } else {
+ if (info->tsp_lcdfreq_flag == 1) {
+ info->tsp_lcdfreq_flag = 0;
+ dev_info(&info->client->dev, "[TSP] LCD framreate to 60 Hz\n");
+ i2c_smbus_write_byte_data(info->client, 0x34, 0x1);
+ }
+ }
+}
+#endif
+
static irqreturn_t mms_ts_interrupt(int irq, void *dev_id)
{
struct mms_ts_info *info = dev_id;
@@ -866,7 +917,7 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id)
if (buf[0] == 0x0E) { /* NOISE MODE */
dev_dbg(&client->dev, "[TSP] noise mode enter!!\n");
- info->noise_mode = 1 ;
+ info->noise_mode = 1;
mms_set_noise_mode(info);
goto out;
}
@@ -920,12 +971,42 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id)
input_mt_slot(info->input_dev, id);
input_mt_report_slot_state(info->input_dev,
MT_TOOL_FINGER, false);
+#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP
if (info->panel == 'M') {
if (info->finger_state[id] != 0) {
info->finger_state[id] = 0;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ dev_notice(&client->dev,
+ "R(%c)(%d) [%2d]", info->ldi,
+ (info->tsp_lcdfreq_flag ? 40 : 60),
+ id);
+#else
+ dev_notice(&client->dev,
+ "R(%c) [%2d]", info->ldi, id);
+#endif
+ }
+ } else {
+ if (info->finger_state[id] != 0) {
+ info->finger_state[id] = 0;
+ dev_notice(&client->dev,
+ "R [%2d]", id);
+ }
+ }
+#else
+ if (info->panel == 'M') {
+ if (info->finger_state[id] != 0) {
+ info->finger_state[id] = 0;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ dev_notice(&client->dev,
+ "R(%c)(%d) [%2d],([%4d],[%3d])",
+ info->ldi,
+ (info->tsp_lcdfreq_flag ? 40 : 60),
+ id, x, y);
+#else
dev_notice(&client->dev,
"R(%c) [%2d],([%4d],[%3d])",
info->ldi, id, x, y);
+#endif
}
} else {
if (info->finger_state[id] != 0) {
@@ -935,6 +1016,7 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id)
id, x, y, tmp[4], tmp[5]);
}
}
+#endif
continue;
}
if (info->panel == 'M') {
@@ -955,14 +1037,36 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id)
ABS_MT_ANGLE, angle);
input_report_abs(info->input_dev,
ABS_MT_PALM, palm);
-
+#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP
+ if (info->finger_state[id] == 0) {
+ info->finger_state[id] = 1;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ dev_notice(&client->dev,
+ "P(%c)(%d) [%2d]", info->ldi,
+ (info->tsp_lcdfreq_flag ? 40 : 60), id);
+#else
+ dev_notice(&client->dev,
+ "P(%c) [%2d]", info->ldi, id);
+#endif
+ }
+#else
if (info->finger_state[id] == 0) {
info->finger_state[id] = 1;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ dev_notice(&client->dev,
+ "P(%c)(%d) [%2d],([%4d],[%3d]) w=%d, major=%d, minor=%d, angle=%d, palm=%d",
+ info->ldi,
+ (info->tsp_lcdfreq_flag ? 40 : 60),
+ id, x, y, tmp[4], tmp[6],
+ tmp[7], angle, palm);
+#else
dev_notice(&client->dev,
"P(%c) [%2d],([%4d],[%3d]) w=%d, major=%d, minor=%d, angle=%d, palm=%d",
info->ldi, id, x, y, tmp[4], tmp[6],
tmp[7], angle, palm);
+#endif
}
+#endif
} else {
input_mt_slot(info->input_dev, id);
input_mt_report_slot_state(info->input_dev,
@@ -975,13 +1079,20 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id)
ABS_MT_TOUCH_MAJOR, tmp[4]);
input_report_abs(info->input_dev,
ABS_MT_PRESSURE, tmp[5]);
-
+#ifdef CONFIG_SAMSUNG_PRODUCT_SHIP
+ if (info->finger_state[id] == 0) {
+ info->finger_state[id] = 1;
+ dev_notice(&client->dev,
+ "P [%2d]", id);
+ }
+#else
if (info->finger_state[id] == 0) {
info->finger_state[id] = 1;
dev_notice(&client->dev,
"P [%2d],([%4d],[%3d]),S:%d W:%d",
id, x, y, tmp[4], tmp[5]);
}
+#endif
}
touch_is_pressed++;
}
@@ -1070,8 +1181,7 @@ static int mms100_get_version_info(struct i2c_client *_client)
unsigned char rd_buf[8];
/* config version brust read (core, private, public) */
- ret = mms100_i2c_read(_client, ISC_ADDR_VERSION, 4, rd_buf);
-
+ ret = mms100_i2c_read(_client, ISC_ADDR_VERSION, 3, rd_buf);
if (ret < 0) {
pr_info("[TSP ISC] %s,%d: i2c read fail[%d]\n",
__func__, __LINE__, ret);
@@ -1083,12 +1193,10 @@ static int mms100_get_version_info(struct i2c_client *_client)
ts_info[SEC_CORE].compatible_version =
ts_info[SEC_BOOTLOADER].version;
- ts_info[SEC_PRIVATE_CONFIG].compatible_version =
- ts_info[SEC_PUBLIC_CONFIG].compatible_version =
+ ts_info[SEC_CONFIG].compatible_version =
ts_info[SEC_CORE].version;
ret = mms100_i2c_read(_client, ISC_ADDR_SECTION_PAGE_INFO, 8, rd_buf);
-
if (ret < 0) {
pr_info("[TSP ISC] %s,%d: i2c read fail[%d]\n",
__func__, __LINE__, ret);
@@ -1097,7 +1205,7 @@ static int mms100_get_version_info(struct i2c_client *_client)
for (i = 0; i < SECTION_NUM; i++) {
ts_info[i].start_addr = rd_buf[i];
- ts_info[i].end_addr = rd_buf[i + SECTION_NUM];
+ ts_info[i].end_addr = rd_buf[i + SECTION_NUM + 1];
}
for (i = 0; i < SECTION_NUM; i++) {
@@ -1229,8 +1337,9 @@ static int mms100_compare_version_info(struct i2c_client *_client)
}
}
section_update_flag[0] = false;
- pr_info("[TSP ISC] [%d] [%d] [%d]", section_update_flag[1],
- section_update_flag[2], section_update_flag[3]);
+ section_update_flag[1] = false;
+ pr_info("[TSP ISC] [%d] [%d] [%d]", section_update_flag[0],
+ section_update_flag[1], section_update_flag[2]);
if (section_update_flag[SEC_BOOTLOADER]) {
expected_compatibility[SEC_CORE] =
@@ -1241,16 +1350,14 @@ static int mms100_compare_version_info(struct i2c_client *_client)
}
if (section_update_flag[SEC_CORE]) {
- expected_compatibility[SEC_PUBLIC_CONFIG] =
- expected_compatibility[SEC_PRIVATE_CONFIG] =
+ expected_compatibility[SEC_CONFIG] =
mbin_info[SEC_CORE].version;
} else {
- expected_compatibility[SEC_PUBLIC_CONFIG] =
- expected_compatibility[SEC_PRIVATE_CONFIG] =
+ expected_compatibility[SEC_CONFIG] =
ts_info[SEC_CORE].version;
}
- for (i = SEC_CORE; i < SEC_PUBLIC_CONFIG; i++) {
+ for (i = SEC_CORE; i < SEC_CONFIG; i++) {
if (section_update_flag[i]) {
pr_info("[TSP ISC] section_update_flag(%d), 0x%02x, 0x%02x\n",
i, expected_compatibility[i],
@@ -1371,7 +1478,7 @@ static int mms100_ISC_clear_validate_markers(struct i2c_client *_client)
int i, j;
bool is_matched_address;
- for (i = SEC_CORE; i <= SEC_PUBLIC_CONFIG; i++) {
+ for (i = SEC_CORE; i <= SEC_CONFIG; i++) {
if (section_update_flag[i]) {
if (ts_info[i].end_addr <= 30 &&
ts_info[i].end_addr > 0) {
@@ -1384,10 +1491,10 @@ static int mms100_ISC_clear_validate_markers(struct i2c_client *_client)
}
}
- for (i = SEC_CORE; i <= SEC_PUBLIC_CONFIG; i++) {
+ for (i = SEC_CORE; i <= SEC_CONFIG; i++) {
if (section_update_flag[i]) {
is_matched_address = false;
- for (j = SEC_CORE; j <= SEC_PUBLIC_CONFIG; j++) {
+ for (j = SEC_CORE; j <= SEC_CONFIG; j++) {
if (mbin_info[i].end_addr ==
ts_info[i].end_addr) {
is_matched_address = true;
@@ -1411,10 +1518,68 @@ static int mms100_ISC_clear_validate_markers(struct i2c_client *_client)
return ISC_SUCCESS;
}
+static void mms100_calc_crc(unsigned char *crc,
+ int page_addr, unsigned char *ptr_fw)
+{
+ int i, j;
+
+ unsigned char ucData;
+
+ unsigned short SeedValue;
+ unsigned short CRC_check_buf;
+ unsigned short CRC_send_buf;
+ unsigned short IN_data;
+ unsigned short XOR_bit_1;
+ unsigned short XOR_bit_2;
+ unsigned short XOR_bit_3;
+
+ CRC_check_buf = 0xFFFF;
+ SeedValue = (unsigned short)page_addr;
+
+ for (i = 7; i >= 0; i--) {
+ IN_data = (SeedValue >> i) & 0x01;
+ XOR_bit_1 = (CRC_check_buf & 0x0001) ^ IN_data;
+ XOR_bit_2 = XOR_bit_1^(CRC_check_buf >> 11 & 0x01);
+ XOR_bit_3 = XOR_bit_1^(CRC_check_buf >> 4 & 0x01);
+ CRC_send_buf = (XOR_bit_1 << 4) | (CRC_check_buf >> 12 & 0x0F);
+ CRC_send_buf =
+ (CRC_send_buf << 7) | (XOR_bit_2 << 6) |
+ (CRC_check_buf >> 5 & 0x3F);
+ CRC_send_buf =
+ (CRC_send_buf << 4) | (XOR_bit_3 << 3) |
+ (CRC_check_buf >> 1 & 0x0007);
+ CRC_check_buf = CRC_send_buf;
+ }
+
+ for (j = 0; j < 1024; j++) {
+ ucData = ptr_fw[j];
+
+ for (i = 7; i >= 0; i--) {
+ IN_data = (ucData >> i) & 0x0001;
+ XOR_bit_1 = (CRC_check_buf & 0x0001) ^ IN_data;
+ XOR_bit_2 = XOR_bit_1^(CRC_check_buf >> 11 & 0x01);
+ XOR_bit_3 = XOR_bit_1^(CRC_check_buf >> 4 & 0x01);
+ CRC_send_buf =
+ (XOR_bit_1 << 4) | (CRC_check_buf >> 12 & 0x0F);
+ CRC_send_buf =
+ (CRC_send_buf << 7) | (XOR_bit_2 << 6) |
+ (CRC_check_buf >> 5 & 0x3F);
+ CRC_send_buf =
+ (CRC_send_buf << 4) | (XOR_bit_3 << 3) |
+ (CRC_check_buf >> 1 & 0x0007);
+ CRC_check_buf = CRC_send_buf;
+ }
+ }
+
+ crc[0] = (unsigned char)((CRC_check_buf >> 8) & 0xFF);
+ crc[1] = (unsigned char)((CRC_check_buf >> 0) & 0xFF);
+}
+
static int mms100_update_section_data(struct i2c_client *_client)
{
- int i, ret, next_ptr;
+ int i, j, ret;
unsigned char rd_buf;
+ unsigned char crc[2];
const unsigned char *ptr_fw;
char str_buf[STRING_BUF_LEN];
int page_addr;
@@ -1423,28 +1588,45 @@ static int mms100_update_section_data(struct i2c_client *_client)
if (section_update_flag[i]) {
pr_info("[TSP ISC] section data i2c flash : [%d]", i);
- next_ptr = 0;
ptr_fw = fw_mbin[i]->data;
do {
- sscanf(ptr_fw + next_ptr, "%s", str_buf);
- next_ptr += strlen(str_buf) + 1;
+ sscanf(ptr_fw, "%s", str_buf);
+ ptr_fw += strlen(str_buf) + 1;
+/*
+ pr_info("[TSP ISC] Section[%d] %s", i, str_buf );
+*/
} while (!strstr(str_buf, "[Binary]"));
- ptr_fw = ptr_fw + next_ptr + 2;
+ ptr_fw += 1;
for (page_addr = mbin_info[i].start_addr;
page_addr <= mbin_info[i].end_addr;
page_addr++) {
if (page_addr - mbin_info[i].start_addr > 0)
- ptr_fw += PACKET_SIZE;
+ ptr_fw += 1024;
- if ((ptr_fw[0] != ISC_CMD_UPDATE_MODE) ||
- (ptr_fw[1] != ISC_SUBCMD_DATA_WRITE) ||
- (ptr_fw[2] != page_addr))
- return ISC_WRITE_BUFFER_ERROR;
+ g_wr_buf[0] = ISC_CMD_UPDATE_MODE;
+ g_wr_buf[1] = ISC_SUBCMD_DATA_WRITE;
+ g_wr_buf[2] = (unsigned char)page_addr;
+ for (j = 0; j < 1024; j += 4) {
+ g_wr_buf[3+j] = ptr_fw[j+3];
+ g_wr_buf[3+j+1] = ptr_fw[j+2];
+ g_wr_buf[3+j+2] = ptr_fw[j+1];
+ g_wr_buf[3+j+3] = ptr_fw[j+0];
+ }
+
+ mms100_calc_crc(crc, page_addr, &g_wr_buf[3]);
+
+ g_wr_buf[1027] = crc[0];
+ g_wr_buf[1028] = crc[1];
+/*
+ pr_info("[TSP ISC] [%d] DATA %02X %02X %02X %02X CRC %02X %02X ",
+ page_addr, g_wr_buf[3], g_wr_buf[4],
+ g_wr_buf[5], g_wr_buf[6] , crc[0] , crc[1] );
+*/
ret = i2c_master_send(_client,
- ptr_fw, PACKET_SIZE);
+ g_wr_buf, PACKET_SIZE);
if (ret < 0) {
pr_info("[TSP ISC] %s,%d: i2c write fail[%d]\n",
__func__, __LINE__, ret);
@@ -1467,20 +1649,25 @@ static int mms100_update_section_data(struct i2c_client *_client)
}
}
- pr_info("[TSP ISC]End mms100_update_section_data()\n");
return ISC_SUCCESS;
}
-static int mms100_open_mbinary(struct i2c_client *_client)
+static int mms100_open_mbinary(struct mms_ts_info *info)
{
+ struct i2c_client *_client = info->client;
int ret = 0;
+ ret += request_firmware(&(fw_mbin[0]),\
+ "tsp_melfas/note/BOOT.fw", &_client->dev);
ret += request_firmware(&(fw_mbin[1]),\
- "tsp_melfas/note/CORE.fw", &_client->dev);
- ret += request_firmware(&(fw_mbin[2]),\
- "tsp_melfas/note/PRIV.fw", &_client->dev);
- ret += request_firmware(&(fw_mbin[3]),\
- "tsp_melfas/note/PUBL.fw", &_client->dev);
+ "tsp_melfas/note/CORE.fw", &_client->dev);
+ if (info->ldi == 'L') {
+ ret += request_firmware(&(fw_mbin[2]),\
+ "tsp_melfas/note/CONFL.fw", &_client->dev);
+ } else {
+ ret += request_firmware(&(fw_mbin[2]),\
+ "tsp_melfas/note/CONFM.fw", &_client->dev);
+ }
if (!ret)
return ISC_SUCCESS;
@@ -1514,7 +1701,7 @@ int mms100_ISC_download_mbinary(struct mms_ts_info *info)
if (ret_msg != ISC_SUCCESS)
goto ISC_ERROR_HANDLE;
*/
- ret_msg = mms100_open_mbinary(_client);
+ ret_msg = mms100_open_mbinary(info);
if (ret_msg != ISC_SUCCESS)
goto ISC_ERROR_HANDLE;
@@ -1806,15 +1993,24 @@ static int fw_download(struct mms_ts_info *info, const u8 * data, size_t len)
struct i2c_client *client = info->client;
u32 val;
int ret = 0;
+ int i;
+ u32 *buf = kzalloc(ISP_CAL_DATA_SIZE * 4, GFP_KERNEL);
+ if (!buf) {
+ dev_err(&info->client->dev, "%s: failed to allocate memory\n",
+ __func__);
+ return -ENOMEM;
+ }
if (len % 4) {
dev_err(&client->dev,
"fw image size (%d) must be a multiple of 4 bytes\n",
len);
+ kfree(buf);
return -EINVAL;
} else if (len > ISP_MAX_FW_SIZE) {
dev_err(&client->dev,
"fw image is too big, %d > %d\n", len, ISP_MAX_FW_SIZE);
+ kfree(buf);
return -EINVAL;
}
@@ -1827,6 +2023,10 @@ static int fw_download(struct mms_ts_info *info, const u8 * data, size_t len)
hw_reboot_bootloader(info);
+ dev_info(&client->dev, "calibration data backup\n");
+ for (i = 0; i < ISP_CAL_DATA_SIZE; i++)
+ buf[i] = flash_readl(info, ISP_IC_INFO_ADDR);
+
val = flash_readl(info, ISP_IC_INFO_ADDR);
dev_info(&client->dev, "IC info: 0x%02x (%x)\n", val & 0xff, val);
@@ -1846,15 +2046,19 @@ static int fw_download(struct mms_ts_info *info, const u8 * data, size_t len)
goto err;
usleep_range(1000, 1500);
- hw_reboot_normal(info);
- usleep_range(1000, 1500);
- dev_info(&client->dev, "fw download done...\n");
+ dev_info(&client->dev, "restoring data\n");
+ for (i = 0; i < ISP_CAL_DATA_SIZE; i++)
+ flash_writel(info, ISP_IC_INFO_ADDR, buf[i]);
+ kfree(buf);
+ dev_info(&client->dev, "fw download done...\n");
+ hw_reboot_normal(info);
msleep(200);
return 0;
err:
dev_err(&client->dev, "fw download failed...\n");
+ kfree(buf);
hw_reboot_normal(info);
return ret;
}
@@ -1987,7 +2191,7 @@ err_mem_alloc:
}
#endif /* SEC_TSP_ISC_FW_UPDATE */
-static int get_core_version(struct mms_ts_info *info)
+static int get_fw_version(struct mms_ts_info *info, u8 area)
{
struct i2c_client *client = info->client;
struct i2c_adapter *adapter = client->adapter;
@@ -2016,43 +2220,14 @@ static int get_core_version(struct mms_ts_info *info)
return ret;
}
- return buf[1];
-}
-
-static int get_fw_version_temp(struct mms_ts_info *info)
-{
- struct i2c_client *client = info->client;
- struct i2c_adapter *adapter = client->adapter;
- struct i2c_msg msg;
- u8 reg = MMS_CORE_VERSION;
- int ret;
- unsigned char buf[4];
-
- msg.addr = client->addr;
- msg.flags = 0x00;
- msg.len = 1;
- msg.buf = &reg;
-
- ret = i2c_transfer(adapter, &msg, 1);
-
- if (ret >= 0) {
- msg.addr = client->addr;
- msg.flags = I2C_M_RD;
- msg.len = 4;
- msg.buf = buf;
-
- ret = i2c_transfer(adapter, &msg, 1);
- }
- if (ret < 0) {
- pr_err("[TSP] : read error : [%d]", ret);
- return ret;
- }
-
- dev_info(&client->dev,
- "[TSP]firm ver [0x%x][0x%x][0x%x][0x%x]\n",
- buf[0], buf[1], buf[2], buf[3]);
-
- return buf[2];
+ if (area == SEC_BOOTLOADER)
+ return buf[0];
+ else if (area == SEC_CORE)
+ return buf[1];
+ else if (area == SEC_CONFIG)
+ return buf[2];
+ else
+ return 0;
}
static int get_panel_version(struct mms_ts_info *info)
@@ -2067,20 +2242,7 @@ static int get_panel_version(struct mms_ts_info *info)
return ret;
}
-#if 0
-static int get_fw_version(struct mms_ts_info *info)
-{
- int ret;
- int retries = 3;
-
- /* this seems to fail sometimes after a reset.. retry a few times */
- do {
- ret = i2c_smbus_read_byte_data(info->client, MMS_FW_VERSION);
- } while (ret < 0 && retries-- > 0);
- return ret;
-}
-#endif
/*
static int mms_ts_enable(struct mms_ts_info *info, int wakeupcmd)
{
@@ -2123,7 +2285,7 @@ static int mms_ts_fw_info(struct mms_ts_info *info)
int ret = 0;
int ver;
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
dev_info(&client->dev,
"[TSP]fw version 0x%02x !!!!\n", ver);
@@ -2144,8 +2306,8 @@ static int mms_ts_fw_info(struct mms_ts_info *info)
return ret;
}
-#if 0
-static int mms_ts_fw_load(struct mms_ts_info *info)
+
+static int mms_ts_fw_load(struct mms_ts_info *info, bool force, char ldi)
{
struct i2c_client *client = info->client;
@@ -2154,15 +2316,11 @@ static int mms_ts_fw_load(struct mms_ts_info *info)
int bin_ver;
int retries = 3;
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
dev_info(&client->dev,
"[TSP]fw version 0x%02x !!!!\n", ver);
- pr_err("[TSP] ISC Ver [0x%02x] [0x%02x]",
- i2c_smbus_read_byte_data(info->client, 0xF4),
- i2c_smbus_read_byte_data(info->client, 0xF5));
-
if (!info->pdata || !info->pdata->mux_fw_flash) {
ret = 1;
dev_err(&client->dev,
@@ -2170,21 +2328,30 @@ static int mms_ts_fw_load(struct mms_ts_info *info)
goto out;
}
- if (info->ldi == 'L')
- bin_ver = FW_VERSION_L;
- else
- bin_ver = FW_VERSION_M;
+ if (ldi == 'N') {
+ if (info->ldi == 'M')
+ bin_ver = FW_VERSION_M;
+ else
+ bin_ver = FW_VERSION_L;
+ } else {
+ if (ldi == 'M')
+ bin_ver = FW_VERSION_M;
+ else
+ bin_ver = FW_VERSION_L;
+ }
- if (ver >= bin_ver) {
- dev_info(&client->dev,
- "fw version update does not need\n");
- goto done;
+ if (!force) {
+ if ((ver >= bin_ver) && (ver != 0xff)) {
+ dev_info(&client->dev,
+ "fw version update does not need\n");
+ goto done;
+ }
}
while (retries--) {
ret = mms100_ISC_download_mbinary(info);
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
if (ret == 0) {
@@ -2200,19 +2367,10 @@ static int mms_ts_fw_load(struct mms_ts_info *info)
}
out:
- return ret;
-
done:
-
-#if ISC_DL_MODE /* ISC_DL_MODE start */
- pr_err("[TSP] ISC Ver [0x%02x] [0x%02x]",
- i2c_smbus_read_byte_data(info->client, 0xF4),
- i2c_smbus_read_byte_data(info->client, 0xF5));
-#endif
-
return ret;
}
-#endif
+
#ifdef SEC_TSP_FACTORY_TEST
static void set_cmd_result(struct mms_ts_info *info, char *buff, int len)
{
@@ -2445,6 +2603,23 @@ static void get_raw_data(struct mms_ts_info *info, u8 cmd)
snprintf(buff, sizeof(buff), "%d,%d", min_value, max_value);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
+ touch_is_pressed = 0;
+ release_all_fingers(info);
+
+ mms_pwr_on_reset(info);
+ info->enabled = true;
+
+ if (info->fw_ic_ver < 0x18) {
+ if (info->ta_status) {
+ dev_notice(&info->client->dev, "TA connect!!!\n");
+ i2c_smbus_write_byte_data(info->client, 0x33, 0x1);
+ } else {
+ dev_notice(&info->client->dev, "TA disconnect!!!\n");
+ i2c_smbus_write_byte_data(info->client, 0x33, 0x2);
+ }
+ }
+ mms_set_noise_mode(info);
+
enable_irq(info->irq);
return;
@@ -2649,7 +2824,7 @@ static int mms_ts_core_fw_load(struct mms_ts_info *info)
long fsize = 0;
const struct firmware *tsp_fw = NULL;
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
dev_info(&client->dev, "Entered REQ_FW\n");
@@ -2698,7 +2873,7 @@ static int mms_ts_core_fw_load(struct mms_ts_info *info)
continue;
}
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
if (ver == fw_bin_ver) {
@@ -2749,29 +2924,42 @@ static void fw_update(void *device_data)
"fw_ic_ver = 0x%02x, fw_bin_ver = 0x%02x\n",
info->fw_ic_ver, fw_bin_ver);
- if (info->cmd_param[0] == 0
- && info->fw_ic_ver >= fw_bin_ver) {
- dev_info(&client->dev,
- "fw version update does not need\n");
- info->cmd_state = 2;
- goto do_not_need_update;
+ if (info->cmd_param[0] == 0) {
+ if (info->fw_core_ver > 0x53) {
+ dev_info(&client->dev,
+ "fw version update does not need\n");
+ info->cmd_state = 2;
+ goto do_not_need_update;
+ } else if (info->fw_core_ver == 0x53) {
+ if (info->fw_ic_ver >= fw_bin_ver) {
+ dev_info(&client->dev,
+ "fw version update does not need\n");
+ info->cmd_state = 2;
+ goto do_not_need_update;
+ }
+ } else { /* core < 0x53 */
+ dev_info(&client->dev,
+ "fw version update need(core:0x%x)\n",
+ info->fw_core_ver);
+ }
}
switch (info->cmd_param[0]) {
case BUILT_IN:
dev_info(&client->dev, "built in fw is loaded!!\n");
-
+ disable_irq(info->irq);
while (retries--) {
#if 0
ret = mms100_ISC_download_mbinary(info);
#else
ret = mms_ts_core_fw_load(info);
#endif
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
if (ret == 0) {
pr_err("[TSP] mms100_ISC_download_mbinary success");
info->cmd_state = 2;
+ enable_irq(info->irq);
return;
} else {
pr_err("[TSP] mms100_ISC_download_mbinary fail[%d]",
@@ -2779,6 +2967,7 @@ static void fw_update(void *device_data)
info->cmd_state = 3;
}
}
+ enable_irq(info->irq);
return;
break;
@@ -2860,7 +3049,7 @@ static void fw_update(void *device_data)
continue;
}
- ver = get_fw_version_temp(info);
+ ver = get_fw_version(info, SEC_CONFIG);
info->fw_ic_ver = ver;
if (info->cmd_param[0] == 1 || info->cmd_param[0] == 2) {
@@ -2913,9 +3102,9 @@ static void get_fw_ver_bin(void *device_data)
set_default_result(info);
if (info->ldi == 'L')
- snprintf(buff, sizeof(buff), "%#02x", FW_VERSION_L);
+ snprintf(buff, sizeof(buff), "ME0053%02x", FW_VERSION_L);
else
- snprintf(buff, sizeof(buff), "%#02x", FW_VERSION_M);
+ snprintf(buff, sizeof(buff), "ME0053%02x", FW_VERSION_M);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 2;
@@ -2928,12 +3117,15 @@ static void get_fw_ver_ic(void *device_data)
struct mms_ts_info *info = (struct mms_ts_info *)device_data;
char buff[16] = {0};
- int ver;
set_default_result(info);
- ver = info->fw_ic_ver;
- snprintf(buff, sizeof(buff), "%#02x", ver);
+ if (info->enabled) {
+ info->fw_core_ver = get_fw_version(info, SEC_CORE);
+ info->fw_ic_ver = get_fw_version(info, SEC_CONFIG);
+ }
+ snprintf(buff, sizeof(buff), "ME00%02x%02x",
+ info->fw_core_ver, info->fw_ic_ver);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 2;
@@ -2949,7 +3141,10 @@ static void get_config_ver(void *device_data)
set_default_result(info);
- snprintf(buff, sizeof(buff), "%s", info->config_fw_version);
+ if (info->ldi == 'L')
+ snprintf(buff, sizeof(buff), "N7100_Me_0921_L");
+ else
+ snprintf(buff, sizeof(buff), "N7100_Me_0911_M");
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
info->cmd_state = 2;
dev_info(&info->client->dev, "%s: %s(%d)\n", __func__,
@@ -3206,7 +3401,7 @@ static void get_x_num(void *device_data)
__func__, val);
return;
}
- } else {
+ } else if (info->fw_ic_ver < 0x29) {
ret = i2c_smbus_read_i2c_block_data(info->client,
ADDR_CH_NUM, 2, r_buf);
val = r_buf[0];
@@ -3220,6 +3415,8 @@ static void get_x_num(void *device_data)
__func__, val);
return;
}
+ } else {
+ val = 30;
}
snprintf(buff, sizeof(buff), "%u", val);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
@@ -3252,7 +3449,7 @@ static void get_y_num(void *device_data)
__func__, val);
return;
}
- } else {
+ } else if (info->fw_ic_ver < 0x29) {
ret = i2c_smbus_read_i2c_block_data(info->client,
ADDR_CH_NUM, 2, r_buf);
val = r_buf[1];
@@ -3266,6 +3463,8 @@ static void get_y_num(void *device_data)
__func__, val);
return;
}
+ } else {
+ val = 17;
}
snprintf(buff, sizeof(buff), "%u", val);
set_cmd_result(info, buff, strnlen(buff, sizeof(buff)));
@@ -3671,6 +3870,9 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
info->lcd_type = info->pdata->lcd_type;
info->input_event = info->pdata->input_event;
info->register_cb = info->pdata->register_cb;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ info->register_lcd_cb = info->pdata->register_lcd_cb;
+#endif
} else {
info->max_x = 720;
info->max_y = 1280;
@@ -3679,7 +3881,7 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
i2c_set_clientdata(client, info);
info->pdata->power(true);
- msleep(100);
+ msleep(250);
if (gpio_get_value(GPIO_OLED_ID)) {
info->ldi = 'L';
@@ -3696,7 +3898,7 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
goto err_config;
}
- info->fw_core_ver = get_core_version(info);
+ info->fw_core_ver = get_fw_version(info, SEC_CORE);
dev_info(&client->dev, "core version : 0x%02x\n",
info->fw_core_ver);
@@ -3710,10 +3912,12 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
ret);
goto err_config;
}
+ info->fw_core_ver = get_fw_version(info, SEC_CORE);
}
if (info->ldi == 'L') {
- if (info->fw_core_ver != 0x53) {
+ if ((info->fw_core_ver < 0x53) ||
+ (info->fw_core_ver == 0xff)) {
dev_err(&client->dev, "core version must be 0x53\n");
dev_err(&client->dev, "excute core firmware update\n");
ret = mms_ts_core_fw_load(info);
@@ -3722,13 +3926,49 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
"failed to initialize (%d)\n", ret);
goto err_config;
}
+ info->fw_core_ver = get_fw_version(info, SEC_CORE);
+ }
+ info->panel = get_panel_version(info);
+ if (info->panel != 'M') {
+ if (info->fw_core_ver == 0x53) {
+ dev_err(&client->dev, "cannot read panel info\n");
+ dev_err(&client->dev, "excute core firmware update\n");
+ ret = mms_ts_fw_load(info, true, 'L');
+ } else {
+ dev_err(&client->dev, "excute core firmware update\n");
+ ret = mms_ts_core_fw_load(info);
+ }
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to initialize (%d)\n",
+ ret);
+ }
}
- info->fw_ic_ver = get_fw_version_temp(info);
- if (info->fw_ic_ver < FW_VERSION_L) {
- dev_err(&client->dev, "firmware version error\n");
- dev_err(&client->dev, "panel:0x%x, bin:0x%x\n",
+ info->fw_ic_ver = get_fw_version(info, SEC_CONFIG);
+ if (((info->fw_ic_ver < FW_VERSION_L) ||
+ (info->fw_ic_ver == 0xff)) &&
+ (info->fw_core_ver == 0x53)) {
+ dev_err(&client->dev, "firmware update\n");
+ dev_err(&client->dev, "ic:0x%x, bin:0x%x\n",
info->fw_ic_ver, FW_VERSION_L);
- ret = mms_ts_core_fw_load(info);
+ if ((info->fw_ic_ver >= 0x21) ||
+ (info->fw_ic_ver == 0) ||
+ (info->fw_ic_ver == 0xff))
+ ret = mms_ts_fw_load(info, false, 'N');
+ else
+ ret = mms_ts_core_fw_load(info);
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to initialize (%d)\n", ret);
+ goto err_config;
+ }
+ }
+ if ((info->fw_ic_ver >= 0x50) &&
+ (info->fw_ic_ver <= 0x69)) {
+ dev_err(&client->dev, "LSI panel, Magna firmware written\n");
+ dev_err(&client->dev, "ic:0x%x, bin:0x%x\n",
+ info->fw_ic_ver, FW_VERSION_L);
+ ret = mms_ts_fw_load(info, true, 'L');
if (ret) {
dev_err(&client->dev,
"failed to initialize (%d)\n", ret);
@@ -3738,14 +3978,9 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
} else {
info->panel = get_panel_version(info);
dev_info(&client->dev, "%c panel\n", info->panel);
-#if 0
- if (info->panel == 'M')
- ret = mms_ts_fw_load(info);
- else
- ret = mms_ts_fw_info(info);
-#else
if (info->panel == 'M') {
- if (info->fw_core_ver != 0x53) {
+ if ((info->fw_core_ver < 0x53) ||
+ (info->fw_core_ver == 0xff)) {
dev_err(&client->dev, "core version must be 0x53\n");
dev_err(&client->dev, "excute core firmware update\n");
ret = mms_ts_core_fw_load(info);
@@ -3755,13 +3990,20 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
ret);
goto err_config;
}
+ info->fw_core_ver =
+ get_fw_version(info, SEC_CORE);
}
- info->fw_ic_ver = get_fw_version_temp(info);
- if (info->fw_ic_ver < FW_VERSION_M) {
- dev_err(&client->dev, "firmware version error\n");
- dev_err(&client->dev, "panel:0x%x, bin:0x%x\n",
+ info->fw_ic_ver = get_fw_version(info, SEC_CONFIG);
+ if ((info->fw_ic_ver < FW_VERSION_M) &&
+ (info->fw_core_ver == 0x53)) {
+ dev_err(&client->dev, "firmware update\n");
+ dev_err(&client->dev, "ic:0x%x, bin:0x%x\n",
info->fw_ic_ver, FW_VERSION_M);
- ret = mms_ts_core_fw_load(info);
+ if ((info->fw_ic_ver >= 0x24) ||
+ (info->fw_ic_ver == 0))
+ ret = mms_ts_fw_load(info, false, 'N');
+ else
+ ret = mms_ts_core_fw_load(info);
if (ret) {
dev_err(&client->dev,
"failed to initialize (%d)\n",
@@ -3770,11 +4012,19 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
}
}
} else if (info->panel == 'A') {
- dev_info(&client->dev, "A panel. Do nothing\n");
+ dev_info(&client->dev, "A panel. Do not firm update\n");
} else {
dev_err(&client->dev, "cannot read panel info\n");
- dev_err(&client->dev, "excute core firmware update\n");
- ret = mms_ts_core_fw_load(info);
+ info->fw_ic_ver = get_fw_version(info, SEC_CONFIG);
+ if (info->fw_core_ver == 0x53) {
+ dev_err(&client->dev, "firmware update\n");
+ dev_err(&client->dev, "ic:0x%x, bin:0x%x\n",
+ info->fw_ic_ver, FW_VERSION_M);
+ ret = mms_ts_fw_load(info, true, 'N');
+ } else {
+ dev_err(&client->dev, "excute core firmware update\n");
+ ret = mms_ts_core_fw_load(info);
+ }
if (ret) {
dev_err(&client->dev,
"failed to initialize (%d)\n",
@@ -3782,7 +4032,18 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
goto err_config;
}
}
-#endif
+ if ((info->fw_ic_ver >= 0x30) &&
+ (info->fw_ic_ver <= 0x49)) {
+ dev_err(&client->dev, "Magna panel, LSI firmware written\n");
+ dev_err(&client->dev, "ic:0x%x, bin:0x%x\n",
+ info->fw_ic_ver, FW_VERSION_M);
+ ret = mms_ts_fw_load(info, true, 'M');
+ if (ret) {
+ dev_err(&client->dev,
+ "failed to initialize (%d)\n", ret);
+ goto err_config;
+ }
+ }
}
info->panel = get_panel_version(info);
dev_info(&client->dev, "%c panel\n", info->panel);
@@ -3802,6 +4063,12 @@ static int __devinit mms_ts_probe(struct i2c_client *client,
info->callbacks.inform_charger = melfas_ta_cb;
if (info->register_cb)
info->register_cb(&info->callbacks);
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ info->lcd_callback.inform_lcd = melfas_lcd_cb;
+ if (info->register_lcd_cb)
+ info->register_lcd_cb(&info->lcd_callback);
+ info->tsp_lcdfreq_flag = 0;
+#endif
snprintf(info->phys, sizeof(info->phys),
"%s/input0", dev_name(&client->dev));
@@ -3954,8 +4221,12 @@ static int mms_ts_suspend(struct device *dev)
disable_irq(info->irq);
info->enabled = false;
touch_is_pressed = 0;
+#ifdef CONFIG_LCD_FREQ_SWITCH
+ info->tsp_lcdfreq_flag = 0;
+#endif
release_all_fingers(info);
info->pdata->power(0);
+ info->sleep_wakeup_ta_check = info->ta_status;
/* This delay needs to prevent unstable POR by
rapid frequently pressing of PWR key. */
msleep(50);
@@ -3979,7 +4250,7 @@ static int mms_ts_resume(struct device *dev)
info->pdata->power(1);
msleep(120);
- if (info->fw_ic_ver != 0x18) {
+ if (info->fw_ic_ver < 0x18) {
if (info->ta_status) {
dev_notice(&client->dev, "TA connect!!!\n");
i2c_smbus_write_byte_data(info->client, 0x33, 0x1);
@@ -3991,6 +4262,15 @@ static int mms_ts_resume(struct device *dev)
info->enabled = true;
mms_set_noise_mode(info);
+ if (info->fw_ic_ver >= 0x21) {
+ if ((info->ta_status == 1) &&
+ (info->sleep_wakeup_ta_check == 0)) {
+ dev_notice(&client->dev,
+ "TA connect!!! %s\n", __func__);
+ i2c_smbus_write_byte_data(info->client, 0x32, 0x1);
+ }
+ }
+
/* Because irq_type by EXT_INTxCON register is changed to low_level
* after wakeup, irq_type set to falling edge interrupt again.
*/