aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/wacom
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/wacom')
-rw-r--r--drivers/input/touchscreen/wacom/w9002_flash.c1253
-rw-r--r--drivers/input/touchscreen/wacom/w9002_flash.h211
-rw-r--r--drivers/input/touchscreen/wacom/wacom_i2c.c54
-rw-r--r--drivers/input/touchscreen/wacom/wacom_i2c_firm.c7
-rw-r--r--drivers/input/touchscreen/wacom/wacom_i2c_flash.c28
-rw-r--r--drivers/input/touchscreen/wacom/wacom_i2c_func.c52
6 files changed, 1597 insertions, 8 deletions
diff --git a/drivers/input/touchscreen/wacom/w9002_flash.c b/drivers/input/touchscreen/wacom/w9002_flash.c
new file mode 100644
index 0000000..e2fe54d
--- /dev/null
+++ b/drivers/input/touchscreen/wacom/w9002_flash.c
@@ -0,0 +1,1253 @@
+/*
+ * w9002_flash.c - Wacom Digitizer Controller Flash Driver
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/wacom_i2c.h>
+#include "w9002_flash.h"
+
+static int wacom_i2c_flash_chksum(struct wacom_i2c *wac_i2c,
+ unsigned char *flash_data,
+ unsigned long *max_address)
+{
+ unsigned long i;
+ unsigned long chksum = 0;
+
+ for (i = 0x0000; i <= *max_address; i++)
+ chksum += flash_data[i];
+
+ chksum &= 0xFFFF;
+
+ return (int)chksum;
+}
+
+static int wacom_flash_cmd(struct wacom_i2c *wac_i2c)
+{
+ int rv, len, i;
+ u8 buf[10];
+ bool i2c_mode = WACOM_I2C_MODE_BOOT;
+
+#if defined(CONFIG_MACH_KONA)
+ buf[0] = 0x0d;
+ buf[1] = FLASH_START0;
+ buf[2] = FLASH_START1;
+ buf[3] = FLASH_START2;
+ buf[4] = FLASH_START3;
+ buf[5] = FLASH_START4;
+ buf[6] = FLASH_START5;
+ buf[7] = 0x0d;
+
+ len = 8;
+ rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode);
+#else
+
+ for (i = 0; i < 2; ++i) {
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x32;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen:fail change to normal:%d\n",
+ rv);
+
+ i2c_mode = WACOM_I2C_MODE_NORMAL;
+ continue;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 2;
+ buf[len++] = 2;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, i2c_mode);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen:fail change to normal:%d\n",
+ rv);
+ i2c_mode = WACOM_I2C_MODE_NORMAL;
+ continue;
+ }
+ }
+#endif
+ if (rv < 0) {
+ printk(KERN_ERR
+ "Sending flash command failed\n");
+ return -1;
+ }
+
+ printk(KERN_DEBUG "epen:flash cmd sent:%d\n", rv);
+ msleep(500);
+
+ return 0;
+}
+
+static bool flash_query(struct wacom_i2c *wac_i2c)
+{
+ int rv, ECH;
+ u8 buf[4];
+ u16 len;
+ unsigned char command[CMD_SIZE];
+ unsigned char response[RSP_SIZE];
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ printk(KERN_DEBUG "epen: %s\n", __func__);
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 5;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_QUERY;
+ command[6] = ECH = 7;
+
+ rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 5 rv:%d\n", rv);
+ return false;
+ }
+
+ if ((response[3] != QUERY_CMD) || (response[4] != ECH)) {
+ printk(KERN_DEBUG "epen: res3:%d res4:%d\n", response[3],
+ response[4]);
+ return false;
+ }
+ if (response[5] != QUERY_RSP) {
+ printk(KERN_DEBUG "epen: res5:%d\n", response[5]);
+ return false;
+ }
+
+ return true;
+}
+
+static bool flash_blver(struct wacom_i2c *wac_i2c, int *blver)
+{
+ int rv, ECH;
+ u8 buf[4];
+ u16 len;
+ unsigned char command[CMD_SIZE];
+ unsigned char response[RSP_SIZE];
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 5;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_BLVER;
+ command[6] = ECH = 7;
+
+ rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 5 rv:%d\n", rv);
+ return false;
+ }
+
+ if ((response[3] != BOOT_CMD) || (response[4] != ECH))
+ return false;
+
+ *blver = (int)response[5];
+
+ return true;
+}
+
+static bool flash_mputype(struct wacom_i2c *wac_i2c, int *pMpuType)
+{
+ int rv, ECH;
+ u8 buf[4];
+ u16 len;
+ unsigned char command[CMD_SIZE];
+ unsigned char response[RSP_SIZE];
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE; /* Command-MSB, SET_REPORT */
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 5;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_MPU;
+ command[6] = ECH = 7;
+
+ rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(1000, 1000);
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 5 rv:%d\n", rv);
+ return false;
+ }
+
+ if ((response[3] != MPU_CMD) || (response[4] != ECH))
+ return false;
+
+ *pMpuType = (int)response[5];
+
+ return true;
+}
+
+static bool flash_security_unlock(struct wacom_i2c *wac_i2c, int *status)
+{
+ int rv, ECH;
+ u8 buf[4];
+ u16 len;
+ unsigned char command[CMD_SIZE];
+ unsigned char response[RSP_SIZE];
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 5;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_SECURITY_UNLOCK;
+ command[6] = ECH = 7;
+
+ rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return 0;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(1000, 1000);
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 5 rv:%d\n", rv);
+ return false;
+ }
+
+ if ((response[3] != SEC_CMD) || (response[4] != ECH))
+ return false;
+
+ *status = (int)response[5];
+
+ return true;
+}
+
+static bool flash_end(struct wacom_i2c *wac_i2c)
+{
+ int rv, ECH;
+ u8 buf[4];
+ u16 len;
+ unsigned char command[CMD_SIZE];
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 5;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_EXIT;
+ command[6] = ECH = 7;
+
+ rv = wacom_i2c_send(wac_i2c, command, 7, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ return true;
+}
+
+static int GetBLVersion(struct wacom_i2c *wac_i2c, int *pBLVer)
+{
+ int rv;
+ int retry = 0;
+
+ wacom_flash_cmd(wac_i2c);
+ do {
+ msleep(100);
+ rv = flash_query(wac_i2c);
+ retry++;
+ } while (rv < 0 && retry < 10);
+
+ if (rv < 0)
+ return EXIT_FAIL_GET_BOOT_LOADER_VERSION;
+
+ rv = flash_blver(wac_i2c, pBLVer);
+ if (rv)
+ return EXIT_OK;
+ else
+ return EXIT_FAIL_GET_BOOT_LOADER_VERSION;
+}
+
+static int GetMpuType(struct wacom_i2c *wac_i2c, int *pMpuType)
+{
+ int rv;
+
+ if (!flash_query(wac_i2c)) {
+ if (!wacom_flash_cmd(wac_i2c)) {
+ return EXIT_FAIL_ENTER_FLASH_MODE;
+ } else {
+ msleep(100);
+ if (!flash_query(wac_i2c))
+ return EXIT_FAIL_FLASH_QUERY;
+ }
+ }
+
+ rv = flash_mputype(wac_i2c, pMpuType);
+ if (rv)
+ return EXIT_OK;
+ else
+ return EXIT_FAIL_GET_MPU_TYPE;
+}
+
+static int SetSecurityUnlock(struct wacom_i2c *wac_i2c, int *pStatus)
+{
+ int rv;
+
+ if (!flash_query(wac_i2c)) {
+ if (!wacom_flash_cmd(wac_i2c)) {
+ return EXIT_FAIL_ENTER_FLASH_MODE;
+ } else {
+ msleep(100);
+ if (!flash_query(wac_i2c))
+ return EXIT_FAIL_FLASH_QUERY;
+ }
+ }
+
+ rv = flash_security_unlock(wac_i2c, pStatus);
+ if (rv)
+ return EXIT_OK;
+ else
+ return EXIT_FAIL;
+}
+
+static bool flash_erase(struct wacom_i2c *wac_i2c, bool bAllUserArea,
+ int *eraseBlock, int num)
+{
+ int rv, ECH;
+ unsigned char sum;
+ unsigned char buf[72];
+ unsigned char cmd_chksum;
+ u16 len;
+ int i, j;
+ unsigned char command[CMD_SIZE];
+ unsigned char response[RSP_SIZE];
+
+ for (i = 0; i < num; i++) {
+ /*msleep(500);*/
+retry:
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: failing 1:%d\n", i);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 7;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_ERASE_FLASH;
+ command[6] = ECH = i;
+ command[7] = *eraseBlock;
+ eraseBlock++;
+
+ sum = 0;
+ for (j = 0; j < 8; j++)
+ sum += command[j];
+ cmd_chksum = ~sum + 1;
+ command[8] = cmd_chksum;
+
+ rv = wacom_i2c_send(wac_i2c, command, 9, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: failing 2:%d\n", i);
+ return false;
+ }
+
+ switch (i) {
+ case 0:
+ msleep(3000);
+ break;
+
+ case 1:
+ msleep(3000);
+ break;
+
+ case 2:
+ msleep(5000);
+ break;
+
+ case 3:
+ msleep(500);
+ break;
+
+ default:
+ msleep(5000);
+ break;
+ }
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: failing 3:%d\n", i);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: failing 4:%d\n", i);
+ return false;
+ }
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: failing 5:%d\n", i);
+ return false;
+ }
+
+ if ((response[3] != ERS_CMD) || (response[4] != ECH)) {
+ printk(KERN_DEBUG "epen: failing 6:%d\n", i);
+ return false;
+ }
+
+ if (response[5] == 0x80) {
+ printk(KERN_DEBUG "epen: retry\n");
+ goto retry;
+ }
+ if (response[5] != ACK) {
+ printk(KERN_DEBUG "epen: failing 7:%d res5:%d\n", i,
+ response[5]);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool is_flash_marking(struct wacom_i2c *wac_i2c,
+ size_t data_size, bool *bMarking, int iMpuID)
+{
+ const int MAX_CMD_SIZE = (12 + FLASH_BLOCK_SIZE + 2);
+ int rv, ECH;
+ unsigned char flash_data[FLASH_BLOCK_SIZE];
+ unsigned char buf[300];
+ unsigned char sum;
+ int len;
+ unsigned int i, j;
+ unsigned char response[RSP_SIZE];
+ unsigned char command[MAX_CMD_SIZE];
+
+ *bMarking = false;
+
+ printk(KERN_DEBUG "epen: started\n");
+ for (i = 0; i < FLASH_BLOCK_SIZE; i++)
+ flash_data[i] = 0xFF;
+
+ flash_data[56] = 0x00;
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 76;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_VERIFY_FLASH;
+ command[6] = ECH = 1;
+ command[7] = 0xC0;
+ command[8] = 0x1F;
+ command[9] = 0x01;
+ command[10] = 0x00;
+ command[11] = 8;
+
+ sum = 0;
+ for (j = 0; j < 12; j++)
+ sum += command[j];
+
+ command[MAX_CMD_SIZE - 2] = ~sum + 1;
+
+ sum = 0;
+ printk(KERN_DEBUG "epen: start writing command\n");
+ for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
+ command[i] = flash_data[i - 12];
+ sum += flash_data[i - 12];
+ }
+ command[MAX_CMD_SIZE - 1] = ~sum + 1;
+
+ printk(KERN_DEBUG "epen: sending command\n");
+ rv = wacom_i2c_send(wac_i2c, command, MAX_CMD_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ rv = wacom_i2c_recv(wac_i2c, response, RSP_SIZE, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 5 rv:%d\n", rv);
+ return false;
+ }
+
+ printk(KERN_DEBUG "epen: checking response\n");
+ if ((response[3] != MARK_CMD) ||
+ (response[4] != ECH) || (response[5] != ACK)) {
+ printk(KERN_DEBUG "epen: fails res3:%d res4:%d res5:%d\n",
+ response[3], response[4], response[5]);
+ return false;
+ }
+
+ *bMarking = true;
+ return true;
+}
+
+static bool flash_write_block(struct wacom_i2c *wac_i2c, char *flash_data,
+ unsigned long ulAddress, u8 *pcommand_id)
+{
+ const int MAX_COM_SIZE = (12 + FLASH_BLOCK_SIZE + 2);
+ int len, ECH;
+ unsigned char buf[300];
+ int rv;
+ unsigned char sum;
+ unsigned char command[MAX_COM_SIZE];
+ unsigned char response[RSP_SIZE];
+ unsigned int i;
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0)
+ return false;
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 76;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_WRITE_FLASH;
+ command[6] = ECH = ++(*pcommand_id);
+ command[7] = ulAddress & 0x000000ff;
+ command[8] = (ulAddress & 0x0000ff00) >> 8;
+ command[9] = (ulAddress & 0x00ff0000) >> 16;
+ command[10] = (ulAddress & 0xff000000) >> 24;
+ command[11] = 8;
+ sum = 0;
+ for (i = 0; i < 12; i++)
+ sum += command[i];
+ command[MAX_COM_SIZE - 2] = ~sum + 1;
+
+ sum = 0;
+ for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
+ command[i] = flash_data[ulAddress + (i - 12)];
+ sum += flash_data[ulAddress + (i - 12)];
+ }
+ command[MAX_COM_SIZE - 1] = ~sum + 1;
+
+ rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ if ((response[3] != WRITE_CMD) ||
+ (response[4] != ECH) || response[5] != ACK)
+ return false;
+
+ return true;
+
+}
+
+static bool flash_write(struct wacom_i2c *wac_i2c,
+ unsigned char *flash_data, size_t data_size,
+ unsigned long start_address, unsigned long *max_address,
+ int mpuType)
+{
+ unsigned long ulAddress;
+ int i;
+ bool rv;
+ unsigned long pageNo = 0;
+ u8 command_id = 0;
+
+ printk(KERN_DEBUG "epen: flash_write start\n");
+
+ for (ulAddress = start_address; ulAddress < *max_address;
+ ulAddress += FLASH_BLOCK_SIZE) {
+ unsigned int j;
+ bool bWrite = false;
+
+ /* Wacom 2012/10/04: skip if all each data locating on
+ from ulAddr to ulAddr+Block_SIZE_W are 0xff */
+ for (i = 0; i < FLASH_BLOCK_SIZE; i++) {
+ if (flash_data[ulAddress + i] != 0xFF)
+ break;
+ }
+ if (i == (FLASH_BLOCK_SIZE)) {
+ /*printk(KERN_DEBUG"epen:BLOCK PASSED\n"); */
+ continue;
+ }
+ /* Wacom 2012/10/04 */
+
+ for (j = 0; j < FLASH_BLOCK_SIZE; j++) {
+ if (flash_data[ulAddress + j] == 0xFF)
+ continue;
+ else {
+ bWrite = true;
+ break;
+ }
+ }
+
+ if (!bWrite) {
+ pageNo++;
+ continue;
+ }
+
+ rv = flash_write_block(wac_i2c, flash_data, ulAddress,
+ &command_id);
+ if (!rv)
+ return false;
+
+ pageNo++;
+ }
+
+ return true;
+}
+
+static bool flash_verify(struct wacom_i2c *wac_i2c,
+ unsigned char *flash_data, size_t data_size,
+ unsigned long start_address,
+ unsigned long *max_address, int mpuType)
+{
+ int ECH;
+ unsigned long ulAddress;
+ int rv;
+ unsigned long pageNo = 0;
+ u8 command_id = 0;
+ printk(KERN_DEBUG "epen: verify starts\n");
+ for (ulAddress = start_address; ulAddress < *max_address;
+ ulAddress += FLASH_BLOCK_SIZE) {
+ const int MAX_CMD_SIZE = 12 + FLASH_BLOCK_SIZE + 2;
+ unsigned char buf[300];
+ unsigned char sum;
+ int len;
+ unsigned int i, j;
+ unsigned char command[MAX_CMD_SIZE];
+ unsigned char response[RSP_SIZE];
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 76;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_VERIFY_FLASH;
+ command[6] = ECH = ++command_id;
+ command[7] = ulAddress & 0x000000ff;
+ command[8] = (ulAddress & 0x0000ff00) >> 8;
+ command[9] = (ulAddress & 0x00ff0000) >> 16;
+ command[10] = (ulAddress & 0xff000000) >> 24;
+ command[11] = 8;
+
+ sum = 0;
+ for (j = 0; j < 12; j++)
+ sum += command[j];
+ command[MAX_CMD_SIZE - 2] = ~sum + 1;
+
+ sum = 0;
+ for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
+ command[i] = flash_data[ulAddress + (i - 12)];
+ sum += flash_data[ulAddress + (i - 12)];
+ }
+ command[MAX_CMD_SIZE - 1] = ~sum + 1;
+
+ rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ if (ulAddress <= 0x0ffff)
+ ndelay(250000);
+ else if (ulAddress >= 0x10000 && ulAddress <= 0x20000)
+ ndelay(350000);
+ else
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 5 rv:%d\n", rv);
+ return false;
+ }
+
+ if ((response[3] != VERIFY_CMD) ||
+ (response[4] != ECH) || (response[5] != ACK)) {
+ printk(KERN_DEBUG "epen: res3:%d res4:%d res5:%d\n",
+ response[3], response[4], response[5]);
+ return false;
+ }
+ pageNo++;
+ }
+
+ return true;
+}
+
+static bool flash_marking(struct wacom_i2c *wac_i2c,
+ size_t data_size, bool bMarking, int iMpuID)
+{
+ const int MAX_CMD_SIZE = 12 + FLASH_BLOCK_SIZE + 2;
+ int rv, ECH;
+ unsigned char flash_data[FLASH_BLOCK_SIZE];
+ unsigned char buf[300];
+ unsigned char response[RSP_SIZE];
+ unsigned char sum;
+ int len;
+ unsigned int i, j;
+ unsigned char command[MAX_CMD_SIZE];
+
+ for (i = 0; i < FLASH_BLOCK_SIZE; i++)
+ flash_data[i] = 0xFF;
+
+ if (bMarking)
+ flash_data[56] = 0x00;
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x37;
+ buf[len++] = CMD_SET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 1 rv:%d\n", rv);
+ return false;
+ }
+
+ command[0] = 5;
+ command[1] = 0;
+ command[2] = 76;
+ command[3] = 0;
+ command[4] = BOOT_CMD_REPORT_ID;
+ command[5] = BOOT_WRITE_FLASH;
+ command[6] = ECH = 1;
+ command[7] = 0xC0;
+ command[8] = 0x1F;
+ command[9] = 0x01;
+ command[10] = 0x00;
+ command[11] = 8;
+
+ sum = 0;
+ for (j = 0; j < 12; j++)
+ sum += command[j];
+ command[MAX_CMD_SIZE - 2] = ~sum + 1;
+
+ sum = 0;
+ for (i = 12; i < (FLASH_BLOCK_SIZE + 12); i++) {
+ command[i] = flash_data[i - 12];
+ sum += flash_data[i - 12];
+ }
+ command[MAX_CMD_SIZE - 1] = ~sum + 1;
+
+ rv = wacom_i2c_send(wac_i2c, command, BOOT_CMD_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 2 rv:%d\n", rv);
+ return false;
+ }
+
+ usleep_range(10000, 10000);
+
+ len = 0;
+ buf[len++] = 4;
+ buf[len++] = 0;
+ buf[len++] = 0x38;
+ buf[len++] = CMD_GET_FEATURE;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 3 rv:%d\n", rv);
+ return false;
+ }
+
+ len = 0;
+ buf[len++] = 5;
+ buf[len++] = 0;
+
+ rv = wacom_i2c_send(wac_i2c, buf, len, WACOM_I2C_MODE_BOOT);
+ if (rv < 0) {
+ printk(KERN_DEBUG "epen: 4 rv:%d\n", rv);
+ return false;
+ }
+
+ printk(KERN_DEBUG "epen: confirming marking\n");
+ rv = wacom_i2c_recv(wac_i2c, response, BOOT_RSP_SIZE,
+ WACOM_I2C_MODE_BOOT);
+ if (rv < 0)
+ return false;
+
+ if ((response[3] != 1) || (response[4] != ECH)\
+ || (response[5] != ACK)) {
+ printk(KERN_DEBUG "epen: failing res3:%d res4:%d res5:%d\n",
+ response[3], response[4], response[5]);
+ return false;
+ }
+
+ return true;
+}
+
+int wacom_i2c_flash(struct wacom_i2c *wac_i2c)
+{
+ unsigned long max_address = 0;
+ unsigned long start_address = 0x4000;
+ int eraseBlock[50], eraseBlockNum;
+ bool bRet;
+ int iChecksum;
+ int iBLVer, iMpuType, iStatus;
+ bool bMarking;
+ int iRet;
+ unsigned long ulMaxRange;
+
+ if (Binary == NULL) {
+ printk(KERN_ERR"[E-PEN] Data is NULL. Exit.\n");
+ return -1;
+ }
+
+#ifdef WACOM_HAVE_FWE_PIN
+ if (wac_i2c->have_fwe_pin) {
+ wac_i2c->wac_pdata->compulsory_flash_mode(true);
+ /*Reset */
+ wac_i2c->wac_pdata->reset_platform_hw();
+ msleep(200);
+ printk(KERN_DEBUG "epen: Set FWE\n");
+ }
+#endif
+ wake_lock(&wac_i2c->wakelock);
+
+ printk(KERN_DEBUG "epen:start getting the boot loader version\n");
+ /*Obtain boot loader version */
+ iRet = GetBLVersion(wac_i2c, &iBLVer);
+ if (iRet != EXIT_OK) {
+ printk(KERN_DEBUG "epen:failed to get Boot Loader version\n");
+ goto fw_update_error;
+ }
+
+ printk(KERN_DEBUG "epen: start getting the MPU version\n");
+ /*Obtain MPU type: this can be manually done in user space */
+ iRet = GetMpuType(wac_i2c, &iMpuType);
+ if (iRet != EXIT_OK) {
+ printk(KERN_DEBUG "epen: failed to get MPU type\n");
+ goto fw_update_error;
+ }
+
+ /*Set start and end address and block numbers */
+ eraseBlockNum = 0;
+ start_address = 0x4000;
+ max_address = 0x12FFF;
+ eraseBlock[eraseBlockNum++] = 2;
+ eraseBlock[eraseBlockNum++] = 1;
+ eraseBlock[eraseBlockNum++] = 0;
+ eraseBlock[eraseBlockNum++] = 3;
+
+ printk(KERN_DEBUG "epen: obtaining the checksum\n");
+ /*Calculate checksum */
+ iChecksum = wacom_i2c_flash_chksum(wac_i2c, Binary, &max_address);
+ printk(KERN_DEBUG "epen: Checksum is :%d\n", iChecksum);
+
+ bRet = true;
+
+ printk(KERN_DEBUG "epen: setting the security unlock\n");
+ /*Unlock security */
+ iRet = SetSecurityUnlock(wac_i2c, &iStatus);
+ if (iRet != EXIT_OK) {
+ printk(KERN_DEBUG "epen: failed to set security unlock\n");
+ goto fw_update_error;
+ }
+
+ /*Set adress range */
+ ulMaxRange = max_address;
+ ulMaxRange -= start_address;
+ ulMaxRange >>= 6;
+ if (max_address > (ulMaxRange << 6))
+ ulMaxRange++;
+
+ printk(KERN_DEBUG "epen: connecting to Wacom Digitizer\n");
+ printk(KERN_DEBUG "epen: erasing the current firmware\n");
+ /*Erase the old program */
+ bRet = flash_erase(wac_i2c, true, eraseBlock, eraseBlockNum);
+ if (!bRet) {
+ printk(KERN_DEBUG "epen: failed to erase the user program\n");
+ iRet = EXIT_FAIL_ERASE;
+ goto fw_update_error;
+ }
+ printk(KERN_DEBUG "epen: erasing done\n");
+
+ max_address = 0x11FC0;
+
+ printk(KERN_DEBUG "epen: writing new firmware\n");
+ /*Write the new program */
+ bRet =
+ flash_write(wac_i2c, Binary, DATA_SIZE, start_address, &max_address,
+ iMpuType);
+ if (!bRet) {
+ printk(KERN_DEBUG "epen: failed to write firmware\n");
+ iRet = EXIT_FAIL_WRITE_FIRMWARE;
+ goto fw_update_error;
+ }
+
+ printk(KERN_DEBUG "epen: start marking\n");
+ /*Set mark in writing process */
+ bRet = flash_marking(wac_i2c, DATA_SIZE, true, iMpuType);
+ if (!bRet) {
+ printk(KERN_DEBUG "epen: failed to mark firmware\n");
+ iRet = EXIT_FAIL_WRITE_FIRMWARE;
+ goto fw_update_error;
+ }
+
+ /*Set the address for verify */
+ start_address = 0x4000;
+ max_address = 0x11FBF;
+
+ printk(KERN_DEBUG "epen: start the verification\n");
+ /*Verify the written program */
+ bRet =
+ flash_verify(wac_i2c, Binary, DATA_SIZE, start_address,
+ &max_address, iMpuType);
+ if (!bRet) {
+ printk(KERN_DEBUG "epen: failed to verify the firmware\n");
+ iRet = EXIT_FAIL_VERIFY_FIRMWARE;
+ goto fw_update_error;
+ }
+
+ printk(KERN_DEBUG "epen: checking the mark\n");
+ /*Set mark */
+ bRet = is_flash_marking(wac_i2c, DATA_SIZE, &bMarking, iMpuType);
+ if (!bRet) {
+ printk(KERN_DEBUG "epen: marking firmwrae failed\n");
+ iRet = EXIT_FAIL_WRITING_MARK_NOT_SET;
+ goto fw_update_error;
+ }
+
+ /*Enable */
+ printk(KERN_DEBUG "epen: closing the boot mode\n");
+ bRet = flash_end(wac_i2c);
+ if (!bRet) {
+ printk(KERN_DEBUG "epen: closing boot mode failed\n");
+ iRet = EXIT_FAIL_WRITING_MARK_NOT_SET;
+ goto fw_update_error;
+ }
+ iRet = EXIT_OK;
+ printk(KERN_DEBUG "epen: write and verify completed\n");
+
+fw_update_error:
+ wake_unlock(&wac_i2c->wakelock);
+
+#ifdef WACOM_HAVE_FWE_PIN
+ if (wac_i2c->have_fwe_pin) {
+ wac_i2c->wac_pdata->compulsory_flash_mode(false);
+ /*Reset */
+ wac_i2c->wac_pdata->reset_platform_hw();
+ msleep(200);
+ }
+#endif
+ return iRet;
+}
diff --git a/drivers/input/touchscreen/wacom/w9002_flash.h b/drivers/input/touchscreen/wacom/w9002_flash.h
new file mode 100644
index 0000000..a6d0e49
--- /dev/null
+++ b/drivers/input/touchscreen/wacom/w9002_flash.h
@@ -0,0 +1,211 @@
+/*
+ * w9002_flash.h
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "wacom_i2c_func.h"
+#include "wacom_i2c_firm.h"
+
+#ifndef _WACOM_I2C_FLASH_H
+#define _WACOM_I2C_FLASH_H
+
+#define WACOM_CMD_QUERY0 0x04
+#define WACOM_CMD_QUERY1 0x00
+#define WACOM_CMD_QUERY2 0x33
+#define WACOM_CMD_QUERY3 0x02
+#define WACOM_CMD_THROW0 0x05
+#define WACOM_CMD_THROW1 0x00
+#define WACOM_QUERY_SIZE 19
+#define WACOM_RETRY_CNT 100
+
+struct flash {
+ int BLen;
+ unsigned long size;
+ unsigned char *data;
+};
+
+#define FLASH_START0 'f'
+#define FLASH_START1 'l'
+#define FLASH_START2 'a'
+#define FLASH_START3 's'
+#define FLASH_START4 'h'
+#define FLASH_START5 '\r'
+#define FLASH_ACK 0x06
+
+#define pana_QUERY 0x11
+
+#define flash_END 0x80
+#define flash_VERIFY 0x81
+#define flash_WRITE 0x82
+#define flash_READ 0x83
+#define flash_ERASE 0x84
+#define flash_SET_INFO 0x85
+#define flash_END_TO_BOOT 0x87
+#define flash_BAUDRATE 0x88
+
+#define flash_QUERY 0xE0
+#define flash_BLVER 0xE1
+#define flash_UNITID 0xE2
+#define flash_GET_INFO 0xE3
+#define flash_FWVER 0xE4
+#define flash_MPU 0xE8
+
+#define pen_QUERY '*'
+
+#define V09 0
+#define V095 1
+
+#define HIDIIC_VERSION V095
+
+#define FLASH_BLOCK_SIZE 64
+
+#define ASCINT_ON 0x0
+#define ASCINT_OFF 0x1
+#define ASCINT_ERROR 0xFF
+
+/*#define WRITE 0*/
+#define VERIFY 1
+#define WRITEVERIFY 2
+#define ERASE 3
+#define GETVERSION 4
+
+#define USER_ADDRESS 0x56
+#define BOOT_ADDRESS 0x57
+
+#define CMD_GET_FEATURE 2
+#define CMD_SET_FEATURE 3
+
+#define ACK 0
+
+#define BOOT_CMD_SIZE 78
+#define BOOT_RSP_SIZE 6
+
+#define BOOT_CMD_REPORT_ID 7
+
+#define BOOT_ERASE_FLASH 0
+#define BOOT_WRITE_FLASH 1
+#define BOOT_VERIFY_FLASH 2
+#define BOOT_EXIT 3
+#define BOOT_BLVER 4
+#define BOOT_MPU 5
+#define BOOT_SECURITY_UNLOCK 6
+#define BOOT_QUERY 7
+
+#define QUERY_CMD 0x07
+#define QUERY_ECH 'D'
+#define QUERY_RSP 0x06
+
+#define BOOT_CMD 0x04
+#define BOOT_ECH 'D'
+
+#define MPU_CMD 0x05
+#define MPU_ECH 'D'
+
+#define SEC_CMD 0x06
+#define SEC_ECH 'D'
+#define SEC_RSP 0x00
+
+#define ERS_CMD 0x00
+#define ERS_ECH 'D'
+#define ERS_RSP 0x00
+
+#define MARK_CMD 0x02
+#define MARK_ECH 'D'
+#define MARK_RSP 0x00
+
+#define WRITE_CMD 0x01
+#define WRITE_ECH 'D'
+#define WRITE_RSP 0x00
+
+#define VERIFY_CMD 0x02
+#define VERIFY_ECH 'D'
+#define VERIFY_RSP 0x00
+
+#define CMD_SIZE (72+6)
+#define RSP_SIZE 6
+
+#define DATA_SIZE (65536 * 2)
+
+/*exit codes*/
+#define EXIT_OK (0)
+#define EXIT_REBOOT (1)
+#define EXIT_FAIL (2)
+#define EXIT_USAGE (3)
+#define EXIT_NO_SUCH_FILE (4)
+#define EXIT_NO_INTEL_HEX (5)
+#define EXIT_FAIL_OPEN_COM_PORT (6)
+#define EXIT_FAIL_ENTER_FLASH_MODE (7)
+#define EXIT_FAIL_FLASH_QUERY (8)
+#define EXIT_FAIL_BAUDRATE_CHANGE (9)
+#define EXIT_FAIL_WRITE_FIRMWARE (10)
+#define EXIT_FAIL_EXIT_FLASH_MODE (11)
+#define EXIT_CANCEL_UPDATE (12)
+#define EXIT_SUCCESS_UPDATE (13)
+#define EXIT_FAIL_HID2SERIAL (14)
+#define EXIT_FAIL_VERIFY_FIRMWARE (15)
+#define EXIT_FAIL_MAKE_WRITING_MARK (16)
+#define EXIT_FAIL_ERASE_WRITING_MARK (17)
+#define EXIT_FAIL_READ_WRITING_MARK (18)
+#define EXIT_EXIST_MARKING (19)
+#define EXIT_FAIL_MISMATCHING (20)
+#define EXIT_FAIL_ERASE (21)
+#define EXIT_FAIL_GET_BOOT_LOADER_VERSION (22)
+#define EXIT_FAIL_GET_MPU_TYPE (23)
+#define EXIT_MISMATCH_BOOTLOADER (24)
+#define EXIT_MISMATCH_MPUTYPE (25)
+#define EXIT_FAIL_ERASE_BOOT (26)
+#define EXIT_FAIL_WRITE_BOOTLOADER (27)
+#define EXIT_FAIL_SWAP_BOOT (28)
+#define EXIT_FAIL_WRITE_DATA (29)
+#define EXIT_FAIL_GET_FIRMWARE_VERSION (30)
+#define EXIT_FAIL_GET_UNIT_ID (31)
+#define EXIT_FAIL_SEND_STOP_COMMAND (32)
+#define EXIT_FAIL_SEND_QUERY_COMMAND (33)
+#define EXIT_NOT_FILE_FOR_535 (34)
+#define EXIT_NOT_FILE_FOR_514 (35)
+#define EXIT_NOT_FILE_FOR_503 (36)
+#define EXIT_MISMATCH_MPU_TYPE (37)
+#define EXIT_NOT_FILE_FOR_515 (38)
+#define EXIT_NOT_FILE_FOR_1024 (39)
+#define EXIT_FAIL_VERIFY_WRITING_MARK (40)
+#define EXIT_DEVICE_NOT_FOUND (41)
+#define EXIT_FAIL_WRITING_MARK_NOT_SET (42)
+
+/*For Report Descreptor of HID over I2C*/
+#define HID_USAGE_UNDEFINED 0x00
+#define HID_USAGE_PAGE 0x05
+#define HID_USAGE_PAGE_DIGITIZER 0x0d
+#define HID_USAGE_PAGE_DESKTOP 0x01
+#define HID_USAGE 0x09
+#define HID_USAGE_X 0x30
+#define HID_USAGE_Y 0x31
+#define HID_USAGE_X_TILT 0x3d
+#define HID_USAGE_Y_TILT 0x3e
+#define HID_USAGE_FINGER 0x22
+#define HID_USAGE_STYLUS 0x20
+#define HID_USAGE_TIP_PRESSURE 0x30
+#define HID_COLLECTION 0xc0
+
+#define I2C_REQ_GET_REPORT 0x01
+#define I2C_REQ_SET_REPORT 0x09
+
+#define WAC_HID_FEATURE_REPORT 0x03
+#define WAC_MSG_RETRIES 5
+
+extern int wacom_i2c_flash(struct wacom_i2c *wac_i2c);
+
+#endif /*_WACOM_I2C_FLASH_H*/
diff --git a/drivers/input/touchscreen/wacom/wacom_i2c.c b/drivers/input/touchscreen/wacom/wacom_i2c.c
index e0dd530..4a47709 100644
--- a/drivers/input/touchscreen/wacom/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom/wacom_i2c.c
@@ -25,7 +25,11 @@
#include <linux/uaccess.h>
#include <linux/firmware.h>
#include "wacom_i2c_func.h"
+#ifdef CONFIG_EPEN_WACOM_G9PL
+#include "w9002_flash.h"
+#else
#include "wacom_i2c_flash.h"
+#endif
#ifdef WACOM_IMPORT_FW_ALGO
#include "wacom_i2c_coord_tables.h"
#endif
@@ -151,13 +155,19 @@ int wacom_i2c_get_ums_data(struct wacom_i2c *wac_i2c, u8 **ums_data)
"[E-PEN] start, file path %s, size %ld Bytes\n",
WACOM_FW_PATH, fsize);
+#ifndef CONFIG_MACH_KONA
if (fsize != nSize) {
printk(KERN_ERR "[E-PEN] UMS firmware size is different\n");
ret = -EFBIG;
goto size_error;
}
+#endif
+#ifdef CONFIG_MACH_KONA
+ *ums_data = kmalloc(65536*2, GFP_KERNEL);
+#else
*ums_data = kmalloc(fsize, GFP_KERNEL);
+#endif
if (IS_ERR(*ums_data)) {
printk(KERN_ERR
"[E-PEN] %s, kmalloc failed\n", __func__);
@@ -165,6 +175,10 @@ int wacom_i2c_get_ums_data(struct wacom_i2c *wac_i2c, u8 **ums_data)
goto malloc_error;
}
+#ifdef CONFIG_MACH_KONA
+ memset((void *)*ums_data, 0xff, 65536*2);
+#endif
+
nread = vfs_read(fp, (char __user *)*ums_data,
fsize, &fp->f_pos);
printk(KERN_NOTICE "[E-PEN] nread %ld Bytes\n", nread);
@@ -223,12 +237,25 @@ int wacom_i2c_fw_update_UMS(struct wacom_i2c *wac_i2c)
return 0;
}
-#if defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_T0)
+#if defined(CONFIG_MACH_Q1_BD) || defined(CONFIG_MACH_T0)\
+ || defined(CONFIG_MACH_KONA)
int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c)
{
int ret;
int retry = 3;
const struct firmware *firm_data = NULL;
+
+#if defined(CONFIG_MACH_KONA)
+ u8 *flash_data;
+
+ flash_data = kmalloc(65536*2, GFP_KERNEL);
+ if (IS_ERR(flash_data)) {
+ printk(KERN_ERR
+ "[E-PEN] %s, kmalloc failed\n", __func__);
+ return -1;
+ }
+ memset((void *)flash_data, 0xff, 65536*2);
+#endif
firmware_updating_state = true;
@@ -242,8 +269,14 @@ int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c)
ret, retry);
continue;
}
+#if defined(CONFIG_MACH_KONA)
+ memcpy((void *)flash_data,
+ (const void *)firm_data->data,
+ firm_data->size);
+ wacom_i2c_set_firm_data((unsigned char *)flash_data);
+#else
wacom_i2c_set_firm_data((unsigned char *)firm_data->data);
-
+#endif
ret = wacom_i2c_flash(wac_i2c);
if (ret == 0) {
@@ -259,6 +292,10 @@ int wacom_i2c_firm_update(struct wacom_i2c *wac_i2c)
}
firmware_updating_state = false;
+
+#if defined(CONFIG_MACH_KONA)
+ kfree(flash_data);
+#endif
if (ret < 0)
return -1;
@@ -535,6 +572,14 @@ static void wacom_i2c_set_input_values(struct i2c_client *client,
/* __set_bit(BTN_STYLUS2, input_dev->keybit); */
/* __set_bit(ABS_MISC, input_dev->absbit); */
+
+ /*softkey*/
+#ifdef WACOM_USE_SOFTKEY
+ __set_bit(EV_LED, input_dev->evbit);
+ __set_bit(LED_MISC, input_dev->ledbit);
+ __set_bit(KEY_MENU, input_dev->keybit);
+ __set_bit(KEY_BACK, input_dev->keybit);
+#endif
}
static int wacom_check_emr_prox(struct wacom_g5_callbacks *cb)
@@ -1349,6 +1394,9 @@ static int wacom_i2c_probe(struct i2c_client *client,
/*Set switch type*/
wac_i2c->invert_pen_insert = wacom_i2c_invert_by_switch_type();
+#elif defined(CONFIG_MACH_KONA)
+ wac_i2c->wac_pdata->late_resume_platform_hw();
+ msleep(200);
#endif
#ifdef WACOM_PDCT_WORK_AROUND
wac_i2c->pen_pdct = PDCT_NOSIGNAL;
@@ -1447,7 +1495,7 @@ static int wacom_i2c_probe(struct i2c_client *client,
printk(KERN_ERR "[E-PEN] exynos_cpufreq_get_level Error\n");
#ifdef SEC_BUS_LOCK
wac_i2c->dvfs_lock_status = false;
-#if defined(CONFIG_MACH_P4NOTE)
+#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA)
wac_i2c->bus_dev = dev_get("exynos-busfreq");
#endif /* CONFIG_MACH_P4NOTE */
#endif /* SEC_BUS_LOCK */
diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_firm.c b/drivers/input/touchscreen/wacom/wacom_i2c_firm.c
index fddb8c9..f826f86 100644
--- a/drivers/input/touchscreen/wacom/wacom_i2c_firm.c
+++ b/drivers/input/touchscreen/wacom/wacom_i2c_firm.c
@@ -71,6 +71,13 @@ char Firmware_checksum[] = { 0x1F, 0x27, 0x85, 0x8B, 0xFB, };
const char B713X_checksum[] = { 0x1F, 0xB5, 0x84, 0x38, 0x34, };
/*checksum for 0x16*/
const char B660X_checksum[] = { 0x1F, 0x83, 0x88, 0xD4, 0x67, };
+#elif defined(CONFIG_MACH_KONA)
+const unsigned int Binary_nLength = 0xCBCB;
+const unsigned char Mpu_type = 0x00;
+unsigned int Firmware_version_of_file = 0x65D;
+unsigned char *firmware_name = "epen/W9002_B781.bin";
+
+char Firmware_checksum[] = { 0x1F, 0x72, 0xCD, 0x6E, 0xE3, };
#endif
void wacom_i2c_set_firm_data(unsigned char *Binary_new)
diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_flash.c b/drivers/input/touchscreen/wacom/wacom_i2c_flash.c
index 691e66c..cf92018 100644
--- a/drivers/input/touchscreen/wacom/wacom_i2c_flash.c
+++ b/drivers/input/touchscreen/wacom/wacom_i2c_flash.c
@@ -73,6 +73,28 @@ int wacom_i2c_flash_cmd(struct wacom_i2c *wac_i2c)
int ret, len, i;
u8 buf[10], flashq;
+
+#if defined(CONFIG_MACH_KONA)
+ buf[0] = 0x0d;
+ buf[1] = FLASH_START0;
+ buf[2] = FLASH_START1;
+ buf[3] = FLASH_START2;
+ buf[4] = FLASH_START3;
+ buf[5] = FLASH_START4;
+ buf[6] = FLASH_START5;
+ buf[7] = 0x0d;
+
+ printk(KERN_DEBUG "[E-PEN][jjals] w9002 running!!\n");
+
+ len = 8;
+ ret = i2c_master_send(wac_i2c->client, buf, len);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "Sending flash command failed\n");
+ return -1;
+ }
+#else
buf[0] = 0x0d;
buf[1] = FLASH_START0;
@@ -110,8 +132,7 @@ int wacom_i2c_flash_cmd(struct wacom_i2c *wac_i2c)
printk(KERN_DEBUG "[E-PEN]: flash send?:%d\n", ret);
msleep(270);
}
-
- wac_i2c->boot_mode = true;
+#endif
return 0;
}
@@ -174,6 +195,9 @@ int wacom_i2c_flash_enter(struct wacom_i2c *wac_i2c)
{
if (wacom_i2c_flash_query(wac_i2c, FLASH_QUERY, FLASH_ACK) == -1)
return ERR_NOT_FLASH;
+
+ wac_i2c->boot_mode = true;
+
return 0;
}
diff --git a/drivers/input/touchscreen/wacom/wacom_i2c_func.c b/drivers/input/touchscreen/wacom/wacom_i2c_func.c
index 18a7900..a981cbc 100644
--- a/drivers/input/touchscreen/wacom/wacom_i2c_func.c
+++ b/drivers/input/touchscreen/wacom/wacom_i2c_func.c
@@ -381,7 +381,8 @@ int wacom_i2c_query(struct wacom_i2c *wac_i2c)
#if defined(CONFIG_MACH_Q1_BD)\
|| defined(CONFIG_MACH_P4NOTE)\
- || defined(CONFIG_MACH_T0)
+ || defined(CONFIG_MACH_T0)\
+ || defined(CONFIG_MACH_KONA)
wac_feature->x_max = (u16) WACOM_MAX_COORD_X;
wac_feature->y_max = (u16) WACOM_MAX_COORD_Y;
#else
@@ -425,7 +426,7 @@ int wacom_i2c_query(struct wacom_i2c *wac_i2c)
}
wac_i2c->query_status = true;
-#if defined(CONFIG_MACH_P4NOTE)
+#if defined(CONFIG_MACH_P4NOTE) || defined(CONFIG_MACH_KONA)
wacom_checksum(wac_i2c);
#endif
@@ -797,6 +798,9 @@ static bool wacom_i2c_coord_range(s16 *x, s16 *y)
#if defined(CONFIG_MACH_T0)
if ((*x >= 0) && (*y >= 0) &&
(*x <= WACOM_POSX_MAX) && (*y <= WACOM_POSY_MAX - 50))
+#elif defined(CONFIG_MACH_KONA)
+ if ((*x >= WACOM_POSX_OFFSET) && (*y >= WACOM_POSX_OFFSET) &&
+ (*x <= WACOM_POSY_MAX) && (*y <= WACOM_POSX_MAX))
#else
if ((*x <= WACOM_POSX_MAX) && (*y <= WACOM_POSY_MAX))
#endif
@@ -805,6 +809,29 @@ static bool wacom_i2c_coord_range(s16 *x, s16 *y)
return false;
}
+#ifdef WACOM_USE_SOFTKEY
+static int keycode[] = {
+ KEY_MENU, KEY_BACK,
+};
+void wacom_i2c_softkey(struct wacom_i2c *wac_i2c, s16 key, s16 pressed)
+{
+ if (gpio_get_value(wac_i2c->wac_pdata->gpio_pendct) && pressed)
+ forced_release(wac_i2c);
+
+ input_report_key(wac_i2c->input_dev,
+ keycode[key], pressed);
+ input_sync(wac_i2c->input_dev);
+
+#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
+ printk(KERN_DEBUG "[E-PEN] keycode:%d pressed:%d\n",
+ keycode[key], pressed);
+#else
+ printk(KERN_DEBUG "[E-PEN] pressed:%d\n",
+ pressed);
+#endif
+}
+#endif
+
int wacom_i2c_coord(struct wacom_i2c *wac_i2c)
{
bool prox = false;
@@ -817,6 +844,9 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c)
u8 gain = 0;
u8 height = 0;
int aveStrength = 2;
+#ifdef WACOM_USE_SOFTKEY
+ static s16 softkey, pressed, keycode;
+#endif
#ifdef WACOM_IRQ_WORK_AROUND
cancel_delayed_work(&wac_i2c->pendct_dwork);
@@ -854,6 +884,15 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c)
pr_debug("[E-PEN] is in(%d)\n", wac_i2c->tool);
#endif
}
+#ifdef WACOM_USE_SOFTKEY
+ softkey = !!(data[5] & 0x80);
+ if (softkey) {
+ pressed = !!(data[5] & 0x40);
+ keycode = (data[5] & 0x30) >> 4;
+ wacom_i2c_softkey(wac_i2c, keycode, pressed);
+ return 0;
+ }
+#endif
prox = !!(data[0] & 0x10);
stylus = !!(data[0] & 0x20);
@@ -976,9 +1015,16 @@ int wacom_i2c_coord(struct wacom_i2c *wac_i2c)
wac_i2c->side_pressed = stylus;
}
#if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
- else
+ else {
printk(KERN_DEBUG "[E-PEN] raw data x=%d, y=%d\n",
x, y);
+#ifdef CONFIG_MACH_KONA
+ /* Pen should be released in the NOT AA area even if rdy value is 1. */
+ if (wac_i2c->pen_pressed || wac_i2c->side_pressed
+ || wac_i2c->pen_prox)
+ forced_release(wac_i2c);
+#endif
+ }
#endif
} else {