#ifndef __LINUX_MSTAR_MSG2133_TS_H__
#define __LINUX_MSTAR_MSG2133_TS_H__
//#define TS_DEBUG_MSG 1
#define VIRTUAL_KEYS 1 //是否有按键
#define MSG2133_UPDATE 1 //T卡升级功能
#define TS_WIDTH_MAX 480 //LCD分辨率
#define TS_HEIGHT_MAX 800 //LCD分辨率 //使用虚拟按键,也不需要把这个分辨率提高到按键区域。
#define TS_ENPIN_LEVEL 0 //ENPIN(ResetPin)电压,如果TP上有反相MOS管,则设为1
#define MSG2133_BUS_NUM 2
#define MSG2133_TS_NAME "msg2133"
#define MSG2133_TS_ADDR 0x26
#define MSG2133_FW_ADDR 0x62
#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 {
u16 x1;
u16 y1;
u16 x2;
u16 y2;
u8 touch_point;
};
struct msg2133_ts_data {
struct input_dev *input_dev;
struct ts_event event;
struct work_struct pen_event_work;
struct workqueue_struct *ts_workqueue;
struct early_suspend early_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 DATE AUTHOR
* 1.0 2010-01-05 WenFS
*
* note: only support mulititouch Wenfs 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_HOME 102
#define MSG2312_KEY_MENU 229
#define MSG2312_KEY_BACK 158
#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");