diff options
Diffstat (limited to 'drivers/input/touchscreen/wacom')
-rw-r--r-- | drivers/input/touchscreen/wacom/w9002_flash.c | 1253 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom/w9002_flash.h | 211 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom/wacom_i2c.c | 54 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom/wacom_i2c_firm.c | 7 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom/wacom_i2c_flash.c | 28 | ||||
-rw-r--r-- | drivers/input/touchscreen/wacom/wacom_i2c_func.c | 52 |
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 { |