#ifndef __LINUX_MSTAR_MSG2133_TS_H__
#define __LINUX_MSTAR_MSG2133_TS_H__

//#define TS_DEBUG_MSG 1
#define VIRTUAL_KEYS1//是否有按键
#define MSG2133_UPDATE1//T卡升级功能

#define TS_WIDTH_MAX480//LCD分辨率
#defineTS_HEIGHT_MAX800//LCD分辨率 //使用虚拟按键,也不需要把这个分辨率提高到按键区域。

#defineTS_ENPIN_LEVEL0//ENPIN(ResetPin)电压,如果TP上有反相MOS管,则设为1

#define MSG2133_BUS_NUM2
#define MSG2133_TS_NAME "msg2133"
#define MSG2133_TS_ADDR0x26
#define MSG2133_FW_ADDR0x62
#define MSG2133_FW_UPDATE_ADDR 0x49


#define TPD_OK 0
#define TPD_REG_BASE 0x00
#define TPD_SOFT_RESET_MODE 0x01
#define TPD_OP_MODE 0x00
#define TPD_LOW_PWR_MODE 0x04
#define TPD_SYSINFO_MODE 0x10

#define GET_HSTMODE(reg) ((reg & 0x70) >> 4) // in op mode or not
#define GET_BOOTLOADERMODE(reg) ((reg & 0x10) >> 4) // in bl mode


struct ts_event {
u16x1;
u16y1;
u16x2;
u16y2;
u8 touch_point;
};

struct msg2133_ts_data {
struct input_dev*input_dev;
struct ts_eventevent;
struct work_struct pen_event_work;
struct workqueue_struct *ts_workqueue;
struct early_suspendearly_suspend;
};

struct TouchScreenInfo_t{
unsigned char nTouchKeyMode;
unsigned char nTouchKeyCode;
//unsigned char nFingerNum;
} ;

#endif // end of __LINUX_MSTAR_MSG2133_TS_H__

================== 分割线 ======================================

/*
* drivers/input/touchscreen/msg2133_ts.c
*
* MStar msg2133 TouchScreen driver.
*
* Copyright (c) 2012 MStar Semiconductor, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* VERSION DATEAUTHOR
* 1.0 2010-01-05WenFS
*
* note: only support mulititouchWenfs 2010-10-01
*/

#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/earlysuspend.h>
#include <linux/interrupt.h>
#include <linux/delay.h>

#include <linux/firmware.h>
#include <linux/platform_device.h>

#include <linux/slab.h>

#include <mach/ldo.h>

#include "msg2133.h"


#define TS_DEBUG_MSG 1// use MSG2133_DBG

#if TS_DEBUG_MSG
#define MSG2133_DBG(format, ...)printk(KERN_INFO "MSG2133 " format "\n", ## __VA_ARGS__)
#else
#define MSG2133_DBG(format, ...)
#endif

extern int sprd_3rdparty_gpio_tp_rst;
extern int sprd_3rdparty_gpio_tp_irq;


static struct i2c_client *this_client;
static struct i2c_board_info msg2133_i2c_boardinfo = {
I2C_BOARD_INFO(MSG2133_TS_NAME, MSG2133_TS_ADDR),
};

static void msg2133_device_power_on();


#ifdef MSG2133_UPDATE

struct class *firmware_class;
struct device *firmware_cmd_dev;
static int update_switch = 0;
static int FwDataCnt;
static char *fw_version;
static unsigned char temp[94][1024];


static void msg2133_reset()
{
gpio_set_value(sprd_3rdparty_gpio_tp_rst, TS_ENPIN_LEVEL);
msg2133_device_power_on();
msleep(20);
gpio_set_value(sprd_3rdparty_gpio_tp_rst,!TS_ENPIN_LEVEL);
msleep(500);
}


static bool msg2133_i2c_read(char *pbt_buf, int dw_lenth)
{
int ret;
//MSG2133_DBG("The msg_i2c_client->addr=0x%x\n",i2c_client->addr);
ret = i2c_master_recv(this_client, pbt_buf, dw_lenth);

if(ret <= 0){
MSG2133_DBG("msg_i2c_read_interface error\n");
return false;
}

return true;
}

static bool msg2133_i2c_write(char *pbt_buf, int dw_lenth)
{
int ret;
//MSG2133_DBG("The msg_i2c_client->addr=0x%x\n",i2c_client->addr);
ret = i2c_master_send(this_client, pbt_buf, dw_lenth);

if(ret <= 0){
MSG2133_DBG("msg_i2c_read_interface error\n");
return false;
}

return true;
}


static void i2c_read_msg2133(unsigned char *pbt_buf, int dw_lenth)
{
this_client->addr = MSG2133_FW_ADDR;
i2c_master_recv(this_client, pbt_buf, dw_lenth);//0xC5_8bit
this_client->addr = MSG2133_TS_ADDR;
}

static void i2c_write_msg2133(unsigned char *pbt_buf, int dw_lenth)
{

this_client->addr = MSG2133_FW_ADDR;
i2c_master_send(this_client, pbt_buf, dw_lenth);//0xC4_8bit
this_client->addr = MSG2133_TS_ADDR;
}

static void i2c_read_update_msg2133(unsigned char *pbt_buf, int dw_lenth)
{

this_client->addr = MSG2133_FW_UPDATE_ADDR;
i2c_master_recv(this_client, pbt_buf, dw_lenth);//0x93_8bit
this_client->addr = MSG2133_TS_ADDR;
}

static void i2c_write_update_msg2133(unsigned char *pbt_buf, int dw_lenth)
{
this_client->addr = MSG2133_FW_UPDATE_ADDR;
i2c_master_send(this_client, pbt_buf, dw_lenth);//0x92_8bit
this_client->addr = MSG2133_TS_ADDR;
}

void dbbusDWIICEnterSerialDebugMode(void)
{
unsigned char data[5];
// Enter the Serial Debug Mode
data[0] = 0x53;
data[1] = 0x45;
data[2] = 0x52;
data[3] = 0x44;
data[4] = 0x42;
i2c_write_msg2133(data, 5);
}

void dbbusDWIICStopMCU(void)
{
unsigned char data[1];
// Stop the MCU
data[0] = 0x37;
i2c_write_msg2133(data, 1);
}

void dbbusDWIICIICUseBus(void)
{
unsigned char data[1];
// IIC Use Bus
data[0] = 0x35;
i2c_write_msg2133(data, 1);
}

void dbbusDWIICIICReshape(void)
{
unsigned char data[1];
// IIC Re-shape
data[0] = 0x71;
i2c_write_msg2133(data, 1);
}

void dbbusDWIICIICNotUseBus(void)
{
unsigned char data[1];
// IIC Not Use Bus
data[0] = 0x34;
i2c_write_msg2133(data, 1);
}

void dbbusDWIICNotStopMCU(void)
{
unsigned char data[1];
// Not Stop the MCU
data[0] = 0x36;
i2c_write_msg2133(data, 1);
}

void dbbusDWIICExitSerialDebugMode(void)
{
unsigned char data[1];
// Exit the Serial Debug Mode
data[0] = 0x45;
i2c_write_msg2133(data, 1);
// Delay some interval to guard the next transaction
}

void drvISP_EntryIspMode(void)
{
unsigned char bWriteData[5] =
{
0x4D, 0x53, 0x54, 0x41, 0x52
};
i2c_write_update_msg2133(bWriteData, 5);
msleep(10); // delay about 10ms
}

void drvISP_WriteEnable(void)
{
unsigned char bWriteData[2] =
{
0x10, 0x06
};
unsigned char bWriteData1 = 0x12;
i2c_write_update_msg2133(bWriteData, 2);
i2c_write_update_msg2133(&bWriteData1, 1);
}

unsigned char drvISP_Read(unsigned char n, unsigned char *pDataToRead) //First it needs send 0x11 to notify we want to get flash data back.
{
unsigned char Read_cmd = 0x11;
unsigned char i = 0;
unsigned char dbbus_rx_data[16] = {0};
i2c_write_update_msg2133(&Read_cmd, 1);
//if (n == 1)
{
i2c_read_update_msg2133(&dbbus_rx_data[0], n + 1);

for(i = 0; i < n; i++)
{
*(pDataToRead + i) = dbbus_rx_data[i + 1];
}
}
//else
{
// i2c_read_update_msg2133(pDataToRead, n);
}
return 0;
}

unsigned char drvISP_ReadStatus(void)
{
unsigned char bReadData = 0;
unsigned char bWriteData[2] =
{
0x10, 0x05
};
unsigned char bWriteData1 = 0x12;
// msleep(1); // delay about 100us
i2c_write_update_msg2133(bWriteData, 2);
// msleep(1); // delay about 100us
drvISP_Read(1, &bReadData);
// msleep(10); // delay about 10ms
i2c_write_update_msg2133(&bWriteData1, 1);
return bReadData;
}

void drvISP_BlockErase(unsigned int addr)
{
unsigned char bWriteData[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned char bWriteData1 = 0x12;
unsigned int timeOutCount=0;

drvISP_WriteEnable();
//Enable write status register
bWriteData[0] = 0x10;
bWriteData[1] = 0x50;
i2c_write_update_msg2133(bWriteData, 2);
i2c_write_update_msg2133(&bWriteData1, 1);
//Write Status
bWriteData[0] = 0x10;
bWriteData[1] = 0x01;
bWriteData[2] = 0x00;
i2c_write_update_msg2133(bWriteData, 3);
i2c_write_update_msg2133(&bWriteData1, 1);
//Write disable
bWriteData[0] = 0x10;
bWriteData[1] = 0x04;
i2c_write_update_msg2133(bWriteData, 2);
i2c_write_update_msg2133(&bWriteData1, 1);

timeOutCount=0;
msleep(1); // delay about 100us
while((drvISP_ReadStatus() & 0x01) == 0x01)
{
timeOutCount++;
if ( timeOutCount > 10000 )
break; /* around 1 sec timeout */
}

//pr_ch("The drvISP_ReadStatus3=%d\n", drvISP_ReadStatus());
drvISP_WriteEnable();
//pr_ch("The drvISP_ReadStatus4=%d\n", drvISP_ReadStatus());
bWriteData[0] = 0x10;
bWriteData[1] = 0xC7; //Block Erase
//bWriteData[2] = ((addr >> 16) & 0xFF) ;
//bWriteData[3] = ((addr >> 8) & 0xFF) ;
// bWriteData[4] = (addr & 0xFF) ;
i2c_write_update_msg2133(bWriteData, 2);
//i2c_write_update_msg2133( &bWriteData, 5);
i2c_write_update_msg2133(&bWriteData1, 1);

timeOutCount=0;
msleep(1); // delay about 100us
while((drvISP_ReadStatus() & 0x01) == 0x01)
{
timeOutCount++;
if ( timeOutCount > 10000 )
break; /* around 1 sec timeout */
}
}

void drvISP_Program(unsigned short k, unsigned char *pDataToWrite)
{
unsigned short i = 0;
unsigned short j = 0;
//U16 n = 0;
unsigned char TX_data[133];
unsigned char bWriteData1 = 0x12;
unsigned int addr = k * 1024;
#if 1

for(j = 0; j < 8; j++) //128*8 cycle
{
TX_data[0] = 0x10;
TX_data[1] = 0x02;// Page Program CMD
TX_data[2] = (addr + 128 * j) >> 16;
TX_data[3] = (addr + 128 * j) >> 8;
TX_data[4] = (addr + 128 * j);

for(i = 0; i < 128; i++)
{
TX_data[5 + i] = pDataToWrite[j * 128 + i];
}

while((drvISP_ReadStatus() & 0x01) == 0x01)
{
; //wait until not in write operation
}

drvISP_WriteEnable();
i2c_write_update_msg2133( TX_data, 133); //write 133 byte per cycle
i2c_write_update_msg2133(&bWriteData1, 1);
}

#else

for(j = 0; j < 512; j++) //128*8 cycle
{
TX_data[0] = 0x10;
TX_data[1] = 0x02;// Page Program CMD
TX_data[2] = (addr + 2 * j) >> 16;
TX_data[3] = (addr + 2 * j) >> 8;
TX_data[4] = (addr + 2 * j);

for(i = 0; i < 2; i++)
{
TX_data[5 + i] = pDataToWrite[j * 2 + i];
}

while((drvISP_ReadStatus() & 0x01) == 0x01)
{
; //wait until not in write operation
}

drvISP_WriteEnable();
i2c_write_update_msg2133(TX_data, 7); //write 7 byte per cycle
i2c_write_update_msg2133(&bWriteData1, 1);
}

#endif
}

void drvISP_ExitIspMode(void)
{
unsigned char bWriteData = 0x24;
i2c_write_update_msg2133(&bWriteData, 1);
}


static ssize_t firmware_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
printk("tyd-tp: firmware_version_show\n");
MSG2133_DBG("*** firmware_version_show fw_version = %s***\n", fw_version);
return sprintf(buf, "%s\n", fw_version);
}

static ssize_t firmware_version_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
unsigned char dbbus_tx_data[3];
unsigned char dbbus_rx_data[4] ;
unsigned short major = 0, minor = 0;
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICStopMCU();
dbbusDWIICIICUseBus();
dbbusDWIICIICReshape();
fw_version = kzalloc(sizeof(char), GFP_KERNEL);
MSG2133_DBG("\n");
printk("tyd-tp: firmware_version_store\n");
//Get_Chip_Version();
dbbus_tx_data[0] = 0x53;
dbbus_tx_data[1] = 0x00;
dbbus_tx_data[2] = 0x74;
//i2c_write(TOUCH_ADDR_MSG20XX, &dbbus_tx_data[0], 3);
//i2c_read(TOUCH_ADDR_MSG20XX, &dbbus_rx_data[0], 4);
msg2133_i2c_write(&dbbus_tx_data[0], 3);
msg2133_i2c_read(&dbbus_rx_data[0], 4);
major = (dbbus_rx_data[1] << 8) + dbbus_rx_data[0];
minor = (dbbus_rx_data[3] << 8) + dbbus_rx_data[2];
MSG2133_DBG("***major = %d ***\n", major);
MSG2133_DBG("***minor = %d ***\n", minor);
sprintf(fw_version, "%03d%03d", major, minor);
MSG2133_DBG("***fw_version = %s ***\n", fw_version);
return size;
}

static ssize_t firmware_update_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
printk("tyd-tp: firmware_update_show\n");
return sprintf(buf, "%s\n", fw_version);
}

static ssize_t firmware_update_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t size)
{
unsigned char i;
unsigned char dbbus_tx_data[4];
unsigned char dbbus_rx_data[2] = {0};
update_switch = 1;
//drvISP_EntryIspMode();
//drvISP_BlockErase(0x00000);
//M by cheehwa _HalTscrHWReset();

//关闭中断
disable_irq_nosync(this_client->irq);

msg2133_reset();
//msctpc_LoopDelay ( 100 ); // delay about 100ms*****
// Enable slave's ISP ECO mode
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICStopMCU();
dbbusDWIICIICUseBus();
dbbusDWIICIICReshape();
//pr_ch("dbbusDWIICIICReshape\n");
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x08;
dbbus_tx_data[2] = 0x0c;
dbbus_tx_data[3] = 0x08;
// Disable the Watchdog
i2c_write_msg2133(dbbus_tx_data, 4);
//Get_Chip_Version();
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x11;
dbbus_tx_data[2] = 0xE2;
dbbus_tx_data[3] = 0x00;
i2c_write_msg2133(dbbus_tx_data, 4);
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x3C;
dbbus_tx_data[2] = 0x60;
dbbus_tx_data[3] = 0x55;
i2c_write_msg2133(dbbus_tx_data, 4);
//pr_ch("update\n");
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x3C;
dbbus_tx_data[2] = 0x61;
dbbus_tx_data[3] = 0xAA;
i2c_write_msg2133(dbbus_tx_data, 4);
//Stop MCU
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x0F;
dbbus_tx_data[2] = 0xE6;
dbbus_tx_data[3] = 0x01;
i2c_write_msg2133(dbbus_tx_data, 4);
//Enable SPI Pad
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x02;
i2c_write_msg2133(dbbus_tx_data, 3);
i2c_read_msg2133(&dbbus_rx_data[0], 2);
//pr_tp("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);
dbbus_tx_data[3] = (dbbus_rx_data[0] | 0x20); //Set Bit 5
i2c_write_msg2133(dbbus_tx_data, 4);
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x25;
i2c_write_msg2133(dbbus_tx_data, 3);
dbbus_rx_data[0] = 0;
dbbus_rx_data[1] = 0;
i2c_read_msg2133(&dbbus_rx_data[0], 2);
//pr_tp("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);
dbbus_tx_data[3] = dbbus_rx_data[0] & 0xFC; //Clear Bit 1,0
i2c_write_msg2133(dbbus_tx_data, 4);
/*
//------------
// ISP Speed Change to 400K
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x11;
dbbus_tx_data[2] = 0xE2;
i2c_write_msg2133( dbbus_tx_data, 3);
i2c_read_msg2133( &dbbus_rx_data[3], 1);
//pr_tp("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);
dbbus_tx_data[3] = dbbus_tx_data[3]&0xf7; //Clear Bit3
i2c_write_msg2133( dbbus_tx_data, 4);
*/
//WP overwrite
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x0E;
dbbus_tx_data[3] = 0x02;
i2c_write_msg2133(dbbus_tx_data, 4);
//set pin high
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x10;
dbbus_tx_data[3] = 0x08;
i2c_write_msg2133(dbbus_tx_data, 4);
dbbusDWIICIICNotUseBus();
dbbusDWIICNotStopMCU();
dbbusDWIICExitSerialDebugMode();
///////////////////////////////////////
// Start to load firmware
///////////////////////////////////////
drvISP_EntryIspMode();
MSG2133_DBG("entryisp\n");
drvISP_BlockErase(0x00000);
//msleep(1000);
MSG2133_DBG("FwVersion=2");

for(i = 0; i < 94; i++) // total 94 KB : 1 byte per R/W
{
//msleep(1);//delay_100us
MSG2133_DBG("drvISP_Program\n");
drvISP_Program(i, temp[i]); // program to slave's flash
//pr_ch("drvISP_Verify\n");
//drvISP_Verify ( i, temp[i] ); //verify data
}

//MSG2133_DBG("update OK\n");
drvISP_ExitIspMode();
FwDataCnt = 0;
msg2133_reset();
MSG2133_DBG("update OK\n");
update_switch = 0;
//打开中断
enable_irq(this_client->irq);
return size;
}

static ssize_t firmware_data_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
printk("tyd-tp: firmware_data_show\n");
return FwDataCnt;
}

static ssize_t firmware_data_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
int i;
MSG2133_DBG("***FwDataCnt = %d ***\n", FwDataCnt);
printk("tyd-tp: firmware_data_store\n");
for(i = 0; i < 1024; i++)
{
memcpy(temp[FwDataCnt], buf, 1024);
}

FwDataCnt++;
return size;
}

static ssize_t firmware_clear_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned short k = 0, i = 0, j = 0;
unsigned char bWriteData[5] =
{
0x10, 0x03, 0, 0, 0
};
unsigned char RX_data[256];
unsigned char bWriteData1 = 0x12;
unsigned int addr = 0;
MSG2133_DBG("\n");
printk("tyd-tp: firmware_clear_show\n");
for(k = 0; k < 94; i++) // total 94 KB : 1 byte per R/W
{
addr = k * 1024;

for(j = 0; j < 8; j++) //128*8 cycle
{
bWriteData[2] = (unsigned char)((addr + j * 128) >> 16);
bWriteData[3] = (unsigned char)((addr + j * 128) >> 8);
bWriteData[4] = (unsigned char)(addr + j * 128);

while((drvISP_ReadStatus() & 0x01) == 0x01)
{
; //wait until not in write operation
}

i2c_write_update_msg2133(bWriteData, 5); //write read flash addr
drvISP_Read(128, RX_data);
i2c_write_update_msg2133(&bWriteData1, 1); //cmd end

for(i = 0; i < 128; i++) //log out if verify error{
if(RX_data[i] != 0xFF){
MSG2133_DBG("k=%d,j=%d,i=%d===============erase not clean================", k, j, i);
}
}
}
MSG2133_DBG("read finish\n");
return sprintf(buf, "%s\n", fw_version);
}

static ssize_t firmware_clear_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
unsigned char dbbus_tx_data[4];
unsigned char dbbus_rx_data[2] = {0};
//msctpc_LoopDelay ( 100 ); // delay about 100ms*****
// Enable slave's ISP ECO mode
/*
dbbusDWIICEnterSerialDebugMode();
dbbusDWIICStopMCU();
dbbusDWIICIICUseBus();
dbbusDWIICIICReshape();*/
MSG2133_DBG("\n");
printk("tyd-tp: firmware_clear_store\n");
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x08;
dbbus_tx_data[2] = 0x0c;
dbbus_tx_data[3] = 0x08;
// Disable the Watchdog
i2c_write_msg2133(dbbus_tx_data, 4);
//Get_Chip_Version();
//FwVersion = 2;
//if (FwVersion == 2)
{
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x11;
dbbus_tx_data[2] = 0xE2;
dbbus_tx_data[3] = 0x00;
i2c_write_msg2133(dbbus_tx_data, 4);
}
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x3C;
dbbus_tx_data[2] = 0x60;
dbbus_tx_data[3] = 0x55;
i2c_write_msg2133(dbbus_tx_data, 4);
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x3C;
dbbus_tx_data[2] = 0x61;
dbbus_tx_data[3] = 0xAA;
i2c_write_msg2133(dbbus_tx_data, 4);
//Stop MCU
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x0F;
dbbus_tx_data[2] = 0xE6;
dbbus_tx_data[3] = 0x01;
i2c_write_msg2133(dbbus_tx_data, 4);
//Enable SPI Pad
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x02;
i2c_write_msg2133(dbbus_tx_data, 3);
i2c_read_msg2133(&dbbus_rx_data[0], 2);
MSG2133_DBG("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);
dbbus_tx_data[3] = (dbbus_rx_data[0] | 0x20); //Set Bit 5
i2c_write_msg2133(dbbus_tx_data, 4);
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x25;
i2c_write_msg2133(dbbus_tx_data, 3);
dbbus_rx_data[0] = 0;
dbbus_rx_data[1] = 0;
i2c_read_msg2133(&dbbus_rx_data[0], 2);
MSG2133_DBG("dbbus_rx_data[0]=0x%x", dbbus_rx_data[0]);
dbbus_tx_data[3] = dbbus_rx_data[0] & 0xFC; //Clear Bit 1,0
i2c_write_msg2133(dbbus_tx_data, 4);
//WP overwrite
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x0E;
dbbus_tx_data[3] = 0x02;
i2c_write_msg2133(dbbus_tx_data, 4);
//set pin high
dbbus_tx_data[0] = 0x10;
dbbus_tx_data[1] = 0x1E;
dbbus_tx_data[2] = 0x10;
dbbus_tx_data[3] = 0x08;
i2c_write_msg2133(dbbus_tx_data, 4);
dbbusDWIICIICNotUseBus();
dbbusDWIICNotStopMCU();
dbbusDWIICExitSerialDebugMode();
///////////////////////////////////////
// Start to load firmware
///////////////////////////////////////
drvISP_EntryIspMode();
MSG2133_DBG("chip erase+\n");
drvISP_BlockErase(0x00000);
MSG2133_DBG("chip erase-\n");
drvISP_ExitIspMode();
return size;
}

static DEVICE_ATTR(version, 0777, firmware_version_show, firmware_version_store);
static DEVICE_ATTR(update, 0777, firmware_update_show, firmware_update_store);
static DEVICE_ATTR(data, 0777, firmware_data_show, firmware_data_store);
static DEVICE_ATTR(clear, 0777, firmware_clear_show, firmware_clear_store);

void msg2133_init_class()
{
firmware_class = class_create(THIS_MODULE,"mtk-tpd" );//client->name

if(IS_ERR(firmware_class))
pr_err("Failed to create class(firmware)!\n");

firmware_cmd_dev = device_create(firmware_class,
NULL, 0, NULL, "device");//device

if(IS_ERR(firmware_cmd_dev))
pr_err("Failed to create device(firmware_cmd_dev)!\n");

// version /sys/class/mtk-tpd/device/version
if(device_create_file(firmware_cmd_dev, &dev_attr_version) < 0)
pr_err("Failed to create device file(%s)!\n", dev_attr_version.attr.name);

// update /sys/class/mtk-tpd/device/update
if(device_create_file(firmware_cmd_dev, &dev_attr_update) < 0)
pr_err("Failed to create device file(%s)!\n", dev_attr_update.attr.name);

// data /sys/class/mtk-tpd/device/data
if(device_create_file(firmware_cmd_dev, &dev_attr_data) < 0)
pr_err("Failed to create device file(%s)!\n", dev_attr_data.attr.name);

// clear /sys/class/mtk-tpd/device/clear
if(device_create_file(firmware_cmd_dev, &dev_attr_clear) < 0)
pr_err("Failed to create device file(%s)!\n", dev_attr_clear.attr.name);
}

#endif //endif MSG2133_UPDATE

static void msg2133_device_power_on()
{
LDO_SetVoltLevel(LDO_LDO_SIM2, LDO_VOLT_LEVEL0);
LDO_TurnOnLDO(LDO_LDO_SIM2);

MSG2133_DBG("msg2133: power on\n");
}

static void msg2133_device_power_off()
{
//LDO_TurnOffLDO(LDO_LDO_SIM2);
MSG2133_DBG("msg2133: power off\n");
}


#ifdef VIRTUAL_KEYS

/*
#define MSG2312_KEY_HOME102
#define MSG2312_KEY_MENU229
#define MSG2312_KEY_BACK158
#define MSG2312_KEY_SEARCH 127

static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
return sprintf(buf,
__stringify(EV_KEY) ":" __stringify(MSG2312_KEY_HOME) ":180:900:64:60"
":" __stringify(EV_KEY) ":" __stringify(MSG2312_KEY_MENU) ":80:900:64:60"
":" __stringify(EV_KEY) ":" __stringify(MSG2312_KEY_BACK) ":280:900:64:60"
":" __stringify(EV_KEY) ":" __stringify(MSG2312_KEY_SEARCH) ":380:900:64:60"
"\n");

}
*/

static ssize_t virtual_keys_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
return sprintf(buf,
__stringify(EV_KEY) ":" __stringify(KEY_HOME) ":180:900:64:60"
":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":80:900:64:60"
":" __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":280:900:64:60"
":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":380:900:64:60"
"\n");
}


static struct kobj_attribute virtual_keys_attr = {
.attr = {
.name = "virtualkeys.msg2133",
.mode = S_IRUGO,
},
.show = &virtual_keys_show,
};

static struct attribute *properties_attrs[] = {
&virtual_keys_attr.attr,
NULL
};

static struct attribute_group properties_attr_group = {
.attrs = properties_attrs,
};

static void virtual_keys_init(void)
{
int ret;
struct kobject *properties_kobj;

MSG2133_DBG("%s\n",__func__);

properties_kobj = kobject_create_and_add("board_properties", NULL);
if (properties_kobj)
ret = sysfs_create_group(properties_kobj,
&properties_attr_group);
if (!properties_kobj || ret)
pr_err("failed to create board_properties\n");
}
#endif

unsigned char msg2133_check_sum(unsigned char *pval)
{
int i, sum = 0;

for(i = 0; i < 7; i++)
{
sum += pval[i];
}

return (unsigned char)((-sum) & 0xFF);
}

static int msg2133_read_data(struct i2c_client *client)
{

int ret, keycode;
unsigned char reg_val[8] = {0};
int dst_x=0,dst_y=0,xysawp_temp=0;
unsigned int temp_checksum;
struct TouchScreenInfo_t touchData;
struct msg2133_ts_data *data = i2c_get_clientdata(this_client);
struct ts_event *event = &data->event;

event->touch_point = 0;
ret = i2c_master_recv(client, reg_val, 8);
MSG2133_DBG("dxf::%s: ret = %d\n", __func__, ret);
if(ret <= 0)
return ret;

event->x1 = ((reg_val[1] & 0xF0) << 4) | reg_val[2];
event->y1 = ((reg_val[1] & 0x0F) << 8) | reg_val[3];
dst_x = ((reg_val[4] & 0xF0) << 4) | reg_val[5];
dst_y = ((reg_val[4] & 0x0F) << 8) | reg_val[6];


temp_checksum = msg2133_check_sum(reg_val);
// if check not ok , discard this point
if((temp_checksum != reg_val[7]) || (reg_val[0] != 0x52) ){
return 0;
}
else
{
if ((reg_val[1] == 0xFF) && (reg_val[2] == 0xFF) && (reg_val[3] == 0xFF) && (reg_val[4] == 0xFF) && (reg_val[6] == 0xFF))
{
event->x1 = 0; // final X coordinate
event->y1 = 0; // final Y coordinate

if((reg_val[5]==0x0)||(reg_val[5]==0xFF)){
event->touch_point = 0; //touch end
touchData.nTouchKeyCode = 0; //TouchKeyMode
touchData.nTouchKeyMode = 0; //TouchKeyMode
keycode=0;
}else// if have key down
{
touchData.nTouchKeyMode = 1; //TouchKeyMode
touchData.nTouchKeyCode = reg_val[5]; //TouchKeyCode
keycode= reg_val[5];
MSG2133_DBG("dxf:: %s: keycode = %d -----------\n", __func__, keycode);
#if 1
// keyset, by duanxufang-----
if(keycode==1){ // keycode==1 --> menu key
event->x1 = 80; // final X coordinate
event->y1 = 900; // final Y coordinate

}else if(keycode==2){ // keycode==2 --> home key
event->x1 = 180; // final X coordinate
event->y1 = 900; // final Y coordinate

}else if(keycode==4){ // keycode==4 --> back key
event->x1 = 280; // final X coordinate
event->y1 = 900; // final Y coordinate

}else{// keycode == 8 --> search key

event->x1 = 380; // final X coordinate
event->y1 = 900; // final Y coordinate
}
#endif
event->touch_point = 1;
}
}else
{// if touch on screen
touchData.nTouchKeyMode = 0; //Touch on screen...

if ((dst_x == 0) && (dst_y == 0)){
event->touch_point = 1; //one touch
MSG2133_DBG("dxf:: %s: event->touch_point = %d\n", __func__, event->touch_point);
#if 0
xysawp_temp=cinfo->x1;
cinfo->x1=2047-cinfo->y1;
cinfo->y1=xysawp_temp;
#endif
event->x1 = (event->x1 * TS_WIDTH_MAX) / 2048;
event->y1 = (event->y1 * TS_HEIGHT_MAX) / 2048;
}else{
event->touch_point = 2; //two touch
MSG2133_DBG("dxf:: %s: event->touch_point = %d\n", __func__, event->touch_point);
if (dst_x > 2048) { //transform the unsigh value to sign value
dst_x -= 4096;
}
if (dst_y > 2048){
dst_y -= 4096;
}

event->x2 = (event->x1 + dst_x);
event->y2 = (event->y1 + dst_y);

#if 0
xysawp_temp=cinfo->x1;
cinfo->x1=2047-cinfo->y1;
cinfo->y1=xysawp_temp;

xysawp_temp=cinfo->x2;
cinfo->x2=2047-cinfo->y2;
cinfo->y2=xysawp_temp;
#endif
//convert to screen resolution
event->x1 = (event->x1 * TS_WIDTH_MAX) / 2048;
event->y1 = (event->y1 * TS_HEIGHT_MAX) / 2048;

event->x2 = (event->x2 * TS_WIDTH_MAX) / 2048;
event->y2 = (event->y2 * TS_HEIGHT_MAX) / 2048;

}
}
return 1;
}//if((temp_checksum != reg_val[7]) || (reg_val[0] != 0x52) )

return 1;

}

static void msg2133_report_value(struct i2c_client *client)
{
struct msg2133_ts_data *data = i2c_get_clientdata(this_client);
struct ts_event *event = &data->event;

MSG2133_DBG("%s, point = %d\n", __func__, event->touch_point);
if(event->touch_point){
//input_report_key(data->input_dev, BTN_TOUCH, 1);// commented by dxf
switch(event->touch_point) {
case 2:
MSG2133_DBG("%s, ::::x2=%d, y2=%d ::::\n", __func__, event->x2, event->y2);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 15);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x2);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y2);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);

case 1:
MSG2133_DBG("%s, ::::x1=%d, y1=%d::::\n", __func__, event->x1, event->y1);
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 15);
input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->x1);
input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->y1);
input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_mt_sync(data->input_dev);

default:
//MSG2133_DBG("==touch_point default =\n");
break;
}
}else{// if event->touch_point==0
//input_report_key(data->input_dev, BTN_TOUCH, 0); //commented by dxf
input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
}

input_sync(data->input_dev); // active
}/*end msg2133_report_value*/

static void msg2133_ts_pen_irq_work(struct work_struct *work)
{
int ret = -1;
MSG2133_DBG("%s\n", __func__);
ret = msg2133_read_data(this_client);
MSG2133_DBG("%s, ret = %d\n", __func__, ret);
if (ret) {
msg2133_report_value(this_client);
}
enable_irq(this_client->irq);

}

static irqreturn_t msg2133_ts_interrupt(int irq, void *dev_id)
{
struct msg2133_ts_data *msg2133_ts = (struct msg2133_ts_data *)dev_id;

MSG2133_DBG("%s\n", __func__);

disable_irq_nosync(this_client->irq);
if (!work_pending(&msg2133_ts->pen_event_work)) {
queue_work(msg2133_ts->ts_workqueue, &msg2133_ts->pen_event_work);
}

return IRQ_HANDLED;
}

static void msg2133_ts_suspend(struct early_suspend *handler)
{
MSG2133_DBG("==%s==\n", __func__);
disable_irq_nosync(this_client->irq);
msleep(3);
gpio_set_value(sprd_3rdparty_gpio_tp_rst, TS_ENPIN_LEVEL);
msleep(10);

msg2133_device_power_off();
}

static void msg2133_ts_resume(struct early_suspend *handler)
{
MSG2133_DBG("==%s==start==\n", __func__);
gpio_set_value(sprd_3rdparty_gpio_tp_rst, TS_ENPIN_LEVEL);
msg2133_device_power_on();
msleep(20);
gpio_set_value(sprd_3rdparty_gpio_tp_rst,!TS_ENPIN_LEVEL);
msleep(100);
enable_irq(this_client->irq);
}

static int msg2133_ts_config_pins(void)
{
int msg2133_irq;

gpio_direction_output(sprd_3rdparty_gpio_tp_rst, 1);
gpio_direction_input(sprd_3rdparty_gpio_tp_irq);
gpio_set_value(sprd_3rdparty_gpio_tp_rst, !TS_ENPIN_LEVEL);

msg2133_irq=sprd_alloc_gpio_irq(sprd_3rdparty_gpio_tp_irq);

msleep(10); //wait for stable
return msg2133_irq;
}


static int msg2133_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct msg2133_ts_data *msg2133_ts;
struct input_dev *input_dev;
int err = 0;

MSG2133_DBG("%s\n", __func__);

this_client = client;
client->irq = msg2133_ts_config_pins();

msg2133_device_power_on();

if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit_check_functionality_failed;
}

msg2133_ts = kzalloc(sizeof(*msg2133_ts), GFP_KERNEL);
if (!msg2133_ts){
err = -ENOMEM;
goto exit_alloc_data_failed;
}

i2c_set_clientdata(client, msg2133_ts);

MSG2133_DBG("I2C addr=%x", client->addr);

INIT_WORK(&msg2133_ts->pen_event_work, msg2133_ts_pen_irq_work);

msg2133_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev));
if (!msg2133_ts->ts_workqueue) {
err = -ESRCH;
goto exit_create_singlethread;
}

//MSG2133_DBG("==request_irq=\n");
MSG2133_DBG("%s: %s IRQ number is %d", __func__, client->name, client->irq);
err = request_irq(client->irq, msg2133_ts_interrupt, IRQF_TRIGGER_FALLING, client->name, msg2133_ts);
if (err < 0) {
MSG2133_DBG("%s: msg2133_probe: request irq failed\n", __func__);
goto exit_irq_request_failed;
}

disable_irq(client->irq);

//MSG2133_DBG("==input_allocate_device=\n");
input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
MSG2133_DBG("%s: failed to allocate input device\n", __func__);
goto exit_input_dev_alloc_failed;
}

msg2133_ts->input_dev = input_dev;

__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_SYN, input_dev->evbit);


__set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
__set_bit(ABS_MT_POSITION_X, input_dev->absbit);
__set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
__set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);

#ifdef VIRTUAL_KEYS
__set_bit(KEY_MENU, input_dev->keybit);
__set_bit(KEY_BACK, input_dev->keybit);
__set_bit(KEY_HOME, input_dev->keybit);
__set_bit(KEY_SEARCH, input_dev->keybit);
#endif

input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, TS_WIDTH_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, TS_HEIGHT_MAX, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);

input_dev->name= MSG2133_TS_NAME;//dev_name(&client->dev)
err = input_register_device(input_dev);
if (err) {
dev_err(&client->dev,
"msg2133_ts_probe: failed to register input device: %s\n",
dev_name(&client->dev));
goto exit_input_register_device_failed;
}

MSG2133_DBG("==register_early_suspend =");
msg2133_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
msg2133_ts->early_suspend.suspend = msg2133_ts_suspend;
msg2133_ts->early_suspend.resume= msg2133_ts_resume;
register_early_suspend(&msg2133_ts->early_suspend);

msleep(50);
//get some register information

#ifdef MSG2133_UPDATE
msg2133_init_class();
#endif

#ifdef VIRTUAL_KEYS
virtual_keys_init();
#endif

enable_irq(client->irq);

return 0;

exit_input_register_device_failed:
input_free_device(input_dev);
exit_input_dev_alloc_failed:
free_irq(client->irq, msg2133_ts);
exit_irq_request_failed:
cancel_work_sync(&msg2133_ts->pen_event_work);
destroy_workqueue(msg2133_ts->ts_workqueue);
exit_create_singlethread:
MSG2133_DBG("==singlethread error =\n");
i2c_set_clientdata(client, NULL);
kfree(msg2133_ts);
exit_alloc_data_failed:
exit_check_functionality_failed:
sprd_free_gpio_irq(client->irq);
return err;
}

static int __devexit msg2133_ts_remove(struct i2c_client *client)
{

struct msg2133_ts_data *msg2133_ts = i2c_get_clientdata(client);

MSG2133_DBG("==msg2133_ts_remove=\n");

unregister_early_suspend(&msg2133_ts->early_suspend);
free_irq(client->irq, msg2133_ts);
sprd_free_gpio_irq(this_client->irq);
input_unregister_device(msg2133_ts->input_dev);
kfree(msg2133_ts);
cancel_work_sync(&msg2133_ts->pen_event_work);
destroy_workqueue(msg2133_ts->ts_workqueue);
i2c_set_clientdata(client, NULL);

msg2133_device_power_off();
return 0;
}

static const struct i2c_device_id msg2133_ts_id[] = {
{ MSG2133_TS_NAME, 0 },{ }
};

MODULE_DEVICE_TABLE(i2c, msg2133_ts_id);

static struct i2c_driver msg2133_ts_driver = {
.probe= msg2133_ts_probe,
.remove= __devexit_p(msg2133_ts_remove),
.id_table= msg2133_ts_id,
.driver= {
.name= "MSG2133",
//.name= MSG2133_TS_NAME, // msg2133_ts_driver.name 不一定要跟虚拟按键的 MSG2133_TS_NAME 一样。也就是说名字不一样,按键部分也可以正常工作。
.owner= THIS_MODULE,
},
};

int msg2133_add_i2c_device(struct i2c_board_info *info)
{
int err;
struct i2c_adapter *adapter;
struct i2c_client *client;

adapter = i2c_get_adapter(MSG2133_BUS_NUM);
if (!adapter) {
MSG2133_DBG("%s: can't get i2c adapter %d\n",
__func__, MSG2133_BUS_NUM);
err = -ENODEV;
goto err_driver;
}

client = i2c_new_device(adapter, info);
if (!client) {
MSG2133_DBG("%s: can't add i2c device at 0x%x\n",
__func__, (unsigned int)info->addr);
err = -ENODEV;
goto err_driver;
}

i2c_put_adapter(adapter);

return 0;

err_driver:
return err;
}

static int __init msg2133_init_module(void)
{
MSG2133_DBG("%s\n", __func__);

msg2133_add_i2c_device(&msg2133_i2c_boardinfo);
return i2c_add_driver(&msg2133_ts_driver);
}

static void __exit msg2133_exit_module(void)
{
MSG2133_DBG("%s\n", __func__);
i2c_unregister_device(this_client);
i2c_del_driver(&msg2133_ts_driver);

}

module_init(msg2133_init_module);
module_exit(msg2133_exit_module);

MODULE_LICENSE("GPL");

更多相关文章

  1. Android(安卓)中判断是否存在虚拟按键
  2. Android(安卓)修改默认按键不震动
  3. Android的dialog控制焦点导致其后Activity不响应
  4. android竖直seekbar
  5. Android系统的开机画面显示过程分析(7)
  6. Android之根据手机屏幕分辨率(px与dp互换)
  7. 安卓5.1屏蔽recent_apps
  8. Android(安卓)MTK 修改TP参数
  9. Android(安卓)7.1 导航栏增加按键

随机推荐

  1. use '@foo' to launch a virtual device
  2. 深入浅出 - Android系统移植与平台开发(七
  3. Android(安卓)Drawable Resource学习(一)、
  4. 【Unity3D】与Android相互传递消息
  5. android中的recovery模式
  6. Application Fundamentals
  7. android测试
  8. android自制的软件如何添加到打开方式
  9. EditText单行显示
  10. android 处理运行时改变 开发文档翻译