summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/msg2138/mstar_drv_self_fw_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/msg2138/mstar_drv_self_fw_control.c')
-rw-r--r--drivers/input/touchscreen/msg2138/mstar_drv_self_fw_control.c3974
1 files changed, 3974 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/msg2138/mstar_drv_self_fw_control.c b/drivers/input/touchscreen/msg2138/mstar_drv_self_fw_control.c
new file mode 100644
index 00000000..dbe21439
--- /dev/null
+++ b/drivers/input/touchscreen/msg2138/mstar_drv_self_fw_control.c
@@ -0,0 +1,3974 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006-2012 MStar Semiconductor, Inc.
+// All rights reserved.
+//
+// Unless otherwise stipulated in writing, any and all information contained
+// herein regardless in any format shall remain the sole proprietary of
+// MStar Semiconductor Inc. and be kept in strict confidence
+// (??MStar Confidential Information??) by the recipient.
+// Any unauthorized act including without limitation unauthorized disclosure,
+// copying, use, reproduction, sale, distribution, modification, disassembling,
+// reverse engineering and compiling of the contents of MStar Confidential
+// Information is unlawful and strictly prohibited. MStar hereby reserves the
+// rights to any and all damages, losses, costs and expenses resulting therefrom.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *
+ * @file mstar_drv_self_fw_control.c
+ *
+ * @brief This file defines the interface of touch screen
+ *
+ * @version v2.2.0.0
+ *
+ */
+
+/*=============================================================*/
+// INCLUDE FILE
+/*=============================================================*/
+
+#include "mstar_drv_self_fw_control.h"
+#include "mstar_drv_utility_adaption.h"
+#include "mstar_drv_platform_porting_layer.h"
+
+/*=============================================================*/
+// EXTERN VARIABLE DECLARATION
+/*=============================================================*/
+static const int g_TpVirtualKeyDimLocal[3][4] = { {256,1000,70,70}, // virtualkey 1 MENU
+ {128,1000,70,70}, // virtualkey 4 HOME
+ {192,1000,70,70} }; // virtualkey 2 BACK
+
+struct point_node_t point_slot[MAX_FINGER_NUM*2];
+static int keycode;
+
+extern struct input_dev *g_InputDevice;
+
+extern u8 g_FwData[94][1024];
+extern u32 g_FwDataCount;
+
+extern struct mutex g_Mutex;
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+extern struct kobject *g_TouchKObj;
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+/*=============================================================*/
+// LOCAL VARIABLE DEFINITION
+/*=============================================================*/
+
+static u8 _gTpVendorCode[3] = {0};
+
+static u8 _gDwIicInfoData[1024];
+static u8 _gOneDimenFwData[MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE*1024+MSG22XX_FIRMWARE_INFO_BLOCK_SIZE] = {0}; // used for MSG22XX
+
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+/*
+ * Note.
+ * Please modify the name of the below .h depends on the vendor TP that you are using.
+ */
+static unsigned char msg2xxx_yyyy_update_bin[] = {
+};
+static unsigned char msg2xxx_xxxx_update_bin[] = {
+#include "msg2xxx_xxxx_update_bin.h"
+};
+
+static u32 _gUpdateRetryCount = UPDATE_FIRMWARE_RETRY_COUNT;
+static struct work_struct _gUpdateFirmwareBySwIdWork;
+static struct workqueue_struct *_gUpdateFirmwareBySwIdWorkQueue = NULL;
+
+static u32 _gIsUpdateInfoBlockFirst = 0;
+static u8 _gIsUpdateFirmware = 0x00;
+
+#endif //CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+static u16 _gGestureWakeupValue = 0;
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+
+
+/*=============================================================*/
+// GLOBAL VARIABLE DEFINITION
+/*=============================================================*/
+
+u8 g_ChipType = 0;
+u8 g_DemoModePacket[DEMO_MODE_PACKET_LENGTH] = {0};
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+FirmwareInfo_t g_FirmwareInfo;
+
+u8 *g_LogModePacket = NULL;
+u16 g_FirmwareMode = FIRMWARE_MODE_DEMO_MODE;
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+u8 *_gGestureWakeupPacket = NULL;
+
+u16 g_GestureWakeupMode = 0x0000;
+u8 g_GestureWakeupFlag = 0;
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+
+/*=============================================================*/
+// LOCAL FUNCTION DECLARATION
+/*=============================================================*/
+
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+static void _DrvFwCtrlUpdateFirmwareBySwIdDoWork(struct work_struct *pWork);
+#endif //CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+
+/*=============================================================*/
+// LOCAL FUNCTION DEFINITION
+/*=============================================================*/
+
+unsigned char tpd_check_sum(unsigned char *pval)
+{
+ int i, sum = 0;
+ for(i = 0; i < 7; i++)
+ sum += pval[i];
+ return (unsigned char)((-sum) & 0xFF);
+}
+
+static void _DrvFwCtrlEraseEmemC32(void)
+{
+ DBG("*** %s() ***\n", __func__);
+
+ /////////////////////////
+ //Erase all
+ /////////////////////////
+
+ // Enter gpio mode
+ RegSet16BitValue(0x161E, 0xBEAF);
+
+ // Before gpio mode, set the control pin as the orginal status
+ RegSet16BitValue(0x1608, 0x0000);
+ RegSetLByteValue(0x160E, 0x10);
+ mdelay(10);
+
+ // ptrim = 1, h'04[2]
+ RegSetLByteValue(0x1608, 0x04);
+ RegSetLByteValue(0x160E, 0x10);
+ mdelay(10);
+
+ // ptm = 6, h'04[12:14] = b'110
+ RegSetLByteValue(0x1609, 0x60);
+ RegSetLByteValue(0x160E, 0x10);
+
+ // pmasi = 1, h'04[6]
+ RegSetLByteValue(0x1608, 0x44);
+ // pce = 1, h'04[11]
+ RegSetLByteValue(0x1609, 0x68);
+ // perase = 1, h'04[7]
+ RegSetLByteValue(0x1608, 0xC4);
+ // pnvstr = 1, h'04[5]
+ RegSetLByteValue(0x1608, 0xE4);
+ // pwe = 1, h'04[9]
+ RegSetLByteValue(0x1609, 0x6A);
+ // trigger gpio load
+ RegSetLByteValue(0x160E, 0x10);
+}
+
+static void _DrvFwCtrlEraseEmemC33(EmemType_e eEmemType)
+{
+ DBG("*** %s() ***\n", __func__);
+
+ // Stop mcu
+ RegSet16BitValue(0x0FE6, 0x0001);
+
+ // Disable watchdog
+ RegSetLByteValue(0x3C60, 0x55);
+ RegSetLByteValue(0x3C61, 0xAA);
+
+ // Set PROGRAM password
+ RegSetLByteValue(0x161A, 0xBA);
+ RegSetLByteValue(0x161B, 0xAB);
+
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+
+ if (eEmemType == EMEM_ALL)
+ {
+ RegSetLByteValue(0x1608, 0x10); //mark
+ }
+
+ RegSetLByteValue(0x1618, 0x40);
+ mdelay(10);
+
+ RegSetLByteValue(0x1618, 0x80);
+
+ // erase trigger
+ if (eEmemType == EMEM_MAIN)
+ {
+ RegSetLByteValue(0x160E, 0x04); //erase main
+ }
+ else
+ {
+ RegSetLByteValue(0x160E, 0x08); //erase all block
+ }
+}
+
+static void _DrvFwCtrlMsg22xxGetTpVendorCode(u8 *pTpVendorCode)
+{
+ DBG("*** %s() ***\n", __func__);
+
+ if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ u16 nRegData1, nRegData2;
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(100);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ // RIU password
+ RegSet16BitValue(0x161A, 0xABBA);
+
+ // Clear pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ RegSet16BitValue(0x1600, 0xC1E9); // Set start address for tp vendor code on info block(Actually, start reading from 0xC1E8)
+
+ // Enable burst mode
+// RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01));
+
+ // Set pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x40));
+
+ RegSetLByteValue(0x160E, 0x01);
+
+ nRegData1 = RegGet16BitValue(0x1604);
+ nRegData2 = RegGet16BitValue(0x1606);
+
+ pTpVendorCode[0] = ((nRegData1 >> 8) & 0xFF);
+ pTpVendorCode[1] = (nRegData2 & 0xFF);
+ pTpVendorCode[2] = ((nRegData2 >> 8) & 0xFF);
+
+ DBG("pTpVendorCode[0] = 0x%x , %c \n", pTpVendorCode[0], pTpVendorCode[0]);
+ DBG("pTpVendorCode[1] = 0x%x , %c \n", pTpVendorCode[1], pTpVendorCode[1]);
+ DBG("pTpVendorCode[2] = 0x%x , %c \n", pTpVendorCode[2], pTpVendorCode[2]);
+
+ // Clear burst mode
+// RegSet16BitValue(0x160C, RegGet16BitValue(0x160C) & (~0x01));
+
+ RegSet16BitValue(0x1600, 0x0000);
+
+ // Clear RIU password
+ RegSet16BitValue(0x161A, 0x0000);
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ DrvPlatformLyrTouchDeviceResetHw();
+ mdelay(100);
+ }
+}
+
+static void _DrvFwCtrlMsg22xxEraseEmem(EmemType_e eEmemType)
+{
+ u32 i;
+ u16 nRegData = 0;
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+
+ DBG("Erase start\n");
+
+ // Stop mcu
+ RegSet16BitValue(0x0FE6, 0x0001);
+
+ // Disable watchdog
+ RegSetLByteValue(0x3C60, 0x55);
+ RegSetLByteValue(0x3C61, 0xAA);
+
+ // Set PROGRAM password
+ RegSetLByteValue(0x161A, 0xBA);
+ RegSetLByteValue(0x161B, 0xAB);
+
+ if (eEmemType == EMEM_ALL) // 48KB + 512Byte
+ {
+ DBG("Erase all block\n");
+
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+ mdelay(100);
+
+ // Chip erase
+ RegSet16BitValue(0x160E, BIT3);
+
+ DBG("Wait erase done flag\n");
+
+ do // Wait erase done flag
+ {
+ nRegData = RegGet16BitValue(0x1610); // Memory status
+ mdelay(50);
+ } while((nRegData & BIT1) != BIT1);
+ }
+ else if (eEmemType == EMEM_MAIN) // 48KB (32+8+8)
+ {
+ DBG("Erase main block\n");
+
+ for (i = 0; i < 3; i ++)
+ {
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+ mdelay(10);
+
+ if (i == 0)
+ {
+ RegSet16BitValue(0x1600, 0x0000);
+ }
+ else if (i == 1)
+ {
+ RegSet16BitValue(0x1600, 0x8000);
+ }
+ else if (i == 2)
+ {
+ RegSet16BitValue(0x1600, 0xA000);
+ }
+
+ // Sector erase
+ RegSet16BitValue(0x160E, (RegGet16BitValue(0x160E) | BIT2));
+
+ DBG("Wait erase done flag\n");
+
+ do // Wait erase done flag
+ {
+ nRegData = RegGet16BitValue(0x1610); // Memory status
+ mdelay(50);
+ } while((nRegData & BIT1) != BIT1);
+ }
+ }
+ else if (eEmemType == EMEM_INFO) // 512Byte
+ {
+ DBG("Erase info block\n");
+
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+ mdelay(10);
+
+ RegSet16BitValue(0x1600, 0xC000);
+
+ // Sector erase
+ RegSet16BitValue(0x160E, (RegGet16BitValue(0x160E) | BIT2));
+
+ DBG("Wait erase done flag\n");
+
+ do // Wait erase done flag
+ {
+ nRegData = RegGet16BitValue(0x1610); // Memory status
+ mdelay(50);
+ } while((nRegData & BIT1) != BIT1);
+ }
+
+ DBG("Erase end\n");
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+}
+
+static void _DrvFwCtrlMsg22xxProgramEmem(EmemType_e eEmemType) // For MSG22XX
+{
+ u32 i, j;
+ u32 nRemainSize = 0, nBlockSize = 0, nSize = 0, index = 0;
+ u16 nRegData;
+ u8 szDbBusTxData[1024] = {0};
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ u32 nSizePerWrite = 125;
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ u32 nSizePerWrite = 1021;
+#endif
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaAlloc();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+
+ // Hold reset pin before program
+ RegSetLByteValue(0x1E06, 0x00);
+
+ DBG("Program start\n");
+
+ RegSet16BitValue(0x161A, 0xABBA);
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ if (eEmemType == EMEM_MAIN)
+ {
+ DBG("Program main block\n");
+
+ RegSet16BitValue(0x1600, 0x0000); // Set start address of main block
+ nRemainSize = MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE * 1024; //48KB
+ index = 0;
+ }
+ else if (eEmemType == EMEM_INFO)
+ {
+ DBG("Program info block\n");
+
+ RegSet16BitValue(0x1600, 0xC000); // Set start address of info block
+ nRemainSize = MSG22XX_FIRMWARE_INFO_BLOCK_SIZE; //512Byte
+ index = MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE * 1024;
+ }
+ else
+ {
+ DBG("eEmemType = %d is not supported for program e-memory.\n", eEmemType);
+ return;
+ }
+
+ RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01)); // Enable burst mode
+
+ // Program start
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x16;
+ szDbBusTxData[2] = 0x02;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 3);
+
+ szDbBusTxData[0] = 0x20;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 1);
+
+ i = 0;
+
+ while (nRemainSize > 0)
+ {
+ if (nRemainSize > nSizePerWrite)
+ {
+ nBlockSize = nSizePerWrite;
+ }
+ else
+ {
+ nBlockSize = nRemainSize;
+ }
+
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x16;
+ szDbBusTxData[2] = 0x02;
+
+ nSize = 3;
+
+ for (j = 0; j < nBlockSize; j ++)
+ {
+ szDbBusTxData[3+j] = _gOneDimenFwData[index+(i*nSizePerWrite)+j];
+ nSize ++;
+ }
+ i ++;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], nSize);
+
+ nRemainSize = nRemainSize - nBlockSize;
+ }
+
+ // Program end
+ szDbBusTxData[0] = 0x21;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 1);
+
+ nRegData = RegGet16BitValue(0x160C);
+ RegSet16BitValue(0x160C, nRegData & (~0x01));
+
+ DBG("Wait write done flag\n");
+
+ // Polling 0x1610 is 0x0002
+ do
+ {
+ nRegData = RegGet16BitValue(0x1610);
+ nRegData = nRegData & BIT1;
+ mdelay(10);
+
+ } while (nRegData != BIT1); // Wait write done flag
+
+ DBG("Program end\n");
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaFree();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+}
+
+static u32 _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EmemType_e eEmemType) // For MSG22XX
+{
+ u16 nCrcDown = 0;
+ u32 nRetVal = 0;
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(100);
+
+ // RIU password
+ RegSet16BitValue(0x161A, 0xABBA);
+
+ // Set PCE high
+ RegSetLByteValue(0x1618, 0x40);
+
+ if (eEmemType == EMEM_MAIN)
+ {
+ // Set start address and end address for main block
+ RegSet16BitValue(0x1600, 0x0000);
+ RegSet16BitValue(0x1640, 0xBFF8);
+ }
+ else if (eEmemType == EMEM_INFO)
+ {
+ // Set start address and end address for info block
+ RegSet16BitValue(0x1600, 0xC000);
+ RegSet16BitValue(0x1640, 0xC1F8);
+ }
+
+ // CRC reset
+ RegSet16BitValue(0x164E, 0x0001);
+
+ RegSet16BitValue(0x164E, 0x0000);
+
+ // Trigger CRC check
+ RegSetLByteValue(0x160E, 0x20);
+ mdelay(10);
+
+ nCrcDown = RegGet16BitValue(0x164E);
+
+ while (nCrcDown != 2)
+ {
+ DBG("Wait CRC down\n");
+ mdelay(10);
+ nCrcDown = RegGet16BitValue(0x164E);
+ }
+
+ nRetVal = RegGet16BitValue(0x1652);
+ nRetVal = (nRetVal << 16) | RegGet16BitValue(0x1650);
+
+ DBG("Hardware CRC = 0x%x\n", nRetVal);
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ return nRetVal;
+}
+
+static void _DrvFwCtrlMsg22xxConvertFwDataTwoDimenToOneDimen(u8 szTwoDimenFwData[][1024], u8* pOneDimenFwData)
+{
+ u32 i, j;
+
+ DBG("*** %s() ***\n", __func__);
+
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ pOneDimenFwData[i*1024+j] = szTwoDimenFwData[i][j];
+ }
+ }
+ else // i == 48
+ {
+ for (j = 0; j < 512; j ++)
+ {
+ pOneDimenFwData[i*1024+j] = szTwoDimenFwData[i][j];
+ }
+ }
+ }
+}
+
+static s32 _DrvFwCtrlParsePacket(u8 *pPacket, u16 nLength, TouchInfo_t *pInfo)
+{
+ u8 nCheckSum = 0;
+ u32 nDeltaX = 0, nDeltaY = 0;
+ u32 nX = 0;
+ u32 nY = 0;
+#ifdef CONFIG_SWAP_X_Y
+ u32 nTempX;
+ u32 nTempY;
+#endif
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ u8 nCheckSumIndex = 0;
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+ DBG("*** %s() ***\n", __func__);
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ if (g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE)
+ {
+ nCheckSumIndex = 7;
+ }
+ else if (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE || g_FirmwareMode == FIRMWARE_MODE_RAW_DATA_MODE)
+ {
+ nCheckSumIndex = 31;
+ }
+
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+ if (g_GestureWakeupFlag == 1)
+ {
+ nCheckSumIndex = nLength-1;
+ }
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ nCheckSum = DrvCommonCalculateCheckSum(&pPacket[0], nCheckSumIndex);
+ DBG("check sum : [%x] == [%x]? \n", pPacket[nCheckSumIndex], nCheckSum);
+#else
+ nCheckSum = DrvCommonCalculateCheckSum(&pPacket[0], (nLength-1));
+ DBG("check ksum : [%x] == [%x]? \n", pPacket[nLength-1], nCheckSum);
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+ if (g_GestureWakeupFlag == 1)
+ {
+ u8 nWakeupMode = 0;
+ u8 bIsCorrectFormat = 0;
+
+ DBG("received raw data from touch panel as following:\n");
+ DBG("pPacket[0]=%x \n pPacket[1]=%x pPacket[2]=%x pPacket[3]=%x pPacket[4]=%x pPacket[5]=%x \n", \
+ pPacket[0], pPacket[1], pPacket[2], pPacket[3], pPacket[4], pPacket[5]);
+
+ if (g_ChipType == CHIP_TYPE_MSG22XX && pPacket[0] == 0xA7 && pPacket[1] == 0x00 && pPacket[2] == 0x06 && pPacket[3] == 0x50)
+ {
+ nWakeupMode = pPacket[4];
+ bIsCorrectFormat = 1;
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG21XXA && pPacket[0] == 0x52 && pPacket[1] == 0xFF && pPacket[2] == 0xFF && pPacket[3] == 0xFF && pPacket[4] == 0xFF && pPacket[6] == 0xFF)
+ {
+ nWakeupMode = pPacket[5];
+ bIsCorrectFormat = 1;
+ }
+
+ if (bIsCorrectFormat)
+ {
+ DBG("nWakeupMode = 0x%x\n", nWakeupMode);
+
+ switch (nWakeupMode)
+ {
+ case 0x58:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_DOUBLE_CLICK_FLAG;
+
+ DBG("Light up screen by DOUBLE_CLICK gesture wakeup.\n");
+
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x60:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_UP_DIRECT_FLAG;
+
+ DBG("Light up screen by UP_DIRECT gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_UP, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_UP, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x61:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_DOWN_DIRECT_FLAG;
+
+ DBG("Light up screen by DOWN_DIRECT gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_DOWN, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_DOWN, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x62:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_LEFT_DIRECT_FLAG;
+
+ DBG("Light up screen by LEFT_DIRECT gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_LEFT, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_LEFT, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x63:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_RIGHT_DIRECT_FLAG;
+
+ DBG("Light up screen by RIGHT_DIRECT gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_RIGHT, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_RIGHT, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x64:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_m_CHARACTER_FLAG;
+
+ DBG("Light up screen by m_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_M, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_M, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x65:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_W_CHARACTER_FLAG;
+
+ DBG("Light up screen by W_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_W, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_W, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x66:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_C_CHARACTER_FLAG;
+
+ DBG("Light up screen by C_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_C, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_C, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x67:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_e_CHARACTER_FLAG;
+
+ DBG("Light up screen by e_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_E, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_E, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x68:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_V_CHARACTER_FLAG;
+
+ DBG("Light up screen by V_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_V, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_V, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x69:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_O_CHARACTER_FLAG;
+
+ DBG("Light up screen by O_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_O, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_O, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x6A:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_S_CHARACTER_FLAG;
+
+ DBG("Light up screen by S_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_S, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_S, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ case 0x6B:
+ _gGestureWakeupValue = GESTURE_WAKEUP_MODE_Z_CHARACTER_FLAG;
+
+ DBG("Light up screen by Z_CHARACTER gesture wakeup.\n");
+
+// input_report_key(g_InputDevice, KEY_Z, 1);
+ input_report_key(g_InputDevice, KEY_POWER, 1);
+ input_sync(g_InputDevice);
+// input_report_key(g_InputDevice, KEY_Z, 0);
+ input_report_key(g_InputDevice, KEY_POWER, 0);
+ input_sync(g_InputDevice);
+ break;
+ default:
+ _gGestureWakeupValue = 0;
+ break;
+ }
+
+ DBG("_gGestureWakeupValue = 0x%x\n", _gGestureWakeupValue);
+ }
+ else
+ {
+ DBG("gesture wakeup packet format is incorrect.\n");
+ }
+
+ return -1;
+ }
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+
+ DBG("received raw data from touch panel as following:\n");
+ DBG("pPacket[0]=%x \n pPacket[1]=%x pPacket[2]=%x pPacket[3]=%x pPacket[4]=%x \n pPacket[5]=%x pPacket[6]=%x pPacket[7]=%x \n", \
+ pPacket[0], pPacket[1], pPacket[2], pPacket[3], pPacket[4], pPacket[5], pPacket[6], pPacket[7]);
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ if ((pPacket[nCheckSumIndex] == nCheckSum) && (pPacket[0] == 0x52)) // check the checksum of packet
+#else
+ if ((pPacket[nLength-1] == nCheckSum) && (pPacket[0] == 0x52)) // check the checksum of packet
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ {
+ nX = (((pPacket[1] & 0xF0) << 4) | pPacket[2]); // parse the packet to coordinate
+ nY = (((pPacket[1] & 0x0F) << 8) | pPacket[3]);
+
+ nDeltaX = (((pPacket[4] & 0xF0) << 4) | pPacket[5]);
+ nDeltaY = (((pPacket[4] & 0x0F) << 8) | pPacket[6]);
+
+ DBG("[x,y]=[%d,%d]\n", nX, nY);
+ DBG("[delta_x,delta_y]=[%d,%d]\n", nDeltaX, nDeltaY);
+
+#ifdef CONFIG_SWAP_X_Y
+ nTempY = nX;
+ nTempX = nY;
+ nX = nTempX;
+ nY = nTempY;
+
+ nTempY = nDeltaX;
+ nTempX = nDeltaY;
+ nDeltaX = nTempX;
+ nDeltaY = nTempY;
+#endif
+
+#ifdef CONFIG_REVERSE_X
+ nX = 2047 - nX;
+ nDeltaX = 4095 - nDeltaX;
+#endif
+
+#ifdef CONFIG_REVERSE_Y
+ nY = 2047 - nY;
+ nDeltaY = 4095 - nDeltaY;
+#endif
+
+ /*
+ * pPacket[0]:id, pPacket[1]~pPacket[3]:the first point abs, pPacket[4]~pPacket[6]:the relative distance between the first point abs and the second point abs
+ * when pPacket[1]~pPacket[4], pPacket[6] is 0xFF, keyevent, pPacket[5] to judge which key press.
+ * pPacket[1]~pPacket[6] all are 0xFF, release touch
+ */
+ if ((pPacket[1] == 0xFF) && (pPacket[2] == 0xFF) && (pPacket[3] == 0xFF) && (pPacket[4] == 0xFF) && (pPacket[6] == 0xFF))
+ {
+ pInfo->tPoint[0].nX = 0; // final X coordinate
+ pInfo->tPoint[0].nY = 0; // final Y coordinate
+
+ if ((pPacket[5] != 0x00) && (pPacket[5] != 0xFF)) /* pPacket[5] is key value */
+ { /* 0x00 is key up, 0xff is touch screen up */
+ DBG("touch key down pPacket[5]=%d\n", pPacket[5]);
+ pInfo->nFingerNum = 1;
+ pInfo->nTouchKeyCode = pPacket[5];
+ pInfo->nTouchKeyMode = 1;
+
+#if 1
+ pInfo->nFingerNum = 1;
+ pInfo->nTouchKeyCode = 0;
+ pInfo->nTouchKeyMode = 0;
+
+ if (pPacket[5] == 1) // TOUCH_KEY_MENU
+ {
+ pInfo->tPoint[0].nX = g_TpVirtualKeyDimLocal[0][0];
+ pInfo->tPoint[0].nY = g_TpVirtualKeyDimLocal[0][1];
+ }
+ else if (pPacket[5] == 2) // TOUCH_KEY_BACK
+ {
+ pInfo->tPoint[0].nX = g_TpVirtualKeyDimLocal[2][0];
+ pInfo->tPoint[0].nY = g_TpVirtualKeyDimLocal[2][1];
+ }
+ else if (pPacket[5] == 4) // TOUCH_KEY_HOME
+ {
+ pInfo->tPoint[0].nX = g_TpVirtualKeyDimLocal[1][0];
+ pInfo->tPoint[0].nY = g_TpVirtualKeyDimLocal[1][1];
+ }
+ else
+ {
+ DBG("multi-key is pressed.\n");
+ return -1;
+ }
+#endif //CONFIG_ENABLE_REPORT_KEY_WITH_COORDINATE
+ }
+ else
+ { /* key up or touch up */
+ DBG("touch end\n");
+ pInfo->nFingerNum = 0; //touch end
+ pInfo->nTouchKeyCode = 0;
+ pInfo->nTouchKeyMode = 0;
+ }
+ }
+ else
+ {
+ pInfo->nTouchKeyMode = 0; //Touch on screen...
+
+// if ((nDeltaX == 0) && (nDeltaY == 0))
+ if(
+#ifdef CONFIG_REVERSE_X
+ (nDeltaX == 4095)
+#else
+ (nDeltaX == 0)
+#endif
+ &&
+#ifdef CONFIG_REVERSE_Y
+ (nDeltaY == 4095)
+#else
+ (nDeltaY == 0)
+#endif
+ )
+ { /* one touch point */
+ pInfo->nFingerNum = 1; // one touch
+ pInfo->tPoint[0].nX = (nX * TOUCH_SCREEN_X_MAX) / TPD_WIDTH;
+ pInfo->tPoint[0].nY = (nY * TOUCH_SCREEN_Y_MAX) / TPD_HEIGHT;
+ DBG("[%s]: [x,y]=[%d,%d]\n", __func__, nX, nY);
+ DBG("[%s]: point[x,y]=[%d,%d]\n", __func__, pInfo->tPoint[0].nX, pInfo->tPoint[0].nY);
+ }
+ else
+ { /* two touch points */
+ u32 nX2, nY2;
+
+ pInfo->nFingerNum = 2; // two touch
+ /* Finger 1 */
+ pInfo->tPoint[0].nX = (nX * TOUCH_SCREEN_X_MAX) / TPD_WIDTH;
+ pInfo->tPoint[0].nY = (nY * TOUCH_SCREEN_Y_MAX) / TPD_HEIGHT;
+ DBG("[%s]: point1[x,y]=[%d,%d]\n", __func__, pInfo->tPoint[0].nX, pInfo->tPoint[0].nY);
+ /* Finger 2 */
+ if (nDeltaX > 2048) // transform the unsigned value to signed value
+ {
+ nDeltaX -= 4096;
+ }
+
+ if (nDeltaY > 2048)
+ {
+ nDeltaY -= 4096;
+ }
+
+ nX2 = (u32)(nX + nDeltaX);
+ nY2 = (u32)(nY + nDeltaY);
+
+ pInfo->tPoint[1].nX = (nX2 * TOUCH_SCREEN_X_MAX) / TPD_WIDTH;
+ pInfo->tPoint[1].nY = (nY2 * TOUCH_SCREEN_Y_MAX) / TPD_HEIGHT;
+ DBG("[%s]: point2[x,y]=[%d,%d]\n", __func__, pInfo->tPoint[1].nX, pInfo->tPoint[1].nY);
+ }
+ }
+ }
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ else if (pPacket[nCheckSumIndex] == nCheckSum && pPacket[0] == 0x62)
+ {
+ nX = ((pPacket[1] << 8) | pPacket[2]); // Position_X
+ nY = ((pPacket[3] << 8) | pPacket[4]); // Position_Y
+
+ nDeltaX = ((pPacket[13] << 8) | pPacket[14]); // Distance_X
+ nDeltaY = ((pPacket[15] << 8) | pPacket[16]); // Distance_Y
+
+ DBG("[x,y]=[%d,%d]\n", nX, nY);
+ DBG("[delta_x,delta_y]=[%d,%d]\n", nDeltaX, nDeltaY);
+
+#ifdef CONFIG_SWAP_X_Y
+ nTempY = nX;
+ nTempX = nY;
+ nX = nTempX;
+ nY = nTempY;
+
+ nTempY = nDeltaX;
+ nTempX = nDeltaY;
+ nDeltaX = nTempX;
+ nDeltaY = nTempY;
+#endif
+
+#ifdef CONFIG_REVERSE_X
+ nX = 2047 - nX;
+ nDeltaX = 4095 - nDeltaX;
+#endif
+
+#ifdef CONFIG_REVERSE_Y
+ nY = 2047 - nY;
+ nDeltaY = 4095 - nDeltaY;
+#endif
+
+ /*
+ * pPacket[0]:id, pPacket[1]~pPacket[4]:the first point abs, pPacket[13]~pPacket[16]:the relative distance between the first point abs and the second point abs
+ * when pPacket[1]~pPacket[7] is 0xFF, keyevent, pPacket[8] to judge which key press.
+ * pPacket[1]~pPacket[8] all are 0xFF, release touch
+ */
+ if ((pPacket[1] == 0xFF) && (pPacket[2] == 0xFF) && (pPacket[3] == 0xFF) && (pPacket[4] == 0xFF) && (pPacket[5] == 0xFF) && (pPacket[6] == 0xFF) && (pPacket[7] == 0xFF))
+ {
+ pInfo->tPoint[0].nX = 0; // final X coordinate
+ pInfo->tPoint[0].nY = 0; // final Y coordinate
+
+ if ((pPacket[8] != 0x00) && (pPacket[8] != 0xFF)) /* pPacket[8] is key value */
+ { /* 0x00 is key up, 0xff is touch screen up */
+ DBG("touch key down pPacket[8]=%d\n", pPacket[8]);
+ pInfo->nFingerNum = 1;
+ pInfo->nTouchKeyCode = pPacket[8];
+ pInfo->nTouchKeyMode = 1;
+
+#if 1
+ pInfo->nFingerNum = 1;
+ pInfo->nTouchKeyCode = 0;
+ pInfo->nTouchKeyMode = 0;
+
+ if (pPacket[8] == 1) // TOUCH_KEY_MENU
+ {
+ pInfo->tPoint[0].nX = g_TpVirtualKeyDimLocal[0][0];
+ pInfo->tPoint[0].nY = g_TpVirtualKeyDimLocal[0][1];
+ }
+ else if (pPacket[8] == 2) // TOUCH_KEY_BACK
+ {
+ pInfo->tPoint[0].nX = g_TpVirtualKeyDimLocal[2][0];
+ pInfo->tPoint[0].nY = g_TpVirtualKeyDimLocal[2][1];
+ }
+ else if (pPacket[8] == 4) // TOUCH_KEY_HOME
+ {
+ pInfo->tPoint[0].nX = g_TpVirtualKeyDimLocal[1][0];
+ pInfo->tPoint[0].nY = g_TpVirtualKeyDimLocal[1][1];
+ }
+ else
+ {
+ DBG("multi-key is pressed.\n");
+ return -1;
+ }
+#endif //CONFIG_ENABLE_REPORT_KEY_WITH_COORDINATE
+ }
+ else
+ { /* key up or touch up */
+ DBG("touch end\n");
+ pInfo->nFingerNum = 0; //touch end
+ pInfo->nTouchKeyCode = 0;
+ pInfo->nTouchKeyMode = 0;
+ }
+ }
+ else
+ {
+ pInfo->nTouchKeyMode = 0; //Touch on screen...
+
+// if ((nDeltaX == 0) && (nDeltaY == 0))
+ if (
+#ifdef CONFIG_REVERSE_X
+ (nDeltaX == 4095)
+#else
+ (nDeltaX == 0)
+#endif
+ &&
+#ifdef CONFIG_REVERSE_Y
+ (nDeltaY == 4095)
+#else
+ (nDeltaY == 0)
+#endif
+ )
+ { /* one touch point */
+ pInfo->nFingerNum = 1; // one touch
+ pInfo->tPoint[0].nX = (nX * TOUCH_SCREEN_X_MAX) / TPD_WIDTH;
+ pInfo->tPoint[0].nY = (nY * TOUCH_SCREEN_Y_MAX) / TPD_HEIGHT;
+ DBG("[%s]: [x,y]=[%d,%d]\n", __func__, nX, nY);
+ DBG("[%s]: point[x,y]=[%d,%d]\n", __func__, pInfo->tPoint[0].nX, pInfo->tPoint[0].nY);
+ }
+ else
+ { /* two touch points */
+ u32 nX2, nY2;
+
+ pInfo->nFingerNum = 2; // two touch
+ /* Finger 1 */
+ pInfo->tPoint[0].nX = (nX * TOUCH_SCREEN_X_MAX) / TPD_WIDTH;
+ pInfo->tPoint[0].nY = (nY * TOUCH_SCREEN_Y_MAX) / TPD_HEIGHT;
+ DBG("[%s]: point1[x,y]=[%d,%d]\n", __func__, pInfo->tPoint[0].nX, pInfo->tPoint[0].nY);
+ /* Finger 2 */
+ if (nDeltaX > 2048) // transform the unsigned value to signed value
+ {
+ nDeltaX -= 4096;
+ }
+
+ if (nDeltaY > 2048)
+ {
+ nDeltaY -= 4096;
+ }
+
+ nX2 = (u32)(nX + nDeltaX);
+ nY2 = (u32)(nY + nDeltaY);
+
+ pInfo->tPoint[1].nX = (nX2 * TOUCH_SCREEN_X_MAX) / TPD_WIDTH;
+ pInfo->tPoint[1].nY = (nY2 * TOUCH_SCREEN_Y_MAX) / TPD_HEIGHT;
+ DBG("[%s]: point2[x,y]=[%d,%d]\n", __func__, pInfo->tPoint[1].nX, pInfo->tPoint[1].nY);
+ }
+
+ // Notify android application to retrieve log data mode packet from device driver by sysfs.
+ if (g_TouchKObj != NULL)
+ {
+ char *pEnvp[2];
+ s32 nRetVal = 0;
+
+ pEnvp[0] = "STATUS=GET_PACKET";
+ pEnvp[1] = NULL;
+
+ nRetVal = kobject_uevent_env(g_TouchKObj, KOBJ_CHANGE, pEnvp);
+ DBG("kobject_uevent_env() nRetVal = %d\n", nRetVal);
+ }
+ }
+ }
+ else
+ {
+ if (pPacket[nCheckSumIndex] != nCheckSum)
+ {
+ DBG("WRONG CHECKSUM\n");
+ return -1;
+ }
+
+ if (g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE && pPacket[0] != 0x52)
+ {
+ DBG("WRONG DEMO MODE HEADER\n");
+ return -1;
+ }
+ else if (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE && pPacket[0] != 0x62)
+ {
+ DBG("WRONG DEBUG MODE HEADER\n");
+ return -1;
+ }
+ else if (g_FirmwareMode == FIRMWARE_MODE_RAW_DATA_MODE && pPacket[0] != 0x62)
+ {
+ DBG("WRONG RAW DATA MODE HEADER\n");
+ return -1;
+ }
+ }
+#else
+ else
+ {
+ DBG("pPacket[0]=0x%x, pPacket[7]=0x%x, nCheckSum=0x%x\n", pPacket[0], pPacket[7], nCheckSum);
+
+ if (pPacket[nLength-1] != nCheckSum)
+ {
+ DBG("WRONG CHECKSUM\n");
+ return -1;
+ }
+
+ if (pPacket[0] != 0x52)
+ {
+ DBG("WRONG DEMO MODE HEADER\n");
+ return -1;
+ }
+ }
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------//
+
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+
+static void _DrvFwCtrlStoreFirmwareData(u8 *pBuf, u32 nSize)
+{
+ u32 nCount = nSize / 1024;
+ u32 i;
+
+ DBG("*** %s() ***\n", __func__);
+
+ if (nCount > 0) // nSize >= 1024
+ {
+ for (i = 0; i < nCount; i ++)
+ {
+ memcpy(g_FwData[g_FwDataCount], pBuf+(i*1024), 1024);
+
+ g_FwDataCount ++;
+ }
+ }
+ else // nSize < 1024
+ {
+ if (nSize > 0)
+ {
+ memcpy(g_FwData[g_FwDataCount], pBuf, nSize);
+
+ g_FwDataCount ++;
+ }
+ }
+
+ DBG("*** g_FwDataCount = %d ***\n", g_FwDataCount);
+
+ if (pBuf != NULL)
+ {
+ DBG("*** buf[0] = %c ***\n", pBuf[0]);
+ }
+}
+
+//-------------------------Start of SW ID for MSG22XX----------------------------//
+
+static u32 _DrvFwCtrlMsg22xxRetrieveFirmwareCrcFromEFlash(EmemType_e eEmemType) // For MSG22XX
+{
+ u32 nRetVal = 0;
+ u16 nRegData1 = 0, nRegData2 = 0;
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(100);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ // RIU password
+ RegSet16BitValue(0x161A, 0xABBA);
+
+ // Clear pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ if (eEmemType == EMEM_MAIN) // Read main block CRC(48KB-4) from main block
+ {
+ RegSet16BitValue(0x1600, 0xBFFC); // Set start address for main block CRC
+ }
+ else if (eEmemType == EMEM_INFO) // Read info block CRC(512Byte-4) from info block
+ {
+ RegSet16BitValue(0x1600, 0xC1FC); // Set start address for info block CRC
+ }
+
+ // Enable burst mode
+ RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01));
+
+ // Set pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x40));
+
+ RegSetLByteValue(0x160E, 0x01);
+
+ nRegData1 = RegGet16BitValue(0x1604);
+ nRegData2 = RegGet16BitValue(0x1606);
+
+ nRetVal = ((nRegData2 >> 8) & 0xFF) << 24;
+ nRetVal |= (nRegData2 & 0xFF) << 16;
+ nRetVal |= ((nRegData1 >> 8) & 0xFF) << 8;
+ nRetVal |= (nRegData1 & 0xFF);
+
+ DBG("CRC = 0x%x\n", nRetVal);
+
+ // Clear burst mode
+ RegSet16BitValue(0x160C, RegGet16BitValue(0x160C) & (~0x01));
+
+ RegSet16BitValue(0x1600, 0x0000);
+
+ // Clear RIU password
+ RegSet16BitValue(0x161A, 0x0000);
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ return nRetVal;
+}
+
+static u32 _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(u8 szTmpBuf[], EmemType_e eEmemType) // For MSG22XX
+{
+ u32 nRetVal = 0;
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+ if (szTmpBuf != NULL)
+ {
+ if (eEmemType == EMEM_MAIN) // Read main block CRC(48KB-4) from bin file
+ {
+ nRetVal = szTmpBuf[0xBFFF] << 24;
+ nRetVal |= szTmpBuf[0xBFFE] << 16;
+ nRetVal |= szTmpBuf[0xBFFD] << 8;
+ nRetVal |= szTmpBuf[0xBFFC];
+ }
+ else if (eEmemType == EMEM_INFO) // Read info block CRC(512Byte-4) from bin file
+ {
+ nRetVal = szTmpBuf[0xC1FF] << 24;
+ nRetVal |= szTmpBuf[0xC1FE] << 16;
+ nRetVal |= szTmpBuf[0xC1FD] << 8;
+ nRetVal |= szTmpBuf[0xC1FC];
+ }
+ }
+
+ return nRetVal;
+}
+
+static u16 _DrvFwCtrlMsg22xxGetSwId(EmemType_e eEmemType) // For MSG22XX
+{
+ u16 nRetVal = 0;
+ u16 nRegData1 = 0;
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(100);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ // RIU password
+ RegSet16BitValue(0x161A, 0xABBA);
+
+ // Clear pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ if (eEmemType == EMEM_MAIN) // Read SW ID from main block
+ {
+ RegSet16BitValue(0x1600, 0xBFF4); // Set start address for main block SW ID
+ }
+ else if (eEmemType == EMEM_INFO) // Read SW ID from info block
+ {
+ RegSet16BitValue(0x1600, 0xC1EC); // Set start address for info block SW ID
+ }
+
+ /*
+ Ex. SW ID in Main Block :
+ Major low byte at address 0xBFF4
+ Major high byte at address 0xBFF5
+
+ SW ID in Info Block :
+ Major low byte at address 0xC1EC
+ Major high byte at address 0xC1ED
+ */
+
+ // Enable burst mode
+// RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01));
+
+ // Set pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x40));
+
+ RegSetLByteValue(0x160E, 0x01);
+
+ nRegData1 = RegGet16BitValue(0x1604);
+// nRegData2 = RegGet16BitValue(0x1606);
+
+ nRetVal = ((nRegData1 >> 8) & 0xFF) << 8;
+ nRetVal |= (nRegData1 & 0xFF);
+
+ // Clear burst mode
+// RegSet16BitValue(0x160C, RegGet16BitValue(0x160C) & (~0x01));
+
+ RegSet16BitValue(0x1600, 0x0000);
+
+ // Clear RIU password
+ RegSet16BitValue(0x161A, 0x0000);
+
+ DBG("SW ID = 0x%x\n", nRetVal);
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ return nRetVal;
+}
+
+static s32 _DrvFwCtrlMsg22xxUpdateFirmwareBySwId(void) // For MSG22XX
+{
+ s32 nRetVal = -1;
+ u32 nCrcInfoA = 0, nCrcInfoB = 0, nCrcMainA = 0, nCrcMainB = 0;
+
+ DBG("*** %s() ***\n", __func__);
+
+ DBG("_gIsUpdateInfoBlockFirst = %d, _gIsUpdateFirmware = 0x%x\n", _gIsUpdateInfoBlockFirst, _gIsUpdateFirmware);
+
+ _DrvFwCtrlMsg22xxConvertFwDataTwoDimenToOneDimen(g_FwData, _gOneDimenFwData);
+
+ if (_gIsUpdateInfoBlockFirst == 1)
+ {
+ if ((_gIsUpdateFirmware & 0x10) == 0x10)
+ {
+ _DrvFwCtrlMsg22xxEraseEmem(EMEM_INFO);
+ _DrvFwCtrlMsg22xxProgramEmem(EMEM_INFO);
+
+ nCrcInfoA = _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(_gOneDimenFwData, EMEM_INFO);
+ nCrcInfoB = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_INFO);
+
+ DBG("nCrcInfoA = 0x%x, nCrcInfoB = 0x%x\n", nCrcInfoA, nCrcInfoB);
+
+ if (nCrcInfoA == nCrcInfoB)
+ {
+ _DrvFwCtrlMsg22xxEraseEmem(EMEM_MAIN);
+ _DrvFwCtrlMsg22xxProgramEmem(EMEM_MAIN);
+
+ nCrcMainA = _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(_gOneDimenFwData, EMEM_MAIN);
+ nCrcMainB = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_MAIN);
+
+ DBG("nCrcMainA = 0x%x, nCrcMainB = 0x%x\n", nCrcMainA, nCrcMainB);
+
+ if (nCrcMainA == nCrcMainB)
+ {
+ _gIsUpdateFirmware = 0x00;
+ nRetVal = 0;
+ }
+ else
+ {
+ _gIsUpdateFirmware = 0x01;
+ }
+ }
+ else
+ {
+ _gIsUpdateFirmware = 0x11;
+ }
+ }
+ else if ((_gIsUpdateFirmware & 0x01) == 0x01)
+ {
+ _DrvFwCtrlMsg22xxEraseEmem(EMEM_MAIN);
+ _DrvFwCtrlMsg22xxProgramEmem(EMEM_MAIN);
+
+ nCrcMainA = _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(_gOneDimenFwData, EMEM_MAIN);
+ nCrcMainB = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_MAIN);
+
+ DBG("nCrcMainA=0x%x, nCrcMainB=0x%x\n", nCrcMainA, nCrcMainB);
+
+ if (nCrcMainA == nCrcMainB)
+ {
+ _gIsUpdateFirmware = 0x00;
+ nRetVal = 0;
+ }
+ else
+ {
+ _gIsUpdateFirmware = 0x01;
+ }
+ }
+ }
+ else //_gIsUpdateInfoBlockFirst == 0
+ {
+ if ((_gIsUpdateFirmware & 0x10) == 0x10)
+ {
+ _DrvFwCtrlMsg22xxEraseEmem(EMEM_MAIN);
+ _DrvFwCtrlMsg22xxProgramEmem(EMEM_MAIN);
+
+ nCrcMainA = _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(_gOneDimenFwData, EMEM_MAIN);
+ nCrcMainB = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_MAIN);
+
+ DBG("nCrcMainA=0x%x, nCrcMainB=0x%x\n", nCrcMainA, nCrcMainB);
+
+ if (nCrcMainA == nCrcMainB)
+ {
+ _DrvFwCtrlMsg22xxEraseEmem(EMEM_INFO);
+ _DrvFwCtrlMsg22xxProgramEmem(EMEM_INFO);
+
+ nCrcInfoA = _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(_gOneDimenFwData, EMEM_INFO);
+ nCrcInfoB = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_INFO);
+
+ DBG("nCrcInfoA=0x%x, nCrcInfoB=0x%x\n", nCrcInfoA, nCrcInfoB);
+
+ if (nCrcInfoA == nCrcInfoB)
+ {
+ _gIsUpdateFirmware = 0x00;
+ nRetVal = 0;
+ }
+ else
+ {
+ _gIsUpdateFirmware = 0x01;
+ }
+ }
+ else
+ {
+ _gIsUpdateFirmware = 0x11;
+ }
+ }
+ else if ((_gIsUpdateFirmware & 0x01) == 0x01)
+ {
+ _DrvFwCtrlMsg22xxEraseEmem(EMEM_INFO);
+ _DrvFwCtrlMsg22xxProgramEmem(EMEM_INFO);
+
+ nCrcInfoA = _DrvFwCtrlMsg22xxRetrieveFrimwareCrcFromBinFile(_gOneDimenFwData, EMEM_INFO);
+ nCrcInfoB = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_INFO);
+
+ DBG("nCrcInfoA=0x%x, nCrcInfoB=0x%x\n", nCrcInfoA, nCrcInfoB);
+
+ if (nCrcInfoA == nCrcInfoB)
+ {
+ _gIsUpdateFirmware = 0x00;
+ nRetVal = 0;
+ }
+ else
+ {
+ _gIsUpdateFirmware = 0x01;
+ }
+ }
+ }
+
+ return nRetVal;
+}
+
+void _DrvFwCtrlMsg22xxCheckFirmwareUpdateBySwId(void) // For MSG22XX
+{
+ u32 nCrcMainA, nCrcInfoA, nCrcMainB, nCrcInfoB;
+ u32 i;
+ u16 nUpdateBinMajor = 0, nUpdateBinMinor = 0;
+ u16 nMajor = 0, nMinor = 0;
+ u8 *pVersion = NULL;
+ Msg22xxSwId_e eSwId = MSG22XX_SW_ID_UNDEFINED;
+
+ DBG("*** %s() ***\n", __func__);
+
+ DrvPlatformLyrDisableFingerTouchReport();
+
+ DrvFwCtrlGetCustomerFirmwareVersion(&nMajor, &nMinor, &pVersion);
+
+ nCrcMainA = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_MAIN);
+ nCrcMainB = _DrvFwCtrlMsg22xxRetrieveFirmwareCrcFromEFlash(EMEM_MAIN);
+
+ nCrcInfoA = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_INFO);
+ nCrcInfoB = _DrvFwCtrlMsg22xxRetrieveFirmwareCrcFromEFlash(EMEM_INFO);
+
+ _gUpdateFirmwareBySwIdWorkQueue = create_singlethread_workqueue("update_firmware_by_sw_id");
+ INIT_WORK(&_gUpdateFirmwareBySwIdWork, _DrvFwCtrlUpdateFirmwareBySwIdDoWork);
+
+ DBG("nCrcMainA=0x%x, nCrcInfoA=0x%x, nCrcMainB=0x%x, nCrcInfoB=0x%x\n", nCrcMainA, nCrcInfoA, nCrcMainB, nCrcInfoB);
+
+ if (nCrcMainA == nCrcMainB && nCrcInfoA == nCrcInfoB) // Case 1. Main Block:OK, Info Block:OK
+ {
+ eSwId = _DrvFwCtrlMsg22xxGetSwId(EMEM_MAIN);
+
+ if (eSwId == MSG22XX_SW_ID_XXXX)
+ {
+ nUpdateBinMajor = msg2xxx_xxxx_update_bin[0xBFF5]<<8 | msg2xxx_xxxx_update_bin[0xBFF4];
+ nUpdateBinMinor = msg2xxx_xxxx_update_bin[0xBFF7]<<8 | msg2xxx_xxxx_update_bin[0xBFF6];
+ }
+ else if (eSwId == MSG22XX_SW_ID_YYYY)
+ {
+ nUpdateBinMajor = msg2xxx_yyyy_update_bin[0xBFF5]<<8 | msg2xxx_yyyy_update_bin[0xBFF4];
+ nUpdateBinMinor = msg2xxx_yyyy_update_bin[0xBFF7]<<8 | msg2xxx_yyyy_update_bin[0xBFF6];
+ }
+ else //eSwId == MSG22XX_SW_ID_UNDEFINED
+ {
+ DBG("eSwId = 0x%x is an undefined SW ID.\n", eSwId);
+
+ eSwId = MSG22XX_SW_ID_UNDEFINED;
+ nUpdateBinMajor = 0;
+ nUpdateBinMinor = 0;
+ }
+
+ DBG("eSwId=0x%x, nMajor=%d, nMinor=%d, nUpdateBinMajor=%d, nUpdateBinMinor=%d\n", eSwId, nMajor, nMinor, nUpdateBinMajor, nUpdateBinMinor);
+
+ if (nUpdateBinMinor > nMinor)
+ {
+ if (eSwId < MSG22XX_SW_ID_UNDEFINED && eSwId != 0x0000 && eSwId != 0xFFFF)
+ {
+ if (eSwId == MSG22XX_SW_ID_XXXX)
+ {
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 1024);
+ }
+ else // i == 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 512);
+ }
+ }
+ }
+ else if (eSwId == MSG22XX_SW_ID_YYYY)
+ {
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 1024);
+ }
+ else // i == 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 512);
+ }
+ }
+ }
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after copying update firmware data to temp buffer
+
+ _gUpdateRetryCount = UPDATE_FIRMWARE_RETRY_COUNT;
+ _gIsUpdateInfoBlockFirst = 1; // Set 1 for indicating main block is complete
+ _gIsUpdateFirmware = 0x11;
+ queue_work(_gUpdateFirmwareBySwIdWorkQueue, &_gUpdateFirmwareBySwIdWork);
+ return;
+ }
+ else
+ {
+ DBG("The sw id is invalid.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+ else
+ {
+ DBG("The update bin version is older than or equal to the current firmware version on e-flash.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+ else if (nCrcMainA == nCrcMainB && nCrcInfoA != nCrcInfoB) // Case 2. Main Block:OK, Info Block:FAIL
+ {
+ eSwId = _DrvFwCtrlMsg22xxGetSwId(EMEM_MAIN);
+
+ DBG("eSwId=0x%x\n", eSwId);
+
+ if (eSwId < MSG22XX_SW_ID_UNDEFINED && eSwId != 0x0000 && eSwId != 0xFFFF)
+ {
+ if (eSwId == MSG22XX_SW_ID_XXXX)
+ {
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 1024);
+ }
+ else // i == 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 512);
+ }
+ }
+ }
+ else if (eSwId == MSG22XX_SW_ID_YYYY)
+ {
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 1024);
+ }
+ else // i == 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 512);
+ }
+ }
+ }
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after copying update firmware data to temp buffer
+
+ _gUpdateRetryCount = UPDATE_FIRMWARE_RETRY_COUNT;
+ _gIsUpdateInfoBlockFirst = 1; // Set 1 for indicating main block is complete
+ _gIsUpdateFirmware = 0x11;
+ queue_work(_gUpdateFirmwareBySwIdWorkQueue, &_gUpdateFirmwareBySwIdWork);
+ return;
+ }
+ else
+ {
+ DBG("The sw id is invalid.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+ else if (nCrcMainA != nCrcMainB && nCrcInfoA == nCrcInfoB) // Case 3. Main Block:FAIL, Info Block:OK
+ {
+ eSwId = _DrvFwCtrlMsg22xxGetSwId(EMEM_INFO);
+
+ DBG("eSwId=0x%x\n", eSwId);
+
+ if (eSwId < MSG22XX_SW_ID_UNDEFINED && eSwId != 0x0000 && eSwId != 0xFFFF)
+ {
+ if (eSwId == MSG22XX_SW_ID_XXXX)
+ {
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 1024);
+ }
+ else // i == 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 512);
+ }
+ }
+ }
+ else if (eSwId == MSG22XX_SW_ID_YYYY)
+ {
+ for (i = 0; i < (MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE+1); i ++)
+ {
+ if (i < MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE) // i < 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 1024);
+ }
+ else // i == 48
+ {
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 512);
+ }
+ }
+ }
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after copying update firmware data to temp buffer
+
+ _gUpdateRetryCount = UPDATE_FIRMWARE_RETRY_COUNT;
+ _gIsUpdateInfoBlockFirst = 0; // Set 0 for indicating main block is broken
+ _gIsUpdateFirmware = 0x11;
+ queue_work(_gUpdateFirmwareBySwIdWorkQueue, &_gUpdateFirmwareBySwIdWork);
+ return;
+ }
+ else
+ {
+ DBG("The sw id is invalid.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+ else // Case 4. Main Block:FAIL, Info Block:FAIL
+ {
+ DBG("Main block and Info block are broken.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DrvPlatformLyrEnableFingerTouchReport();
+}
+
+//-------------------------End of SW ID for MSG22XX----------------------------//
+
+//-------------------------Start of SW ID for MSG21XXA----------------------------//
+
+static u32 _DrvFwCtrlMsg21xxaCalculateMainCrcFromEFlash(void) // For MSG21XXA
+{
+ u32 nRetVal = 0;
+ u16 nRegData = 0;
+
+ DBG("*** %s() ***\n", __func__);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(20);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01); //bank:mheg5, addr:h0073
+
+ // Stop Watchdog
+ RegSet16BitValue(0x3C60, 0xAA55); //bank:reg_PIU_MISC_0, addr:h0030
+
+ // cmd
+ RegSet16BitValue(0x3CE4, 0xDF4C); //bank:reg_PIU_MISC_0, addr:h0072
+
+ // TP SW reset
+ RegSet16BitValue(0x1E04, 0x7d60); //bank:chip, addr:h0002
+ RegSet16BitValue(0x1E04, 0x829F);
+
+ // Start mcu
+ RegSetLByteValue(0x0FE6, 0x00); //bank:mheg5, addr:h0073
+
+ mdelay(20);
+
+ // Polling 0x3CE4 is 0x9432
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4); //bank:reg_PIU_MISC_0, addr:h0072
+ } while (nRegData != 0x9432);
+
+ // Read calculated main block CRC from register
+ nRetVal = RegGet16BitValue(0x3C80);
+ nRetVal = (nRetVal << 16) | RegGet16BitValue(0x3C82);
+
+ DBG("Main Block CRC = 0x%x\n", nRetVal);
+
+ return nRetVal;
+}
+
+static u32 _DrvFwCtrlMsg21xxaRetrieveMainCrcFromMainBlock(void) // For MSG21XXA
+{
+ u32 nRetVal = 0;
+ u16 nRegData = 0;
+ u8 szDbBusTxData[5] = {0};
+ u8 szDbBusRxData[4] = {0};
+
+ DBG("*** %s() ***\n", __func__);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(20);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01); //bank:mheg5, addr:h0073
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55); //bank:reg_PIU_MISC_0, addr:h0030
+
+ // cmd
+ RegSet16BitValue(0x3CE4, 0xA4AB); //bank:reg_PIU_MISC_0, addr:h0072
+
+ // TP SW reset
+ RegSet16BitValue(0x1E04, 0x7d60); //bank:chip, addr:h0002
+ RegSet16BitValue(0x1E04, 0x829F);
+
+ // Start mcu
+ RegSetLByteValue(0x0FE6, 0x00); //bank:mheg5, addr:h0073
+
+ mdelay(20);
+
+ // Polling 0x3CE4 is 0x5B58
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4); //bank:reg_PIU_MISC_0, addr:h0072
+ } while (nRegData != 0x5B58);
+
+ // Read main block CRC from main block
+ szDbBusTxData[0] = 0x72;
+ szDbBusTxData[1] = 0x7F;
+ szDbBusTxData[2] = 0xFC;
+ szDbBusTxData[3] = 0x00;
+ szDbBusTxData[4] = 0x04;
+
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 5);
+ IicReadData(SLAVE_I2C_ID_DWI2C, &szDbBusRxData[0], 4);
+
+ nRetVal = szDbBusRxData[0];
+ nRetVal = (nRetVal << 8) | szDbBusRxData[1];
+ nRetVal = (nRetVal << 8) | szDbBusRxData[2];
+ nRetVal = (nRetVal << 8) | szDbBusRxData[3];
+
+ DBG("CRC = 0x%x\n", nRetVal);
+
+ return nRetVal;
+}
+
+static u16 _DrvFwCtrlMsg21xxaGetSwId(EmemType_e eEmemType) // For MSG21XXA
+{
+ u16 nRetVal = 0;
+ u16 nRegData = 0;
+ u8 szDbBusTxData[5] = {0};
+ u8 szDbBusRxData[4] = {0};
+
+ DBG("*** %s() eEmemType = %d ***\n", __func__, eEmemType);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(20);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01); //bank:mheg5, addr:h0073
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55); //bank:reg_PIU_MISC_0, addr:h0030
+
+ // cmd
+ RegSet16BitValue(0x3CE4, 0xA4AB); //bank:reg_PIU_MISC_0, addr:h0072
+
+ // TP SW reset
+ RegSet16BitValue(0x1E04, 0x7d60); //bank:chip, addr:h0002
+ RegSet16BitValue(0x1E04, 0x829F);
+
+ // Start mcu
+ RegSetLByteValue(0x0FE6, 0x00); //bank:mheg5, addr:h0073
+
+ mdelay(20);
+
+ // Polling 0x3CE4 is 0x5B58
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4); //bank:reg_PIU_MISC_0, addr:h0072
+ } while (nRegData != 0x5B58);
+
+ szDbBusTxData[0] = 0x72;
+ if (eEmemType == EMEM_MAIN) // Read SW ID from main block
+ {
+ szDbBusTxData[1] = 0x7F;
+ szDbBusTxData[2] = 0x55;
+ }
+ else if (eEmemType == EMEM_INFO) // Read SW ID from info block
+ {
+ szDbBusTxData[1] = 0x83;
+ szDbBusTxData[2] = 0x00;
+ }
+ szDbBusTxData[3] = 0x00;
+ szDbBusTxData[4] = 0x04;
+
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 5);
+ IicReadData(SLAVE_I2C_ID_DWI2C, &szDbBusRxData[0], 4);
+
+ DBG("szDbBusRxData[0,1,2,3] = 0x%x,0x%x,0x%x,0x%x\n", szDbBusRxData[0], szDbBusRxData[1], szDbBusRxData[2], szDbBusRxData[3]);
+
+ if ((szDbBusRxData[0] >= 0x30 && szDbBusRxData[0] <= 0x39)
+ &&(szDbBusRxData[1] >= 0x30 && szDbBusRxData[1] <= 0x39)
+ &&(szDbBusRxData[2] >= 0x31 && szDbBusRxData[2] <= 0x39))
+ {
+ nRetVal = (szDbBusRxData[0]-0x30)*100+(szDbBusRxData[1]-0x30)*10+(szDbBusRxData[2]-0x30);
+ }
+
+ DBG("SW ID = 0x%x\n", nRetVal);
+
+ return nRetVal;
+}
+
+static s32 _DrvFwCtrlMsg21xxaUpdateFirmwareBySwId(u8 szFwData[][1024], EmemType_e eEmemType) // For MSG21XXA
+{
+ u32 i, j, nCalculateCrcSize;
+ u32 nCrcMain = 0, nCrcMainTp = 0;
+ u32 nCrcInfo = 0, nCrcInfoTp = 0;
+ u32 nCrcTemp = 0;
+ u16 nRegData = 0;
+
+ DBG("*** %s() ***\n", __func__);
+
+ nCrcMain = 0xffffffff;
+ nCrcInfo = 0xffffffff;
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaAlloc();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ // erase main
+ _DrvFwCtrlEraseEmemC33(EMEM_MAIN);
+ mdelay(1000);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(300);
+
+ /////////////////////////
+ // Program
+ /////////////////////////
+
+ // Polling 0x3CE4 is 0x1C70
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x1C70);
+ }
+
+ switch (eEmemType)
+ {
+ case EMEM_ALL:
+ RegSet16BitValue(0x3CE4, 0xE38F); // for all blocks
+ break;
+ case EMEM_MAIN:
+ RegSet16BitValue(0x3CE4, 0x7731); // for main block
+ break;
+ case EMEM_INFO:
+ RegSet16BitValue(0x3CE4, 0x7731); // for info block
+
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ RegSetLByteValue(0x3CE4, 0xC5);
+ RegSetLByteValue(0x3CE5, 0x78);
+
+ RegSetLByteValue(0x1E04, 0x9F);
+ RegSetLByteValue(0x1E05, 0x82);
+
+ RegSetLByteValue(0x0FE6, 0x00);
+ mdelay(100);
+ break;
+ }
+
+ // Polling 0x3CE4 is 0x2F43
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x2F43);
+
+ // Calculate CRC 32
+ DrvCommonCrcInitTable();
+
+ if (eEmemType == EMEM_ALL)
+ {
+ nCalculateCrcSize = MSG21XXA_FIRMWARE_WHOLE_SIZE;
+ }
+ else if (eEmemType == EMEM_MAIN)
+ {
+ nCalculateCrcSize = MSG21XXA_FIRMWARE_MAIN_BLOCK_SIZE;
+ }
+ else if (eEmemType == EMEM_INFO)
+ {
+ nCalculateCrcSize = MSG21XXA_FIRMWARE_INFO_BLOCK_SIZE;
+ }
+ else
+ {
+ nCalculateCrcSize = 0;
+ }
+
+ for (i = 0; i < nCalculateCrcSize; i ++)
+ {
+ if (eEmemType == EMEM_INFO)
+ {
+ i = 32;
+ }
+
+ if (i < 32) // emem_main
+ {
+ if (i == 31)
+ {
+ szFwData[i][1014] = 0x5A;
+ szFwData[i][1015] = 0xA5;
+
+ for (j = 0; j < 1016; j ++)
+ {
+ nCrcMain = DrvCommonCrcGetValue(szFwData[i][j], nCrcMain);
+ }
+
+ nCrcTemp = nCrcMain;
+ nCrcTemp = nCrcTemp ^ 0xffffffff;
+
+ DBG("nCrcTemp=%x\n", nCrcTemp); // add for debug
+
+ for (j = 0; j < 4; j ++)
+ {
+ szFwData[i][1023-j] = ((nCrcTemp>>(8*j)) & 0xFF);
+
+ DBG("((nCrcTemp>>(8*%d)) & 0xFF)=%x\n", j, ((nCrcTemp>>(8*j)) & 0xFF)); // add for debug
+ DBG("Update main clock crc32 into bin buffer szFwData[%d][%d]=%x\n", i, (1020+j), szFwData[i][1020+j]);
+ }
+ }
+ else
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ nCrcMain = DrvCommonCrcGetValue(szFwData[i][j], nCrcMain);
+ }
+ }
+ }
+ else // emem_info
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ nCrcInfo = DrvCommonCrcGetValue(szFwData[i][j], nCrcInfo);
+ }
+
+ if (eEmemType == EMEM_MAIN)
+ {
+ break;
+ }
+ }
+
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ for (j = 0; j < 8; j ++)
+ {
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szFwData[i][j*128], 128);
+ }
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ IicWriteData(SLAVE_I2C_ID_DWI2C, szFwData[i], 1024);
+#endif
+
+ // Polling 0x3CE4 is 0xD0BC
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0xD0BC);
+
+ RegSet16BitValue(0x3CE4, 0x2F43);
+ }
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ // write file done and check crc
+ RegSet16BitValue(0x3CE4, 0x1380);
+ }
+ mdelay(10);
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ // Polling 0x3CE4 is 0x9432
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x9432);
+ }
+
+ nCrcMain = nCrcMain ^ 0xffffffff;
+ nCrcInfo = nCrcInfo ^ 0xffffffff;
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ // CRC Main from TP
+ nCrcMainTp = RegGet16BitValue(0x3C80);
+ nCrcMainTp = (nCrcMainTp << 16) | RegGet16BitValue(0x3C82);
+ }
+
+ if (eEmemType == EMEM_ALL)
+ {
+ // CRC Info from TP
+ nCrcInfoTp = RegGet16BitValue(0x3CA0);
+ nCrcInfoTp = (nCrcInfoTp << 16) | RegGet16BitValue(0x3CA2);
+ }
+
+ DBG("nCrcMain=0x%x, nCrcInfo=0x%x, nCrcMainTp=0x%x, nCrcInfoTp=0x%x\n", nCrcMain, nCrcInfo, nCrcMainTp, nCrcInfoTp);
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after update firmware
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaFree();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ if (nCrcMainTp != nCrcMain)
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+ }
+
+ if (eEmemType == EMEM_ALL)
+ {
+ if (nCrcInfoTp != nCrcInfo)
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+ }
+
+ DBG("Update SUCCESS\n");
+
+ return 0;
+}
+
+void _DrvFwCtrlMsg21xxaCheckFirmwareUpdateBySwId(void) // For MSG21XXA
+{
+ u32 nCrcMainA, nCrcMainB;
+ u32 i;
+ u16 nUpdateBinMajor = 0, nUpdateBinMinor = 0;
+ u16 nMajor = 0, nMinor = 0;
+ u8 nIsCompareVersion = 0;
+ u8 *pVersion = NULL;
+ Msg21xxaSwId_e eMainSwId = MSG21XXA_SW_ID_UNDEFINED, eInfoSwId = MSG21XXA_SW_ID_UNDEFINED, eSwId = MSG21XXA_SW_ID_UNDEFINED;
+
+ DBG("*** %s() ***\n", __func__);
+
+ DrvPlatformLyrDisableFingerTouchReport();
+ msleep(100);
+ DrvFwCtrlGetCustomerFirmwareVersion(&nMajor, &nMinor, &pVersion);
+
+ nCrcMainA = _DrvFwCtrlMsg21xxaCalculateMainCrcFromEFlash();
+ nCrcMainB = _DrvFwCtrlMsg21xxaRetrieveMainCrcFromMainBlock();
+
+ _gUpdateFirmwareBySwIdWorkQueue = create_singlethread_workqueue("update_firmware_by_sw_id");
+ INIT_WORK(&_gUpdateFirmwareBySwIdWork, _DrvFwCtrlUpdateFirmwareBySwIdDoWork);
+
+ DBG("nCrcMainA=0x%x, nCrcMainB=0x%x\n", nCrcMainA, nCrcMainB);
+
+ if (nCrcMainA == nCrcMainB)
+ {
+ eMainSwId = _DrvFwCtrlMsg21xxaGetSwId(EMEM_MAIN);
+ eInfoSwId = _DrvFwCtrlMsg21xxaGetSwId(EMEM_INFO);
+
+ DBG("Check firmware integrity success\n");
+ DBG("eMainSwId=0x%x, eInfoSwId=0x%x\n", eMainSwId, eInfoSwId);
+
+ if (eMainSwId == eInfoSwId)
+ {
+ eSwId = eMainSwId;
+ nIsCompareVersion = 1;
+ }
+ else
+ {
+ eSwId = eInfoSwId;
+ nIsCompareVersion = 0;
+ }
+
+ if (eSwId == MSG21XXA_SW_ID_XXXX)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_TWO_DIMENSIONAL_ARRAY // By two dimensional array
+ nUpdateBinMajor = msg2xxx_xxxx_update_bin[31][0x34F]<<8 | msg2xxx_xxxx_update_bin[31][0x34E];
+ nUpdateBinMinor = msg2xxx_xxxx_update_bin[31][0x351]<<8 | msg2xxx_xxxx_update_bin[31][0x350];
+#else // By one dimensional array
+ nUpdateBinMajor = msg2xxx_xxxx_update_bin[0x7F4F]<<8 | msg2xxx_xxxx_update_bin[0x7F4E];
+ nUpdateBinMinor = msg2xxx_xxxx_update_bin[0x7F51]<<8 | msg2xxx_xxxx_update_bin[0x7F50];
+#endif
+ }
+ else if (eSwId == MSG21XXA_SW_ID_YYYY)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_TWO_DIMENSIONAL_ARRAY // By two dimensional array
+ nUpdateBinMajor = msg2xxx_yyyy_update_bin[31][0x34F]<<8 | msg2xxx_yyyy_update_bin[31][0x34E];
+ nUpdateBinMinor = msg2xxx_yyyy_update_bin[31][0x351]<<8 | msg2xxx_yyyy_update_bin[31][0x350];
+#else // By one dimensional array
+ nUpdateBinMajor = msg2xxx_yyyy_update_bin[0x7F4F]<<8 | msg2xxx_yyyy_update_bin[0x7F4E];
+ nUpdateBinMinor = msg2xxx_yyyy_update_bin[0x7F51]<<8 | msg2xxx_yyyy_update_bin[0x7F50];
+#endif
+ }
+ else //eSwId == MSG21XXA_SW_ID_UNDEFINED
+ {
+ DBG("eSwId = 0x%x is an undefined SW ID.\n", eSwId);
+
+ eSwId = MSG21XXA_SW_ID_UNDEFINED;
+ nUpdateBinMajor = 0;
+ nUpdateBinMinor = 0;
+ }
+
+ DBG("eSwId=0x%x, nMajor=%d, nMinor=%d, nUpdateBinMajor=%d, nUpdateBinMinor=%d\n", eSwId, nMajor, nMinor, nUpdateBinMajor, nUpdateBinMinor);
+
+ if ((nUpdateBinMinor > nMinor && nIsCompareVersion == 1) || (nIsCompareVersion == 0))
+ {
+ if (eSwId < MSG21XXA_SW_ID_UNDEFINED && eSwId != 0xFFFF)
+ {
+ if (eSwId == MSG21XXA_SW_ID_XXXX)
+ {
+ for (i = 0; i < MSG21XXA_FIRMWARE_MAIN_BLOCK_SIZE; i ++)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_TWO_DIMENSIONAL_ARRAY // By two dimensional array
+ _DrvFwCtrlStoreFirmwareData(msg2xxx_xxxx_update_bin[i], 1024);
+#else // By one dimensional array
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 1024);
+#endif
+ }
+ }
+ else if (eSwId == MSG21XXA_SW_ID_YYYY)
+ {
+ for (i = 0; i < MSG21XXA_FIRMWARE_MAIN_BLOCK_SIZE; i ++)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_TWO_DIMENSIONAL_ARRAY // By two dimensional array
+ _DrvFwCtrlStoreFirmwareData(msg2xxx_yyyy_update_bin[i], 1024);
+#else // By one dimensional array
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 1024);
+#endif
+ }
+ }
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after copying update firmware data to temp buffer
+
+ _gUpdateRetryCount = UPDATE_FIRMWARE_RETRY_COUNT;
+ queue_work(_gUpdateFirmwareBySwIdWorkQueue, &_gUpdateFirmwareBySwIdWork);
+ return;
+ }
+ else
+ {
+ DBG("The sw id is invalid.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+ else
+ {
+ DBG("The update bin version is older than or equal to the current firmware version on e-flash.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+ else
+ {
+ eSwId = _DrvFwCtrlMsg21xxaGetSwId(EMEM_INFO);
+
+ DBG("Check firmware integrity failed\n");
+ DBG("eSwId=0x%x\n", eSwId);
+
+ if (eSwId < MSG21XXA_SW_ID_UNDEFINED && eSwId != 0xFFFF)
+ {
+ if (eSwId == MSG21XXA_SW_ID_XXXX)
+ {
+ for (i = 0; i < MSG21XXA_FIRMWARE_MAIN_BLOCK_SIZE; i ++)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_TWO_DIMENSIONAL_ARRAY // By two dimensional array
+ _DrvFwCtrlStoreFirmwareData(msg2xxx_xxxx_update_bin[i], 1024);
+#else // By one dimensional array
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_xxxx_update_bin[i*1024]), 1024);
+#endif
+ }
+ }
+ else if (eSwId == MSG21XXA_SW_ID_YYYY)
+ {
+ for (i = 0; i < MSG21XXA_FIRMWARE_MAIN_BLOCK_SIZE; i ++)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_TWO_DIMENSIONAL_ARRAY // By two dimensional array
+ _DrvFwCtrlStoreFirmwareData(msg2xxx_yyyy_update_bin[i], 1024);
+#else // By one dimensional array
+ _DrvFwCtrlStoreFirmwareData(&(msg2xxx_yyyy_update_bin[i*1024]), 1024);
+#endif
+ }
+ }
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after copying update firmware data to temp buffer
+
+ _gUpdateRetryCount = UPDATE_FIRMWARE_RETRY_COUNT;
+ queue_work(_gUpdateFirmwareBySwIdWorkQueue, &_gUpdateFirmwareBySwIdWork);
+ return;
+ }
+ else
+ {
+ DBG("The sw id is invalid.\n");
+ DBG("Go to normal boot up process.\n");
+ }
+ }
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DrvPlatformLyrEnableFingerTouchReport();
+}
+
+//-------------------------End of SW ID for MSG21XXA----------------------------//
+
+static void _DrvFwCtrlUpdateFirmwareBySwIdDoWork(struct work_struct *pWork)
+{
+ s32 nRetVal = 0;
+
+ DBG("*** %s() _gUpdateRetryCount = %d ***\n", __func__, _gUpdateRetryCount);
+
+ if (g_ChipType == CHIP_TYPE_MSG21XXA)
+ {
+ nRetVal = _DrvFwCtrlMsg21xxaUpdateFirmwareBySwId(g_FwData, EMEM_MAIN);
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ nRetVal = _DrvFwCtrlMsg22xxUpdateFirmwareBySwId();
+ }
+ else
+ {
+ DBG("This chip type (%d) does not support update firmware by sw id\n", g_ChipType);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DrvPlatformLyrEnableFingerTouchReport();
+
+ nRetVal = -1;
+ return;
+ }
+
+ DBG("*** update firmware by sw id result = %d ***\n", nRetVal);
+
+ if (nRetVal == 0)
+ {
+ DBG("update firmware by sw id success\n");
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DrvPlatformLyrEnableFingerTouchReport();
+
+ if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ _gIsUpdateInfoBlockFirst = 0;
+ _gIsUpdateFirmware = 0x00;
+ }
+ }
+ else //nRetVal == -1
+ {
+ _gUpdateRetryCount --;
+ if (_gUpdateRetryCount > 0)
+ {
+ DBG("_gUpdateRetryCount = %d\n", _gUpdateRetryCount);
+ queue_work(_gUpdateFirmwareBySwIdWorkQueue, &_gUpdateFirmwareBySwIdWork);
+ }
+ else
+ {
+ DBG("update firmware by sw id failed\n");
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DrvPlatformLyrEnableFingerTouchReport();
+
+ if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ _gIsUpdateInfoBlockFirst = 0;
+ _gIsUpdateFirmware = 0x00;
+ }
+ }
+ }
+}
+
+#endif //CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+
+//------------------------------------------------------------------------------//
+
+static void _DrvFwCtrlReadInfoC33(void)
+{
+ u8 szDbBusTxData[5] = {0};
+ u16 nRegData = 0;
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ u32 i;
+#endif
+
+ DBG("*** %s() ***\n", __func__);
+
+ mdelay(300);
+
+ // Stop Watchdog
+ RegSetLByteValue(0x3C60, 0x55);
+ RegSetLByteValue(0x3C61, 0xAA);
+
+ RegSet16BitValue(0x3CE4, 0xA4AB);
+
+ RegSet16BitValue(0x1E04, 0x7d60);
+
+ // TP SW reset
+ RegSet16BitValue(0x1E04, 0x829F);
+ mdelay(1);
+
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x0F;
+ szDbBusTxData[2] = 0xE6;
+ szDbBusTxData[3] = 0x00;
+ IicWriteData(SLAVE_I2C_ID_DBBUS, szDbBusTxData, 4);
+ mdelay(100);
+
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x5B58);
+
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ szDbBusTxData[0] = 0x72;
+ szDbBusTxData[3] = 0x00;
+ szDbBusTxData[4] = 0x80; // read 128 bytes
+
+ for (i = 0; i < 8; i ++)
+ {
+ szDbBusTxData[1] = 0x80 + (((i*128)&0xff00)>>8);
+ szDbBusTxData[2] = (i*128)&0x00ff;
+
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 5);
+
+ mdelay(50);
+
+ // Receive info data
+ IicReadData(SLAVE_I2C_ID_DWI2C, &_gDwIicInfoData[i*128], 128);
+ }
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ szDbBusTxData[0] = 0x72;
+ szDbBusTxData[1] = 0x80;
+ szDbBusTxData[2] = 0x00;
+ szDbBusTxData[3] = 0x04; // read 1024 bytes
+ szDbBusTxData[4] = 0x00;
+
+ IicWriteData(SLAVE_I2C_ID_DWI2C, szDbBusTxData, 5);
+
+ mdelay(50);
+
+ // Receive info data
+ IicReadData(SLAVE_I2C_ID_DWI2C, &_gDwIicInfoData[0], 1024);
+#endif
+}
+
+static s32 _DrvFwCtrlUpdateFirmwareC32(u8 szFwData[][1024], EmemType_e eEmemType)
+{
+ u32 i, j;
+ u32 nCrcMain, nCrcMainTp;
+ u32 nCrcInfo, nCrcInfoTp;
+ u32 nCrcTemp;
+ u16 nRegData = 0;
+
+ DBG("*** %s() ***\n", __func__);
+
+ nCrcMain = 0xffffffff;
+ nCrcInfo = 0xffffffff;
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaAlloc();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ /////////////////////////
+ // Erase all
+ /////////////////////////
+ _DrvFwCtrlEraseEmemC32();
+ mdelay(1000);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(300);
+
+ // Reset watch dog
+ RegSetLByteValue(0x3C60, 0x55);
+ RegSetLByteValue(0x3C61, 0xAA);
+
+ /////////////////////////
+ // Program
+ /////////////////////////
+
+ // Polling 0x3CE4 is 0x1C70
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x1C70);
+
+ RegSet16BitValue(0x3CE4, 0xE38F); // for all-blocks
+
+ // Polling 0x3CE4 is 0x2F43
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x2F43);
+
+ // Calculate CRC 32
+ DrvCommonCrcInitTable();
+
+ for (i = 0; i < 33; i ++) // total 33 KB : 2 byte per R/W
+ {
+ if (i < 32) // emem_main
+ {
+ if (i == 31)
+ {
+ szFwData[i][1014] = 0x5A;
+ szFwData[i][1015] = 0xA5;
+
+ for (j = 0; j < 1016; j ++)
+ {
+ nCrcMain = DrvCommonCrcGetValue(szFwData[i][j], nCrcMain);
+ }
+
+ nCrcTemp = nCrcMain;
+ nCrcTemp = nCrcTemp ^ 0xffffffff;
+
+ DBG("nCrcTemp=%x\n", nCrcTemp); // add for debug
+
+ for (j = 0; j < 4; j ++)
+ {
+ szFwData[i][1023-j] = ((nCrcTemp>>(8*j)) & 0xFF);
+
+ DBG("((nCrcTemp>>(8*%d)) & 0xFF)=%x\n", j, ((nCrcTemp>>(8*j)) & 0xFF)); // add for debug
+ DBG("Update main clock crc32 into bin buffer szFwData[%d][%d]=%x\n", i, (1020+j), szFwData[i][1020+j]);
+ }
+ }
+ else
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ nCrcMain = DrvCommonCrcGetValue(szFwData[i][j], nCrcMain);
+ }
+ }
+ }
+ else // emem_info
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ nCrcInfo = DrvCommonCrcGetValue(szFwData[i][j], nCrcInfo);
+ }
+ }
+
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ for (j = 0; j < 8; j ++)
+ {
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szFwData[i][j*128], 128);
+ }
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ IicWriteData(SLAVE_I2C_ID_DWI2C, szFwData[i], 1024);
+#endif
+
+ // Polling 0x3CE4 is 0xD0BC
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0xD0BC);
+
+ RegSet16BitValue(0x3CE4, 0x2F43);
+ }
+
+ // Write file done
+ RegSet16BitValue(0x3CE4, 0x1380);
+
+ mdelay(10);
+ // Polling 0x3CE4 is 0x9432
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x9432);
+
+ nCrcMain = nCrcMain ^ 0xffffffff;
+ nCrcInfo = nCrcInfo ^ 0xffffffff;
+
+ // CRC Main from TP
+ nCrcMainTp = RegGet16BitValue(0x3C80);
+ nCrcMainTp = (nCrcMainTp << 16) | RegGet16BitValue(0x3C82);
+
+ // CRC Info from TP
+ nCrcInfoTp = RegGet16BitValue(0x3CA0);
+ nCrcInfoTp = (nCrcInfoTp << 16) | RegGet16BitValue(0x3CA2);
+
+ DBG("nCrcMain=0x%x, nCrcInfo=0x%x, nCrcMainTp=0x%x, nCrcInfoTp=0x%x\n",
+ nCrcMain, nCrcInfo, nCrcMainTp, nCrcInfoTp);
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after update firmware
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaFree();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ if ((nCrcMainTp != nCrcMain) || (nCrcInfoTp != nCrcInfo))
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+
+ DBG("Update SUCCESS\n");
+
+ return 0;
+}
+
+static s32 _DrvFwCtrlUpdateFirmwareC33(u8 szFwData[][1024], EmemType_e eEmemType)
+{
+ u8 szLifeCounter[2];
+ u32 i, j;
+ u32 nCrcMain, nCrcMainTp;
+ u32 nCrcInfo, nCrcInfoTp;
+ u32 nCrcTemp;
+ u16 nRegData = 0;
+
+ DBG("*** %s() ***\n", __func__);
+
+ nCrcMain = 0xffffffff;
+ nCrcInfo = 0xffffffff;
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaAlloc();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ _DrvFwCtrlReadInfoC33();
+
+ if (_gDwIicInfoData[0] == 'M' && _gDwIicInfoData[1] == 'S' && _gDwIicInfoData[2] == 'T' && _gDwIicInfoData[3] == 'A' && _gDwIicInfoData[4] == 'R' && _gDwIicInfoData[5] == 'T' && _gDwIicInfoData[6] == 'P' && _gDwIicInfoData[7] == 'C')
+ {
+ _gDwIicInfoData[8] = szFwData[32][8];
+ _gDwIicInfoData[9] = szFwData[32][9];
+ _gDwIicInfoData[10] = szFwData[32][10];
+ _gDwIicInfoData[11] = szFwData[32][11];
+ // updata life counter
+ szLifeCounter[1] = ((((_gDwIicInfoData[13] << 8) | _gDwIicInfoData[12]) + 1) >> 8) & 0xFF;
+ szLifeCounter[0] = (((_gDwIicInfoData[13] << 8) | _gDwIicInfoData[12]) + 1) & 0xFF;
+ _gDwIicInfoData[12] = szLifeCounter[0];
+ _gDwIicInfoData[13] = szLifeCounter[1];
+
+ RegSet16BitValue(0x3CE4, 0x78C5);
+ RegSet16BitValue(0x1E04, 0x7d60);
+ // TP SW reset
+ RegSet16BitValue(0x1E04, 0x829F);
+
+ mdelay(50);
+
+ // Polling 0x3CE4 is 0x2F43
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x2F43);
+
+ // Transmit lk info data
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ for (j = 0; j < 8; j ++)
+ {
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &_gDwIicInfoData[j*128], 128);
+ }
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &_gDwIicInfoData[0], 1024);
+#endif
+
+ // Polling 0x3CE4 is 0xD0BC
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0xD0BC);
+ }
+
+ // erase main
+ _DrvFwCtrlEraseEmemC33(EMEM_MAIN);
+ mdelay(1000);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(300);
+
+ /////////////////////////
+ // Program
+ /////////////////////////
+
+ // Polling 0x3CE4 is 0x1C70
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x1C70);
+ }
+
+ switch (eEmemType)
+ {
+ case EMEM_ALL:
+ RegSet16BitValue(0x3CE4, 0xE38F); // for all blocks
+ break;
+ case EMEM_MAIN:
+ RegSet16BitValue(0x3CE4, 0x7731); // for main block
+ break;
+ case EMEM_INFO:
+ RegSet16BitValue(0x3CE4, 0x7731); // for info block
+
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ RegSetLByteValue(0x3CE4, 0xC5);
+ RegSetLByteValue(0x3CE5, 0x78);
+
+ RegSetLByteValue(0x1E04, 0x9F);
+ RegSetLByteValue(0x1E05, 0x82);
+
+ RegSetLByteValue(0x0FE6, 0x00);
+ mdelay(100);
+ break;
+ }
+
+ // Polling 0x3CE4 is 0x2F43
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x2F43);
+
+ // Calculate CRC 32
+ DrvCommonCrcInitTable();
+
+ for (i = 0; i < 33; i ++) // total 33 KB : 2 byte per R/W
+ {
+ if (eEmemType == EMEM_INFO)
+ {
+ i = 32;
+ }
+
+ if (i < 32) // emem_main
+ {
+ if (i == 31)
+ {
+ szFwData[i][1014] = 0x5A;
+ szFwData[i][1015] = 0xA5;
+
+ for (j = 0; j < 1016; j ++)
+ {
+ nCrcMain = DrvCommonCrcGetValue(szFwData[i][j], nCrcMain);
+ }
+
+ nCrcTemp = nCrcMain;
+ nCrcTemp = nCrcTemp ^ 0xffffffff;
+
+ DBG("nCrcTemp=%x\n", nCrcTemp); // add for debug
+
+ for (j = 0; j < 4; j ++)
+ {
+ szFwData[i][1023-j] = ((nCrcTemp>>(8*j)) & 0xFF);
+
+ DBG("((nCrcTemp>>(8*%d)) & 0xFF)=%x\n", j, ((nCrcTemp>>(8*j)) & 0xFF)); // add for debug
+ DBG("Update main clock crc32 into bin buffer szFwData[%d][%d]=%x\n", i, (1020+j), szFwData[i][1020+j]); // add for debug
+ }
+ }
+ else
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ nCrcMain = DrvCommonCrcGetValue(szFwData[i][j], nCrcMain);
+ }
+ }
+ }
+ else // emem_info
+ {
+ for (j = 0; j < 1024; j ++)
+ {
+ nCrcInfo = DrvCommonCrcGetValue(_gDwIicInfoData[j], nCrcInfo);
+ }
+
+ if (eEmemType == EMEM_MAIN)
+ {
+ break;
+ }
+ }
+
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ for (j = 0; j < 8; j ++)
+ {
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szFwData[i][j*128], 128);
+ }
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ IicWriteData(SLAVE_I2C_ID_DWI2C, szFwData[i], 1024);
+#endif
+
+ // Polling 0x3CE4 is 0xD0BC
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0xD0BC);
+
+ RegSet16BitValue(0x3CE4, 0x2F43);
+ }
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ // write file done and check crc
+ RegSet16BitValue(0x3CE4, 0x1380);
+ }
+ mdelay(10);
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ // Polling 0x3CE4 is 0x9432
+ do
+ {
+ nRegData = RegGet16BitValue(0x3CE4);
+ } while (nRegData != 0x9432);
+ }
+
+ nCrcMain = nCrcMain ^ 0xffffffff;
+ nCrcInfo = nCrcInfo ^ 0xffffffff;
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ // CRC Main from TP
+ nCrcMainTp = RegGet16BitValue(0x3C80);
+ nCrcMainTp = (nCrcMainTp << 16) | RegGet16BitValue(0x3C82);
+
+ // CRC Info from TP
+ nCrcInfoTp = RegGet16BitValue(0x3CA0);
+ nCrcInfoTp = (nCrcInfoTp << 16) | RegGet16BitValue(0x3CA2);
+ }
+ DBG("nCrcMain=0x%x, nCrcInfo=0x%x, nCrcMainTp=0x%x, nCrcInfoTp=0x%x\n", nCrcMain, nCrcInfo, nCrcMainTp, nCrcInfoTp);
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after update firmware
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaFree();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ if ((eEmemType == EMEM_ALL) || (eEmemType == EMEM_MAIN))
+ {
+ if ((nCrcMainTp != nCrcMain) || (nCrcInfoTp != nCrcInfo))
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+ }
+
+ DBG("Update SUCCESS\n");
+
+ return 0;
+}
+
+static s32 _DrvFwCtrlMsg22xxUpdateFirmware(u8 szFwData[][1024], EmemType_e eEmemType)
+{
+ u32 i, index;
+ u32 nCrcMain, nCrcMainTp;
+ u32 nCrcInfo, nCrcInfoTp;
+ u32 nRemainSize, nBlockSize, nSize;
+ u16 nRegData = 0;
+ u8 szDbBusTxData[1024] = {0};
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM) || defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+ u32 nSizePerWrite = 125;
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+ u32 nSizePerWrite = 1021;
+#endif
+
+ DBG("*** %s() ***\n", __func__);
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaAlloc();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ _DrvFwCtrlMsg22xxConvertFwDataTwoDimenToOneDimen(szFwData, _gOneDimenFwData);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+
+ DBG("Erase start\n");
+
+ // Stop mcu
+ RegSet16BitValue(0x0FE6, 0x0001);
+
+ // Disable watchdog
+ RegSetLByteValue(0x3C60, 0x55);
+ RegSetLByteValue(0x3C61, 0xAA);
+
+ // Set PROGRAM password
+ RegSetLByteValue(0x161A, 0xBA);
+ RegSetLByteValue(0x161B, 0xAB);
+
+ if (eEmemType == EMEM_ALL) // 48KB + 512Byte
+ {
+ DBG("Erase all block\n");
+
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+ mdelay(100);
+
+ // Chip erase
+ RegSet16BitValue(0x160E, BIT3);
+
+ DBG("Wait erase done flag\n");
+
+ do // Wait erase done flag
+ {
+ nRegData = RegGet16BitValue(0x1610); // Memory status
+ mdelay(50);
+ } while((nRegData & BIT1) != BIT1);
+ }
+ else if (eEmemType == EMEM_MAIN) // 48KB (32+8+8)
+ {
+ DBG("Erase main block\n");
+
+ for (i = 0; i < 3; i ++)
+ {
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+ mdelay(10);
+
+ if (i == 0)
+ {
+ RegSet16BitValue(0x1600, 0x0000);
+ }
+ else if (i == 1)
+ {
+ RegSet16BitValue(0x1600, 0x8000);
+ }
+ else if (i == 2)
+ {
+ RegSet16BitValue(0x1600, 0xA000);
+ }
+
+ // Sector erase
+ RegSet16BitValue(0x160E, (RegGet16BitValue(0x160E) | BIT2));
+
+ DBG("Wait erase done flag\n");
+
+ do // Wait erase done flag
+ {
+ nRegData = RegGet16BitValue(0x1610); // Memory status
+ mdelay(50);
+ } while((nRegData & BIT1) != BIT1);
+ }
+ }
+ else if (eEmemType == EMEM_INFO) // 512Byte
+ {
+ DBG("Erase info block\n");
+
+ // Clear pce
+ RegSetLByteValue(0x1618, 0x80);
+ mdelay(10);
+
+ RegSet16BitValue(0x1600, 0xC000);
+
+ // Sector erase
+ RegSet16BitValue(0x160E, (RegGet16BitValue(0x160E) | BIT2));
+
+ DBG("Wait erase done flag\n");
+
+ do // Wait erase done flag
+ {
+ nRegData = RegGet16BitValue(0x1610); // Memory status
+ mdelay(50);
+ } while((nRegData & BIT1) != BIT1);
+ }
+
+ DBG("Erase end\n");
+
+ // Hold reset pin before program
+ RegSetLByteValue(0x1E06, 0x00);
+
+ /////////////////////////
+ // Program
+ /////////////////////////
+
+ if (eEmemType == EMEM_ALL || eEmemType == EMEM_MAIN) // 48KB
+ {
+ DBG("Program main block start\n");
+
+ // Program main block
+ RegSet16BitValue(0x161A, 0xABBA);
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ RegSet16BitValue(0x1600, 0x0000); // Set start address of main block
+ RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01)); // Enable burst mode
+
+ // Program start
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x16;
+ szDbBusTxData[2] = 0x02;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 3);
+
+ szDbBusTxData[0] = 0x20;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 1);
+
+ nRemainSize = MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE * 1024; //48KB
+ index = 0;
+
+ while (nRemainSize > 0)
+ {
+ if (nRemainSize > nSizePerWrite)
+ {
+ nBlockSize = nSizePerWrite;
+ }
+ else
+ {
+ nBlockSize = nRemainSize;
+ }
+
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x16;
+ szDbBusTxData[2] = 0x02;
+
+ nSize = 3;
+
+ for (i = 0; i < nBlockSize; i ++)
+ {
+ szDbBusTxData[3+i] = _gOneDimenFwData[index*nSizePerWrite+i];
+ nSize ++;
+ }
+ index ++;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], nSize);
+
+ nRemainSize = nRemainSize - nBlockSize;
+ }
+
+ // Program end
+ szDbBusTxData[0] = 0x21;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 1);
+
+ nRegData = RegGet16BitValue(0x160C);
+ RegSet16BitValue(0x160C, nRegData & (~0x01));
+
+ DBG("Wait main block write done flag\n");
+
+ // Polling 0x1610 is 0x0002
+ do
+ {
+ nRegData = RegGet16BitValue(0x1610);
+ nRegData = nRegData & BIT1;
+ mdelay(10);
+
+ } while (nRegData != BIT1); // Wait write done flag
+
+ DBG("Program main block end\n");
+ }
+
+ if (eEmemType == EMEM_ALL || eEmemType == EMEM_INFO) // 512 Byte
+ {
+ DBG("Program info block start\n");
+
+ // Program info block
+ RegSet16BitValue(0x161A, 0xABBA);
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ RegSet16BitValue(0x1600, 0xC000); // Set start address of info block
+ RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01)); // Enable burst mode
+
+ // Program start
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x16;
+ szDbBusTxData[2] = 0x02;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 3);
+
+ szDbBusTxData[0] = 0x20;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 1);
+
+ nRemainSize = MSG22XX_FIRMWARE_INFO_BLOCK_SIZE; //512Byte
+ index = 0;
+
+ while (nRemainSize > 0)
+ {
+ if (nRemainSize > nSizePerWrite)
+ {
+ nBlockSize = nSizePerWrite;
+ }
+ else
+ {
+ nBlockSize = nRemainSize;
+ }
+
+ szDbBusTxData[0] = 0x10;
+ szDbBusTxData[1] = 0x16;
+ szDbBusTxData[2] = 0x02;
+
+ nSize = 3;
+
+ for (i = 0; i < nBlockSize; i ++)
+ {
+ szDbBusTxData[3+i] = _gOneDimenFwData[(MSG22XX_FIRMWARE_MAIN_BLOCK_SIZE*1024)+(index*nSizePerWrite)+i];
+ nSize ++;
+ }
+ index ++;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], nSize);
+
+ nRemainSize = nRemainSize - nBlockSize;
+ }
+
+ // Program end
+ szDbBusTxData[0] = 0x21;
+
+ IicWriteData(SLAVE_I2C_ID_DBBUS, &szDbBusTxData[0], 1);
+
+ nRegData = RegGet16BitValue(0x160C);
+ RegSet16BitValue(0x160C, nRegData & (~0x01));
+
+ DBG("Wait info block write done flag\n");
+
+ // Polling 0x1610 is 0x0002
+ do
+ {
+ nRegData = RegGet16BitValue(0x1610);
+ nRegData = nRegData & BIT1;
+ mdelay(10);
+
+ } while (nRegData != BIT1); // Wait write done flag
+
+ DBG("Program info block end\n");
+ }
+
+ if (eEmemType == EMEM_ALL || eEmemType == EMEM_MAIN)
+ {
+ // Get CRC 32 from updated firmware bin file
+ nCrcMain = _gOneDimenFwData[0xBFFF] << 24;
+ nCrcMain |= _gOneDimenFwData[0xBFFE] << 16;
+ nCrcMain |= _gOneDimenFwData[0xBFFD] << 8;
+ nCrcMain |= _gOneDimenFwData[0xBFFC];
+
+ // CRC Main from TP
+ DBG("Get Main CRC from TP\n");
+
+ nCrcMainTp = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_MAIN);
+
+ DBG("nCrcMain=0x%x, nCrcMainTp=0x%x\n", nCrcMain, nCrcMainTp);
+ }
+
+ if (eEmemType == EMEM_ALL || eEmemType == EMEM_INFO)
+ {
+ nCrcInfo = _gOneDimenFwData[0xC1FF] << 24;
+ nCrcInfo |= _gOneDimenFwData[0xC1FE] << 16;
+ nCrcInfo |= _gOneDimenFwData[0xC1FD] << 8;
+ nCrcInfo |= _gOneDimenFwData[0xC1FC];
+
+ // CRC Info from TP
+ DBG("Get Info CRC from TP\n");
+
+ nCrcInfoTp = _DrvFwCtrlMsg22xxGetFirmwareCrcByHardware(EMEM_INFO);
+
+ DBG("nCrcInfo=0x%x, nCrcInfoTp=0x%x\n", nCrcInfo, nCrcInfoTp);
+ }
+
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after update firmware
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+#ifdef CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaFree();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif //CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM
+
+ if (eEmemType == EMEM_ALL)
+ {
+ if ((nCrcMainTp != nCrcMain) || (nCrcInfoTp != nCrcInfo))
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+ }
+ else if (eEmemType == EMEM_MAIN)
+ {
+ if (nCrcMainTp != nCrcMain)
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+ }
+ else if (eEmemType == EMEM_INFO)
+ {
+ if (nCrcInfoTp != nCrcInfo)
+ {
+ DBG("Update FAILED\n");
+
+ return -1;
+ }
+ }
+
+ DBG("Update SUCCESS\n");
+
+ return 0;
+}
+
+static s32 _DrvFwCtrlUpdateFirmwareCash(u8 szFwData[][1024])
+{
+ DBG("*** %s() ***\n", __func__);
+
+ DBG("chip type = 0x%x\n", g_ChipType);
+
+ if (g_ChipType == CHIP_TYPE_MSG21XXA) // (0x02)
+ {
+// u16 nChipType;
+ u8 nChipVersion = 0;
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ // Erase TP Flash first
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(300);
+
+ // Stop MCU
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Disable watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ /////////////////////////
+ // Difference between C2 and C3
+ /////////////////////////
+ // c2:MSG2133(1) c32:MSG2133A(2) c33:MSG2138A(2)
+ // check ic type
+// nChipType = RegGet16BitValue(0x1ECC) & 0xFF;
+
+ // check ic version
+ nChipVersion = RegGet16BitValue(0x3CEA) & 0xFF;
+
+ DBG("chip version = 0x%x\n", nChipVersion);
+
+ if (nChipVersion == 3)
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+ return _DrvFwCtrlMsg21xxaUpdateFirmwareBySwId(szFwData, EMEM_MAIN);
+#else
+ return _DrvFwCtrlUpdateFirmwareC33(szFwData, EMEM_MAIN);
+#endif
+ }
+ else
+ {
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+ return _DrvFwCtrlMsg21xxaUpdateFirmwareBySwId(szFwData, EMEM_MAIN);
+#else
+ return _DrvFwCtrlUpdateFirmwareC32(szFwData, EMEM_ALL);
+#endif
+ }
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG22XX) // (0x7A)
+ {
+// _DrvFwCtrlMsg22xxGetTpVendorCode(_gTpVendorCode);
+
+// if (_gTpVendorCode[0] == 'C' && _gTpVendorCode[1] == 'N' && _gTpVendorCode[2] == 'T') // for specific TP vendor which store some important information in info block, only update firmware for main block, do not update firmware for info block.
+// {
+// return _DrvFwCtrlMsg22xxUpdateFirmware(szFwData, EMEM_MAIN);
+// }
+// else
+// {
+ return _DrvFwCtrlMsg22xxUpdateFirmware(szFwData, EMEM_ALL);
+// }
+ }
+ else // CHIP_TYPE_MSG21XX (0x01)
+ {
+ DBG("Can not update firmware. Catch-2 is no need to be maintained now.\n");
+ g_FwDataCount = 0; // Reset g_FwDataCount to 0 after update firmware
+
+ return -1;
+ }
+}
+
+/*=============================================================*/
+// GLOBAL FUNCTION DEFINITION
+/*=============================================================*/
+
+u8 DrvFwCtrlGetChipType(void)
+{
+ u8 nChipType = 0;
+
+ DBG("*** %s() ***\n", __func__);
+
+ //DrvPlatformLyrTouchDeviceResetHw();
+
+ // Erase TP Flash first
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(20);
+
+ // Stop MCU
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Disable watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ /////////////////////////
+ // Difference between C2 and C3
+ /////////////////////////
+ // c2:MSG2133(1) c32:MSG2133A(2) c33:MSG2138A(2)
+ // check ic type
+ nChipType = RegGet16BitValue(0x1ECC) & 0xFF;
+
+ if (nChipType != CHIP_TYPE_MSG21XX && // (0x01)
+ nChipType != CHIP_TYPE_MSG21XXA && // (0x02)
+ nChipType != CHIP_TYPE_MSG26XXM && // (0x03)
+ nChipType != CHIP_TYPE_MSG22XX) // (0x7A)
+ {
+ nChipType = 0;
+ }
+
+ DBG("*** Chip Type = 0x%x ***\n", nChipType);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ return nChipType;
+}
+
+void DrvFwCtrlGetCustomerFirmwareVersion(u16 *pMajor, u16 *pMinor, u8 **ppVersion)
+{
+ DBG("*** %s() ***\n", __func__);
+
+ if (g_ChipType == CHIP_TYPE_MSG21XXA || g_ChipType == CHIP_TYPE_MSG21XX)
+ {
+ u8 szDbBusTxData[3] = {0};
+ u8 szDbBusRxData[4] = {0};
+
+ szDbBusTxData[0] = 0x53;
+ szDbBusTxData[1] = 0x00;
+
+ if (g_ChipType == CHIP_TYPE_MSG21XXA)
+ {
+ szDbBusTxData[2] = 0x2A;
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG21XX)
+ {
+ szDbBusTxData[2] = 0x74;
+ }
+ else
+ {
+ szDbBusTxData[2] = 0x2A;
+ }
+
+ mutex_lock(&g_Mutex);
+
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 3);
+ IicReadData(SLAVE_I2C_ID_DWI2C, &szDbBusRxData[0], 4);
+
+ mutex_unlock(&g_Mutex);
+
+ *pMajor = (szDbBusRxData[1]<<8) + szDbBusRxData[0];
+ *pMinor = (szDbBusRxData[3]<<8) + szDbBusRxData[2];
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ u16 nRegData1, nRegData2;
+
+ mutex_lock(&g_Mutex);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(100);
+
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ // RIU password
+ RegSet16BitValue(0x161A, 0xABBA);
+
+ // Clear pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ RegSet16BitValue(0x1600, 0xBFF4); // Set start address for customer firmware version on main block
+
+ // Enable burst mode
+// RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01));
+
+ // Set pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x40));
+
+ RegSetLByteValue(0x160E, 0x01);
+
+ nRegData1 = RegGet16BitValue(0x1604);
+ nRegData2 = RegGet16BitValue(0x1606);
+
+ *pMajor = (((nRegData1 >> 8) & 0xFF) << 8) + (nRegData1 & 0xFF);
+ *pMinor = (((nRegData2 >> 8) & 0xFF) << 8) + (nRegData2 & 0xFF);
+
+ // Clear burst mode
+// RegSet16BitValue(0x160C, RegGet16BitValue(0x160C) & (~0x01));
+
+ RegSet16BitValue(0x1600, 0x0000);
+
+ // Clear RIU password
+ RegSet16BitValue(0x161A, 0x0000);
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ DrvPlatformLyrTouchDeviceResetHw();
+ mdelay(100);
+
+ mutex_unlock(&g_Mutex);
+ }
+
+ DBG("*** major = %d ***\n", *pMajor);
+ DBG("*** minor = %d ***\n", *pMinor);
+
+ if (*ppVersion == NULL)
+ {
+ *ppVersion = kzalloc(sizeof(u8)*6, GFP_KERNEL);
+ }
+
+ sprintf(*ppVersion, "%03d%03d", *pMajor, *pMinor);
+}
+
+void DrvFwCtrlGetPlatformFirmwareVersion(u8 **ppVersion)
+{
+ u32 i;
+ u16 nRegData1, nRegData2;
+ u8 szDbBusRxData[12] = {0};
+
+ DBG("*** %s() ***\n", __func__);
+
+ mutex_lock(&g_Mutex);
+
+ DrvPlatformLyrTouchDeviceResetHw();
+
+ DbBusEnterSerialDebugMode();
+ DbBusStopMCU();
+ DbBusIICUseBus();
+ DbBusIICReshape();
+ mdelay(100);
+
+ if (g_ChipType == CHIP_TYPE_MSG22XX) // Only MSG22XX support platform firmware version
+ {
+ // Stop mcu
+ RegSetLByteValue(0x0FE6, 0x01);
+
+ // Stop watchdog
+ RegSet16BitValue(0x3C60, 0xAA55);
+
+ // RIU password
+ RegSet16BitValue(0x161A, 0xABBA);
+
+ // Clear pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x80));
+
+ RegSet16BitValue(0x1600, 0xC1F2); // Set start address for platform firmware version on info block(Actually, start reading from 0xC1F0)
+
+ // Enable burst mode
+ RegSet16BitValue(0x160C, (RegGet16BitValue(0x160C) | 0x01));
+
+ // Set pce
+ RegSet16BitValue(0x1618, (RegGet16BitValue(0x1618) | 0x40));
+
+ for (i = 0; i < 3; i ++)
+ {
+ RegSetLByteValue(0x160E, 0x01);
+
+ nRegData1 = RegGet16BitValue(0x1604);
+ nRegData2 = RegGet16BitValue(0x1606);
+
+ szDbBusRxData[i*4+0] = (nRegData1 & 0xFF);
+ szDbBusRxData[i*4+1] = ((nRegData1 >> 8 ) & 0xFF);
+
+// DBG("szDbBusRxData[%d] = 0x%x , %c \n", i*4+0, szDbBusRxData[i*4+0], szDbBusRxData[i*4+0]); // add for debug
+// DBG("szDbBusRxData[%d] = 0x%x , %c \n", i*4+1, szDbBusRxData[i*4+1], szDbBusRxData[i*4+1]); // add for debug
+
+ szDbBusRxData[i*4+2] = (nRegData2 & 0xFF);
+ szDbBusRxData[i*4+3] = ((nRegData2 >> 8 ) & 0xFF);
+
+// DBG("szDbBusRxData[%d] = 0x%x , %c \n", i*4+2, szDbBusRxData[i*4+2], szDbBusRxData[i*4+2]); // add for debug
+// DBG("szDbBusRxData[%d] = 0x%x , %c \n", i*4+3, szDbBusRxData[i*4+3], szDbBusRxData[i*4+3]); // add for debug
+ }
+
+ // Clear burst mode
+ RegSet16BitValue(0x160C, RegGet16BitValue(0x160C) & (~0x01));
+
+ RegSet16BitValue(0x1600, 0x0000);
+
+ // Clear RIU password
+ RegSet16BitValue(0x161A, 0x0000);
+
+ if (*ppVersion == NULL)
+ {
+ *ppVersion = kzalloc(sizeof(u8)*10, GFP_KERNEL);
+ }
+
+ sprintf(*ppVersion, "%c%c%c%c%c%c%c%c%c%c", szDbBusRxData[2], szDbBusRxData[3], szDbBusRxData[4],
+ szDbBusRxData[5], szDbBusRxData[6], szDbBusRxData[7], szDbBusRxData[8], szDbBusRxData[9], szDbBusRxData[10], szDbBusRxData[11]);
+ }
+ else
+ {
+ if (*ppVersion == NULL)
+ {
+ *ppVersion = kzalloc(sizeof(u8)*10, GFP_KERNEL);
+ }
+
+ sprintf(*ppVersion, "%s", "N/A");
+ }
+
+ DbBusIICNotUseBus();
+ DbBusNotStopMCU();
+ DbBusExitSerialDebugMode();
+
+ DrvPlatformLyrTouchDeviceResetHw();
+ mdelay(100);
+
+ mutex_unlock(&g_Mutex);
+
+ DBG("*** platform firmware version = %s ***\n", *ppVersion);
+}
+
+s32 DrvFwCtrlUpdateFirmware(u8 szFwData[][1024], EmemType_e eEmemType)
+{
+ DBG("*** %s() ***\n", __func__);
+
+ return _DrvFwCtrlUpdateFirmwareCash(szFwData);
+}
+
+void DrvFwCtrlHandleFingerTouch(void)
+{
+ TouchInfo_t tInfo;
+ u32 i;
+ u8 nTouchKeyCode = 0;
+ static u32 nLastKeyCode = 0;
+ u8 *pPacket = NULL;
+ u16 nReportPacketLength = 0;
+
+// DBG("*** %s() ***\n", __func__);
+
+ memset(&tInfo, 0x0, sizeof(tInfo));
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+ if (g_FirmwareMode == FIRMWARE_MODE_DEMO_MODE)
+ {
+ DBG("FIRMWARE_MODE_DEMO_MODE\n");
+
+ nReportPacketLength = DEMO_MODE_PACKET_LENGTH;
+ pPacket = g_DemoModePacket;
+ }
+ else if (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE)
+ {
+ DBG("FIRMWARE_MODE_DEBUG_MODE\n");
+
+ if (g_FirmwareInfo.nLogModePacketHeader != 0x62)
+ {
+ DBG("WRONG DEBUG MODE HEADER : 0x%x\n", g_FirmwareInfo.nLogModePacketHeader);
+ return;
+ }
+
+ if (g_LogModePacket == NULL)
+ {
+ g_LogModePacket = kzalloc(sizeof(u8)*g_FirmwareInfo.nLogModePacketLength, GFP_KERNEL);
+ }
+
+ nReportPacketLength = g_FirmwareInfo.nLogModePacketLength;
+ pPacket = g_LogModePacket;
+ }
+ else if (g_FirmwareMode == FIRMWARE_MODE_RAW_DATA_MODE)
+ {
+ DBG("FIRMWARE_MODE_RAW_DATA_MODE\n");
+
+ if (g_FirmwareInfo.nLogModePacketHeader != 0x62)
+ {
+ DBG("WRONG RAW DATA MODE HEADER : 0x%x\n", g_FirmwareInfo.nLogModePacketHeader);
+ return;
+ }
+
+ if (g_LogModePacket == NULL)
+ {
+ g_LogModePacket = kzalloc(sizeof(u8)*g_FirmwareInfo.nLogModePacketLength, GFP_KERNEL);
+ }
+
+ nReportPacketLength = g_FirmwareInfo.nLogModePacketLength;
+ pPacket = g_LogModePacket;
+ }
+ else
+ {
+ DBG("WRONG FIRMWARE MODE : 0x%x\n", g_FirmwareMode);
+ return;
+ }
+#else
+ DBG("FIRMWARE_MODE_DEMO_MODE\n");
+
+ nReportPacketLength = DEMO_MODE_PACKET_LENGTH;
+ pPacket = g_DemoModePacket;
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+ if (g_GestureWakeupFlag == 1)
+ {
+ DBG("Set gesture wakeup packet length, g_ChipType=%d\n", g_ChipType);
+
+ if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ if (_gGestureWakeupPacket == NULL)
+ {
+ _gGestureWakeupPacket = kzalloc(sizeof(u8)*GESTURE_WAKEUP_PACKET_LENGTH, GFP_KERNEL);
+ }
+
+ nReportPacketLength = GESTURE_WAKEUP_PACKET_LENGTH;
+ pPacket = _gGestureWakeupPacket;
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG21XXA)
+ {
+ if (_gGestureWakeupPacket == NULL)
+ {
+ _gGestureWakeupPacket = kzalloc(sizeof(u8)*DEMO_MODE_PACKET_LENGTH, GFP_KERNEL);
+ }
+
+ nReportPacketLength = DEMO_MODE_PACKET_LENGTH;
+ pPacket = _gGestureWakeupPacket;
+ }
+ else
+ {
+ DBG("This chip type does not support gesture wakeup.\n");
+ return;
+ }
+ }
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+
+#if defined(CONFIG_TOUCH_DRIVER_RUN_ON_SPRD_PLATFORM)
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+ if (g_GestureWakeupFlag == 1)
+ {
+ u32 i = 0, rc;
+
+ while (i < 5)
+ {
+ mdelay(50);
+
+ rc = IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);
+
+ if (rc > 0)
+ {
+ break;
+ }
+
+ i ++;
+ }
+ }
+ else
+ {
+ IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);
+ }
+#else
+ IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_QCOM_PLATFORM)
+ IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);
+#elif defined(CONFIG_TOUCH_DRIVER_RUN_ON_MTK_PLATFORM)
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaAlloc();
+#endif //CONFIG_ENABLE_DMA_IIC
+ IicReadData(SLAVE_I2C_ID_DWI2C, &pPacket[0], nReportPacketLength);
+#ifdef CONFIG_ENABLE_DMA_IIC
+ DmaFree();
+#endif //CONFIG_ENABLE_DMA_IIC
+#endif
+
+ if (0 == _DrvFwCtrlParsePacket(pPacket, nReportPacketLength, &tInfo))
+ {
+ //report...
+ if ((tInfo.nFingerNum) == 0) //touch end
+ {
+ if (nLastKeyCode != 0)
+ {
+ DBG("key touch released\n");
+
+ input_report_key(g_InputDevice, BTN_TOUCH, 0);
+ input_report_key(g_InputDevice, nLastKeyCode, 0);
+
+ nLastKeyCode = 0; //clear key status..
+ }
+ else
+ {
+ DrvPlatformLyrFingerTouchReleased(0, 0);
+ }
+ }
+ else //touch on screen
+ {
+ if (tInfo.nTouchKeyCode != 0)
+ {
+#ifdef CONFIG_TP_HAVE_KEY
+ if (tInfo.nTouchKeyCode == 4) // TOUCH_KEY_HOME
+ {
+ nTouchKeyCode = g_TpVirtualKey[1];
+ }
+ else if (tInfo.nTouchKeyCode == 1) // TOUCH_KEY_MENU
+ {
+ nTouchKeyCode = g_TpVirtualKey[0];
+ }
+ else if (tInfo.nTouchKeyCode == 2) // TOUCH_KEY_BACK
+ {
+ nTouchKeyCode = g_TpVirtualKey[2];
+ }
+ else if (tInfo.nTouchKeyCode == 8) // TOUCH_KEY_SEARCH
+ {
+ nTouchKeyCode = g_TpVirtualKey[3];
+ }
+
+ if (nLastKeyCode != nTouchKeyCode)
+ {
+ DBG("key touch pressed\n");
+ DBG("nTouchKeyCode = %d, nLastKeyCode = %d\n", nTouchKeyCode, nLastKeyCode);
+
+ nLastKeyCode = nTouchKeyCode;
+
+ input_report_key(g_InputDevice, BTN_TOUCH, 1);
+ input_report_key(g_InputDevice, nTouchKeyCode, 1);
+ }
+#endif //CONFIG_TP_HAVE_KEY
+ }
+ else
+ {
+ DBG("tInfo->nFingerNum = %d...............\n", tInfo.nFingerNum);
+
+ for (i = 0; i < tInfo.nFingerNum; i ++)
+ {
+ DrvPlatformLyrFingerTouchPressed(tInfo.tPoint[i].nX, tInfo.tPoint[i].nY, 0, 0);
+ }
+ }
+ }
+
+ input_sync(g_InputDevice);
+ }
+}
+
+//------------------------------------------------------------------------------//
+
+#ifdef CONFIG_ENABLE_GESTURE_WAKEUP
+
+void DrvFwCtrlOpenGestureWakeup(u16 nMode)
+{
+ u8 szDbBusTxData[3] = {0};
+ u32 i = 0;
+ s32 rc;
+
+ DBG("*** %s() ***\n", __func__);
+
+ DBG("wakeup mode = 0x%x\n", nMode);
+
+ szDbBusTxData[0] = 0x58;
+ szDbBusTxData[1] = (nMode >> 8) & 0xFF;
+ szDbBusTxData[2] = nMode & 0xFF;
+
+ while (i < 5)
+ {
+ rc = IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 3);
+
+ if (rc > 0)
+ {
+ DBG("Enable gesture wakeup success\n");
+ break;
+ }
+
+ i ++;
+ }
+
+ if (i == 5)
+ {
+ DBG("Enable gesture wakeup failed\n");
+ }
+/*
+ rc = IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 3);
+ if (rc < 0)
+ {
+ DBG("Enable gesture wakeup failed\n");
+ }
+ else
+ {
+ DBG("Enable gesture wakeup success\n");
+ }
+*/
+ g_GestureWakeupFlag = 1; // gesture wakeup is enabled
+}
+
+void DrvFwCtrlCloseGestureWakeup(void)
+{
+// u8 szDbBusTxData[3] = {0};
+// s32 rc;
+
+ DBG("*** %s() ***\n", __func__);
+/*
+ szDbBusTxData[0] = 0x58;
+ szDbBusTxData[1] = 0x00;
+ szDbBusTxData[2] = 0x00;
+
+ rc = IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 3);
+ if (rc < 0)
+ {
+ DBG("Disable gesture wakeup failed\n");
+ }
+ else
+ {
+ DBG("Disable gesture wakeup success\n");
+ }
+*/
+ g_GestureWakeupFlag = 0; // gesture wakeup is disabled
+}
+
+#endif //CONFIG_ENABLE_GESTURE_WAKEUP
+
+//------------------------------------------------------------------------------//
+
+#ifdef CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+u16 DrvFwCtrlChangeFirmwareMode(u16 nMode)
+{
+ u8 szDbBusTxData[2] = {0};
+
+ DBG("*** %s() ***\n", __func__);
+
+ szDbBusTxData[0] = 0x02;
+ szDbBusTxData[1] = (u8)nMode;
+
+ mdelay(20);
+
+ mutex_lock(&g_Mutex);
+
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 2);
+
+ mutex_unlock(&g_Mutex);
+
+ return nMode;
+}
+
+void DrvFwCtrlGetFirmwareInfo(FirmwareInfo_t *pInfo)
+{
+ u8 szDbBusTxData[1] = {0};
+ u8 szDbBusRxData[8] = {0};
+
+ DBG("*** %s() ***\n", __func__);
+
+ szDbBusTxData[0] = 0x01;
+
+ mutex_lock(&g_Mutex);
+
+ mdelay(300);
+ IicWriteData(SLAVE_I2C_ID_DWI2C, &szDbBusTxData[0], 1);
+ mdelay(20);
+ IicReadData(SLAVE_I2C_ID_DWI2C, &szDbBusRxData[0], 8);
+
+ mutex_unlock(&g_Mutex);
+
+ if ((szDbBusRxData[1] & 0x80) == 0x80)
+ {
+ pInfo->nIsCanChangeFirmwareMode = 0;
+ }
+ else
+ {
+ pInfo->nIsCanChangeFirmwareMode = 1;
+ }
+
+ pInfo->nFirmwareMode = szDbBusRxData[1] & 0x7F;
+ pInfo->nLogModePacketHeader = szDbBusRxData[2];
+ pInfo->nLogModePacketLength = (szDbBusRxData[3]<<8) + szDbBusRxData[4];
+
+ DBG("pInfo->nFirmwareMode=0x%x, pInfo->nLogModePacketHeader=0x%x, pInfo->nLogModePacketLength=%d, pInfo->nIsCanChangeFirmwareMode=%d\n", pInfo->nFirmwareMode, pInfo->nLogModePacketHeader, pInfo->nLogModePacketLength, pInfo->nIsCanChangeFirmwareMode);
+}
+
+void DrvFwCtrlRestoreFirmwareModeToLogDataMode(void)
+{
+ FirmwareInfo_t tInfo;
+
+ DBG("*** %s() ***\n", __func__);
+
+ memset(&tInfo, 0x0, sizeof(FirmwareInfo_t));
+
+ DrvFwCtrlGetFirmwareInfo(&tInfo);
+
+ DBG("g_FirmwareMode = 0x%x, tInfo.nFirmwareMode = 0x%x\n", g_FirmwareMode, tInfo.nFirmwareMode);
+
+ // Since reset_hw() will reset the firmware mode to demo mode, we must reset the firmware mode again after reset_hw().
+ if (g_FirmwareMode == FIRMWARE_MODE_DEBUG_MODE && FIRMWARE_MODE_DEBUG_MODE != tInfo.nFirmwareMode)
+ {
+ g_FirmwareMode = DrvFwCtrlChangeFirmwareMode(FIRMWARE_MODE_DEBUG_MODE);
+ }
+ else if (g_FirmwareMode == FIRMWARE_MODE_RAW_DATA_MODE && FIRMWARE_MODE_RAW_DATA_MODE != tInfo.nFirmwareMode)
+ {
+ g_FirmwareMode = DrvFwCtrlChangeFirmwareMode(FIRMWARE_MODE_RAW_DATA_MODE);
+ }
+ else
+ {
+ DBG("firmware mode is not restored\n");
+ }
+}
+#endif //CONFIG_ENABLE_FIRMWARE_DATA_LOG
+
+//------------------------------------------------------------------------------//
+
+#ifdef CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+
+void DrvFwCtrlCheckFirmwareUpdateBySwId(void)
+{
+ if (g_ChipType == CHIP_TYPE_MSG21XXA)
+ {
+ _DrvFwCtrlMsg21xxaCheckFirmwareUpdateBySwId();
+ }
+ else if (g_ChipType == CHIP_TYPE_MSG22XX)
+ {
+ _DrvFwCtrlMsg22xxCheckFirmwareUpdateBySwId();
+ }
+ else
+ {
+ DBG("This chip type (%d) does not support update firmware by sw id\n", g_ChipType);
+ }
+}
+
+#endif //CONFIG_UPDATE_FIRMWARE_BY_SW_ID
+
+//------------------------------------------------------------------------------//