mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
tp: vtl new driver
This commit is contained in:
@@ -416,16 +416,13 @@
|
||||
|
||||
&i2c4 {
|
||||
status = "okay";
|
||||
|
||||
ts@01 {
|
||||
compatible = "ct,ct36x";
|
||||
compatible = "ct,vtl_ts";
|
||||
reg = <0x01>;
|
||||
ct-model = <363>;
|
||||
touch-gpio = <&gpio7 GPIO_A6 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpio = <&gpio7 GPIO_A5 GPIO_ACTIVE_HIGH>;
|
||||
max-x = <2048>;
|
||||
max-y = <1536>;
|
||||
orientation=<1 0 0 1>;
|
||||
screen_max_x = <2048>;
|
||||
screen_max_y = <1536>;
|
||||
irq_gpio_number = <&gpio7 GPIO_A6 IRQ_TYPE_LEVEL_LOW>;
|
||||
rst_gpio_number = <&gpio7 GPIO_A5 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -512,14 +512,12 @@
|
||||
};
|
||||
|
||||
ts@01 {
|
||||
compatible = "ct,ct36x";
|
||||
compatible = "ct,vtl_ts";
|
||||
reg = <0x01>;
|
||||
ct-model = <365>;
|
||||
touch-gpio = <&gpio7 GPIO_A6 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpio = <&gpio7 GPIO_A5 GPIO_ACTIVE_HIGH>;
|
||||
max-x = <1280>;
|
||||
max-y = <800>;
|
||||
orientation=<1 0 0 1>;
|
||||
screen_max_x = <2048>;
|
||||
screen_max_y = <1536>;
|
||||
irq_gpio_number = <&gpio7 GPIO_A6 IRQ_TYPE_LEVEL_LOW>;
|
||||
rst_gpio_number = <&gpio7 GPIO_A5 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ CONFIG_TABLET_USB_KBTAB=y
|
||||
CONFIG_TABLET_USB_WACOM=y
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_GT8XX=y
|
||||
CONFIG_CT36X_TS=y
|
||||
CONFIG_TOUCHSCREEN_VTL_CT36X=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_KEYCHORD=y
|
||||
CONFIG_INPUT_RICOH619_PWRKEY=y
|
||||
|
||||
@@ -19,8 +19,11 @@ config TOUCHSCREEN_GT8XX
|
||||
code includes that in its table of IIC devices.
|
||||
If unsure, say N.
|
||||
|
||||
config CT36X_TS
|
||||
config TOUCHSCREEN_CT36X_TS
|
||||
tristate "CT36X touchscreens support"
|
||||
|
||||
config TOUCHSCREEN_VTL_CT36X
|
||||
tristate "VTL touchscreens support"
|
||||
|
||||
config TOUCHSCREEN_88PM860X
|
||||
tristate "Marvell 88PM860x touchscreen"
|
||||
|
||||
3
drivers/input/touchscreen/Makefile
Normal file → Executable file
3
drivers/input/touchscreen/Makefile
Normal file → Executable file
@@ -5,7 +5,7 @@
|
||||
# Each configuration option enables a list of files.
|
||||
|
||||
wm97xx-ts-y := wm97xx-core.o
|
||||
obj-y += ct36x/
|
||||
obj-$(CONFIG_TOUCHSCREEN_CT36X_TS) += ct36x/
|
||||
obj-$(CONFIG_TOUCHSCREEN_GT8XX) += rk29_i2c_goodix.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
|
||||
@@ -73,3 +73,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_VTL_CT36X) += vtl_ts/
|
||||
8
drivers/input/touchscreen/vtl_ts/Makefile
Executable file
8
drivers/input/touchscreen/vtl_ts/Makefile
Executable file
@@ -0,0 +1,8 @@
|
||||
|
||||
obj-$(CONFIG_TOUCHSCREEN_VTL_CT36X) += vtl_ts_ct36x.o
|
||||
#obj-y += vtl_ts_ct36x.o
|
||||
|
||||
vtl_ts_ct36x-y +=vtl_ts.o
|
||||
vtl_ts_ct36x-y +=chip.o
|
||||
vtl_ts_ct36x-y +=apk.o
|
||||
|
||||
231
drivers/input/touchscreen/vtl_ts/apk.c
Executable file
231
drivers/input/touchscreen/vtl_ts/apk.c
Executable file
@@ -0,0 +1,231 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "vtl_ts.h"
|
||||
#include "chip.h"
|
||||
|
||||
#define APK_ITOUCH 0x01
|
||||
|
||||
#define INVALID 0x00
|
||||
#define HW_RESET_CMD 0x01
|
||||
#define CHIP_INFO_CMD 0x02
|
||||
#define DRIVER_INFO_CMD 0x03
|
||||
#define CHIP_ID_CMD 0x04
|
||||
#define WRITE_CHIP_CMD 0x05
|
||||
#define READ_CHIP_CMD 0x06
|
||||
#define RECOVERY_CMD 0x07
|
||||
#define INTERRUPT_CMD 0x08
|
||||
#define READ_CHECKSUM_CMD 0x09
|
||||
#define READ_FWCHECKSUM_CMD 0x0a
|
||||
#define XY_DEBUG_CMD 0x0b
|
||||
|
||||
|
||||
#define LINUX_SHELL 'c'
|
||||
#define SHELL_CHECKSUM_CMD '1'
|
||||
#define SHELL_UPDATE_CMD '2'
|
||||
#define SHELL_DEBUG_CMD '3'
|
||||
|
||||
|
||||
|
||||
static struct ts_info * ts_object = NULL;
|
||||
|
||||
/*****************************************************************************
|
||||
** Function define
|
||||
*****************************************************************************/
|
||||
static int apk_i2c_transfer(struct i2c_client *client,unsigned char i2c_addr,unsigned char len,unsigned char *buf,unsigned char rw)
|
||||
{
|
||||
struct i2c_msg msgs[1];
|
||||
|
||||
DEBUG();
|
||||
|
||||
msgs[0].flags = rw;
|
||||
msgs[0].addr = i2c_addr;
|
||||
msgs[0].len = len;
|
||||
msgs[0].buf = buf;
|
||||
msgs[0].scl_rate = TS_I2C_SPEED; //only for rockchip
|
||||
|
||||
if(i2c_transfer(client->adapter, msgs, 1)!= 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int apk_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
printk("___%s___\n",__func__);
|
||||
DEBUG();
|
||||
|
||||
ts_object = vtl_ts_get_object();
|
||||
if(ts_object == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apk_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
printk("___%s___\n",__func__);
|
||||
DEBUG();
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int apk_write(struct file *file, const char __user *buff, size_t count, loff_t *offp)
|
||||
{
|
||||
struct i2c_client *client = ts_object->driver->client;
|
||||
unsigned char frame_data[255] = {0};
|
||||
int bin_checksum = 0;
|
||||
int fw_checksum = 0;
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
if(copy_from_user(frame_data, buff, count)){
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if(frame_data[0]==APK_ITOUCH){
|
||||
|
||||
switch(frame_data[1]){
|
||||
|
||||
case HW_RESET_CMD :{
|
||||
vtl_ts_hw_reset();
|
||||
}break;
|
||||
|
||||
case INTERRUPT_CMD :{
|
||||
if(frame_data[4]){
|
||||
enable_irq(ts_object->config_info.irq_number);
|
||||
}else{
|
||||
disable_irq(ts_object->config_info.irq_number);
|
||||
}
|
||||
}break;
|
||||
|
||||
case RECOVERY_CMD :{
|
||||
ret = update(client);
|
||||
}break;
|
||||
|
||||
case WRITE_CHIP_CMD:{
|
||||
ret = apk_i2c_transfer(client,frame_data[2],frame_data[3],&frame_data[4],0);
|
||||
}break;
|
||||
|
||||
case XY_DEBUG_CMD :{
|
||||
if(ts_object->debug){
|
||||
ts_object->debug = 0x00;
|
||||
}else{
|
||||
ts_object->debug = 0x01;
|
||||
}
|
||||
}break;
|
||||
|
||||
default :{
|
||||
|
||||
}break;
|
||||
}
|
||||
}else if(frame_data[0]==LINUX_SHELL){
|
||||
printk("CMD: %s,count = %d\n",frame_data,count);
|
||||
switch(frame_data[1]){
|
||||
case SHELL_CHECKSUM_CMD :{
|
||||
chip_get_checksum(client,&bin_checksum,&fw_checksum);
|
||||
printk("bin_checksum = 0x%x,fw_checksum = 0x%x\n",bin_checksum,fw_checksum);
|
||||
}break;
|
||||
|
||||
case SHELL_UPDATE_CMD :{
|
||||
chip_update(client);
|
||||
}break;
|
||||
|
||||
case SHELL_DEBUG_CMD :{
|
||||
if(ts_object->debug){
|
||||
ts_object->debug = 0x00;
|
||||
}else{
|
||||
ts_object->debug = 0x01;
|
||||
}
|
||||
|
||||
}break;
|
||||
|
||||
default :{
|
||||
|
||||
}break;
|
||||
}
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
if(ret<0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int apk_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
|
||||
{
|
||||
struct i2c_client *client = ts_object->driver->client;
|
||||
unsigned char frame_data[255];
|
||||
int bin_checksum = 0;
|
||||
int fw_checksum = 0;
|
||||
int len = 0;
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
if(copy_from_user(frame_data, buff, count))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
len = frame_data[3];
|
||||
if(frame_data[0]==APK_ITOUCH){
|
||||
|
||||
switch(frame_data[1]){
|
||||
case DRIVER_INFO_CMD :{
|
||||
frame_data[0] = client->addr;
|
||||
}break;
|
||||
|
||||
case READ_CHIP_CMD :{
|
||||
|
||||
ret = apk_i2c_transfer(client,frame_data[2],frame_data[3],frame_data,1);
|
||||
}break;
|
||||
|
||||
case READ_CHECKSUM_CMD :{
|
||||
ret = chip_get_checksum(client,&bin_checksum,&fw_checksum);
|
||||
frame_data[0] = bin_checksum & 0x00ff;
|
||||
frame_data[1] = bin_checksum >> 8;
|
||||
frame_data[2] = fw_checksum & 0x00ff;
|
||||
frame_data[3] = fw_checksum >> 8;
|
||||
}break;
|
||||
case READ_FWCHECKSUM_CMD :{
|
||||
ret = chip_get_fwchksum(client,&fw_checksum);
|
||||
frame_data[0] = fw_checksum & 0x00ff;
|
||||
frame_data[1] = fw_checksum >> 8;
|
||||
}break;
|
||||
|
||||
default :{
|
||||
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
if(copy_to_user(buff, frame_data,len)){
|
||||
return -EFAULT;
|
||||
};
|
||||
if(ret<0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
struct file_operations apk_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = apk_open,
|
||||
.release = apk_close,
|
||||
.write = apk_write,
|
||||
.read = apk_read,
|
||||
};
|
||||
|
||||
6
drivers/input/touchscreen/vtl_ts/apk.h
Executable file
6
drivers/input/touchscreen/vtl_ts/apk.h
Executable file
@@ -0,0 +1,6 @@
|
||||
#ifndef _APK_H_
|
||||
#define _APK_H_
|
||||
|
||||
extern struct file_operations apk_fops;
|
||||
|
||||
#endif
|
||||
856
drivers/input/touchscreen/vtl_ts/chip.c
Executable file
856
drivers/input/touchscreen/vtl_ts/chip.c
Executable file
@@ -0,0 +1,856 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
|
||||
#include "vtl_ts.h"
|
||||
|
||||
#define FLASH_I2C_ADDR 0X7F
|
||||
#define CHIP_ID_ADDR 0xf000
|
||||
#define RW_FLAG 0xff
|
||||
|
||||
#define CHIP_WRITE_FLASH_CMD 0x55
|
||||
#define CHIP_FLASH_SOURCE_SIZE 8
|
||||
|
||||
|
||||
struct chip_cmd {
|
||||
unsigned short addr;
|
||||
unsigned char data;
|
||||
};
|
||||
|
||||
|
||||
static struct ts_info * ts_object = NULL;
|
||||
static struct chip_cmd (*chip) = NULL;
|
||||
|
||||
|
||||
static unsigned char binary_data[] = {
|
||||
#include "lx--js77_97_CT365_V01_E7DA_130419.dat"
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
enum cmd_index {
|
||||
|
||||
FW_VERSION = 0X00,
|
||||
FW_CHECKSUM_CMD,
|
||||
FW_CHECKSUM_VAL,
|
||||
CHIP_SLEEP,
|
||||
CHIP_ID_CMD,
|
||||
|
||||
/***********flash***********/
|
||||
FLASH_SECTOR_ERASE_CMD,
|
||||
FLASH_SECTOR_NUM,
|
||||
FLASH_SECTOR_SIZE,
|
||||
FLASH_MASS_ERASE_CMD
|
||||
};
|
||||
|
||||
static struct chip_cmd ct360_cmd[] = {
|
||||
{0x0f2a,RW_FLAG}, //fw version
|
||||
|
||||
{0x0fff,0xe1}, //fw checksum cmd
|
||||
{0x0a0d,RW_FLAG}, //fw checksum val
|
||||
|
||||
{0x0f2b,0x00}, //chip sleep cmd
|
||||
|
||||
{0xf000,RW_FLAG}, //chip id cmd
|
||||
|
||||
/************flash*************/
|
||||
{0x33,RW_FLAG}, //FLASH_SECTOR_ERASE_CMD
|
||||
{8,RW_FLAG}, //FLASH_SECTOR_NUM
|
||||
{2048,RW_FLAG}, //FLASH_SECTOR_SIZE
|
||||
{RW_FLAG,RW_FLAG}, //FLASH_MASS_ERASE_CMD
|
||||
};
|
||||
|
||||
static struct chip_cmd ct36x_cmd[] = {
|
||||
{0x3fff,RW_FLAG}, //fw version
|
||||
|
||||
{0x8fff,0xe1}, //fw checksum cmd
|
||||
{0x8e0e,RW_FLAG}, //fw checksum val
|
||||
|
||||
{0x8fff,0xaf}, //chip sleep cmd
|
||||
|
||||
{0xf000,RW_FLAG}, //chip id cmd
|
||||
|
||||
/************flash*************/
|
||||
{0x30,RW_FLAG}, //FLASH_SECTOR_ERASE_CMD
|
||||
{256,RW_FLAG}, //FLASH_SECTOR_NUM
|
||||
{128,RW_FLAG}, //FLASH_SECTOR_SIZE
|
||||
{0x33,RW_FLAG}, //FLASH_MASS_ERASE_CMD
|
||||
};
|
||||
|
||||
#if 0
|
||||
unsigned int ct36x_cmd[4][2] = {
|
||||
{0x3fff,0x00}, //fw version
|
||||
|
||||
{0x0fff,0xe1}, //fw checksum cmd
|
||||
{0x0a0d,0x00}, //fw checksum val
|
||||
|
||||
{0x8fff,0xaf},//chip sleep cmd
|
||||
};
|
||||
|
||||
unsigned int (*chip)[2] = ct36x_cmd;
|
||||
#endif
|
||||
|
||||
|
||||
static int chip_i2c_read(struct i2c_client *client, __u16 addr, __u8 *buf, __u16 len)
|
||||
{
|
||||
struct i2c_msg msgs;
|
||||
int ret;
|
||||
|
||||
DEBUG();
|
||||
msgs.addr = addr;
|
||||
msgs.flags = 0x01; // 0x00: write 0x01:read
|
||||
msgs.len = len;
|
||||
msgs.buf = buf;
|
||||
//#if(PLATFORM == ROCKCHIP)
|
||||
msgs.scl_rate = TS_I2C_SPEED;
|
||||
//#endif
|
||||
|
||||
ret = i2c_transfer(client->adapter, &msgs, 1);
|
||||
if(ret != 1){
|
||||
printk("___%s:i2c read error___\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_i2c_write(struct i2c_client *client, __u16 addr, __u8 *buf, __u16 len)
|
||||
{
|
||||
struct i2c_msg msgs;
|
||||
int ret;
|
||||
|
||||
DEBUG();
|
||||
msgs.addr = addr;
|
||||
msgs.flags = 0x00; // 0x00: write 0x01:read
|
||||
msgs.len = len;
|
||||
msgs.buf = buf;
|
||||
//#if(PLATFORM == ROCKCHIP)
|
||||
msgs.scl_rate = TS_I2C_SPEED;
|
||||
//#endif
|
||||
|
||||
ret = i2c_transfer(client->adapter, &msgs, 1);
|
||||
if(ret != 1){
|
||||
printk("___%s:i2c write error___\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int chip_ram_write_1byte(unsigned short addr,unsigned char data)
|
||||
{
|
||||
struct i2c_client *client = ts_object->driver->client;
|
||||
unsigned char buf[3];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
buf[0] = 0xff;
|
||||
buf[1] = addr >> 8;
|
||||
buf[2] = addr & 0x00ff;
|
||||
//printk("addr = %x,buf[0] = %x,buf[1] = %x,buf[2] = %x,data = %x\n",addr,buf[0],buf[1],buf[2],data);
|
||||
ret = chip_i2c_write(client, client->addr, buf,3);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
udelay(10);
|
||||
buf[0] = 0x00;
|
||||
buf[1] = data;
|
||||
ret = chip_i2c_write(client, client->addr, buf,2);
|
||||
udelay(10);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int chip_ram_read(unsigned short addr,unsigned char *rx_buf,unsigned short len)
|
||||
{
|
||||
struct i2c_client *client = ts_object->driver->client;
|
||||
unsigned char buf[3];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
buf[0] = 0xff;
|
||||
buf[1] = addr >> 8;
|
||||
buf[2] = addr & 0x00ff;
|
||||
//printk("addr = %x,buf[0] = %x,buf[1] = %x,buf[2] = %x\n",addr,buf[0],buf[1],buf[2]);
|
||||
ret = chip_i2c_write(client, client->addr, buf,3);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
udelay(10);
|
||||
buf[0] = 0x00;
|
||||
ret = chip_i2c_write(client, client->addr, buf,1);
|
||||
udelay(10);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
udelay(10);
|
||||
ret = chip_i2c_read(client,client->addr,rx_buf,len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int chip_get_fw_version(unsigned char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
ret = chip_ram_read(chip[FW_VERSION].addr,buf,1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int chip_get_chip_id(unsigned char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
ret = chip_ram_read(chip[CHIP_ID_CMD].addr,buf,1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int chip_enter_sleep_mode(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
if(chip == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
ret = chip_ram_write_1byte(chip[CHIP_SLEEP].addr,chip[CHIP_SLEEP].data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int chip_function(enum cmd_index cmd_index,unsigned char *rx_buf,unsigned char len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
if(chip[cmd_index].data != RW_FLAG) //write
|
||||
{
|
||||
ret = chip_ram_write_1byte(chip[cmd_index].addr,chip[cmd_index].data);
|
||||
}
|
||||
else //read
|
||||
{
|
||||
ret = chip_ram_read(chip[cmd_index].addr,rx_buf,len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************flash********************/
|
||||
|
||||
static int chip_flash_init(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
ret = chip_i2c_write(client, FLASH_I2C_ADDR, buf,2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int chip_read_bus_status(struct i2c_client *client,unsigned char *rx_buf)
|
||||
{
|
||||
unsigned char buf[1];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
buf[0] = 0x00;
|
||||
ret = chip_i2c_write(client, FLASH_I2C_ADDR, buf,1);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
mdelay(1);
|
||||
ret = chip_i2c_read(client,FLASH_I2C_ADDR,rx_buf,1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int chip_enter_idle_mode(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0xa5;
|
||||
ret = chip_i2c_write(client, FLASH_I2C_ADDR, buf,2);
|
||||
mdelay(5);
|
||||
//mdelay(10);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int chip_solfware_reset(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x5a;
|
||||
ret = chip_i2c_write(client, FLASH_I2C_ADDR, buf,2);
|
||||
msleep(200);//ct36x
|
||||
//msleep(100);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int chip_erase_flash(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
int sec,sec_addr;
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
if(chip[FLASH_MASS_ERASE_CMD].addr == 0x33)//ct36x mass erase
|
||||
{
|
||||
ret = chip_read_bus_status(client,buf);
|
||||
if(buf[0] != 0xaa)
|
||||
{
|
||||
printk("___i2c bus busy,bus_status = %d___\n",buf[0]);
|
||||
return -1;
|
||||
}
|
||||
buf[0] = 0x00;
|
||||
buf[1] = chip[FLASH_MASS_ERASE_CMD].addr;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
ret = chip_i2c_write(client, FLASH_I2C_ADDR, buf,4);
|
||||
if(ret)
|
||||
{
|
||||
printk("vtl chip flash erase fail\n");
|
||||
return ret;
|
||||
}
|
||||
//printk("mass erase\n");
|
||||
//mdelay(10);
|
||||
msleep(10);
|
||||
}
|
||||
else //ct360/ct36x sector erase
|
||||
{
|
||||
for(sec = 0;sec < chip[FLASH_SECTOR_NUM].addr;sec++)
|
||||
{
|
||||
ret = chip_read_bus_status(client,buf);
|
||||
if(buf[0] != 0xaa)
|
||||
{
|
||||
printk("___i2c bus busy,bus_status = %x,sec = %d___\n",buf[0],sec);
|
||||
return -1;
|
||||
}
|
||||
sec_addr = sec * chip[FLASH_SECTOR_SIZE].addr;
|
||||
buf[0] = 0x00;
|
||||
buf[1] = chip[FLASH_SECTOR_ERASE_CMD].addr;
|
||||
buf[2] = sec_addr >> 8;
|
||||
buf[3] = sec_addr & 0x00ff;
|
||||
ret = chip_i2c_write(client, FLASH_I2C_ADDR, buf,4);
|
||||
if(ret)
|
||||
{
|
||||
printk("vtl chip flash erase fail\n");
|
||||
return ret;
|
||||
}
|
||||
//msleep(10);//ct36x
|
||||
msleep(100);//ct360
|
||||
}
|
||||
//printk("sector erase\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_set_code(unsigned int flash_addr, unsigned char *buf)
|
||||
{
|
||||
unsigned char i;
|
||||
|
||||
buf[2] = (flash_addr >> 8);
|
||||
buf[3] = (flash_addr & 0xFF);
|
||||
buf[4] = 0x08;
|
||||
|
||||
DEBUG();
|
||||
if ( (flash_addr == 160) || (flash_addr == 168) )
|
||||
{
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
buf[i+6] = ~binary_data[flash_addr + i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
buf[i+6] = binary_data[flash_addr + i];
|
||||
}
|
||||
}
|
||||
buf[5] = ~(buf[2]+buf[3]+buf[4]+buf[6]+buf[7]+buf[8]+buf[9]+buf[10]+buf[11]+buf[12]+buf[13]) + 1;
|
||||
return buf[5];
|
||||
}
|
||||
|
||||
static int chip_get_bin_checksum(void)
|
||||
{
|
||||
unsigned char buf[14];
|
||||
int sec,cod;
|
||||
int flash_addr;
|
||||
unsigned short bin_checksum = 0;
|
||||
|
||||
DEBUG();
|
||||
flash_addr = 0x00;
|
||||
cod = chip[FLASH_SECTOR_NUM].addr * (chip[FLASH_SECTOR_SIZE].addr/CHIP_FLASH_SOURCE_SIZE);
|
||||
for(sec=0;sec<cod;sec++)
|
||||
{
|
||||
bin_checksum += chip_set_code(flash_addr,buf);
|
||||
flash_addr += CHIP_FLASH_SOURCE_SIZE;
|
||||
//printk("sec = %d\n",sec);
|
||||
}
|
||||
return bin_checksum;
|
||||
}
|
||||
|
||||
int chip_get_fwchksum(struct i2c_client *client,int *fwchksum)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
if(chip == NULL){
|
||||
return -1;
|
||||
}
|
||||
ret = chip_ram_write_1byte(chip[FW_CHECKSUM_CMD].addr,chip[FW_CHECKSUM_CMD].data);
|
||||
if(ret)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
msleep(700);
|
||||
ret = chip_ram_read(chip[FW_CHECKSUM_VAL].addr,buf,2);
|
||||
*fwchksum = (buf[0]<<8)|buf[1];
|
||||
//chip_solfware_reset(client);
|
||||
vtl_ts_hw_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_write_flash(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[14];
|
||||
unsigned char bus_status[1];
|
||||
int sec,cod,sec_8byte_num;
|
||||
int flash_addr;
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = CHIP_WRITE_FLASH_CMD;
|
||||
sec_8byte_num = chip[FLASH_SECTOR_SIZE].addr/CHIP_FLASH_SOURCE_SIZE;
|
||||
cod = chip[FLASH_SECTOR_NUM].addr * sec_8byte_num;
|
||||
flash_addr = 0x00;
|
||||
for(sec=0;sec<cod;)
|
||||
{
|
||||
chip_set_code(flash_addr,buf);
|
||||
flash_addr += CHIP_FLASH_SOURCE_SIZE;
|
||||
#if 0
|
||||
ret = chip_read_bus_status(client,bus_status);
|
||||
if(bus_status[0] != 0xaa)
|
||||
{
|
||||
printk("i2c bus busy,sec = %d,bus_status = %x\n",sec,bus_status[0]);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
ret = chip_i2c_write(client,FLASH_I2C_ADDR, buf,14);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
sec++;
|
||||
if(!(sec%sec_8byte_num))
|
||||
{
|
||||
msleep(10);
|
||||
//mdelay(10);
|
||||
}
|
||||
mdelay(1);//ct360
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chip_get_checksum(struct i2c_client *client,int *bin_checksum,int *fw_checksum)
|
||||
{
|
||||
DEBUG();
|
||||
|
||||
if(chip == NULL){
|
||||
return -1;
|
||||
}
|
||||
*bin_checksum = chip_get_bin_checksum();
|
||||
chip_get_fwchksum(client,fw_checksum);
|
||||
//printk("bin_checksum = 0x%x,fw_checksum = 0x%x\n",*bin_checksum,*fw_checksum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[20];
|
||||
int ret = 0;
|
||||
DEBUG();
|
||||
|
||||
if(chip == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk("___chip update start___\n");
|
||||
ret = chip_enter_idle_mode(client);
|
||||
if(ret)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
ret = chip_read_bus_status(client,buf);
|
||||
if(buf[0] != 0xaa)
|
||||
{
|
||||
printk("___i2c bus busy,bus_status = %x___\n",buf[0]);
|
||||
return -1;
|
||||
}
|
||||
ret = chip_erase_flash(client);
|
||||
if(ret)
|
||||
{
|
||||
printk("___erase flash fail___\n");
|
||||
return -1;
|
||||
}
|
||||
ret = chip_write_flash(client);
|
||||
if(ret)
|
||||
{
|
||||
printk("___write flash fail___\n");
|
||||
return -1;
|
||||
}
|
||||
vtl_ts_hw_reset();
|
||||
printk("___chip update end___\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int chip_update(struct i2c_client *client)
|
||||
{
|
||||
int bin_checksum = 0xff;
|
||||
int fw_checksum = 0;
|
||||
int cnt = 0;
|
||||
|
||||
DEBUG();
|
||||
if(chip == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
chip_get_checksum(client,&bin_checksum,&fw_checksum);
|
||||
printk("bin_checksum = 0x%x,fw_checksum = 0x%x\n",bin_checksum,fw_checksum);
|
||||
cnt = 2;
|
||||
while((bin_checksum != fw_checksum) && (cnt--))
|
||||
{
|
||||
if(update(client) < 0)
|
||||
{
|
||||
vtl_ts_hw_reset();
|
||||
continue;
|
||||
};
|
||||
chip_get_fwchksum(client,&fw_checksum);
|
||||
printk("bin_checksum = %x,fw_checksum = %x,cnt = %d\n",bin_checksum,fw_checksum,cnt);
|
||||
}
|
||||
|
||||
if(bin_checksum != fw_checksum)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int chip_update(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[20];
|
||||
int bin_checksum,fw_checksum,cnt;
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
if(chip == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bin_checksum = chip_get_bin_checksum();
|
||||
chip_get_fwchksum(client,&fw_checksum);
|
||||
printk("bin_checksum = %x,fw_checksum = %x\n",bin_checksum,fw_checksum);
|
||||
cnt = 2;
|
||||
while((bin_checksum != fw_checksum) && (cnt--))
|
||||
//while(cnt--)
|
||||
{
|
||||
printk("___chip update start___\n");
|
||||
ret = chip_enter_idle_mode(client);
|
||||
if(ret)
|
||||
{
|
||||
//return ret;
|
||||
continue;
|
||||
}
|
||||
ret = chip_read_bus_status(client,buf);
|
||||
if(buf[0] != 0xaa)
|
||||
{
|
||||
printk("___i2c bus busy,bus_status = %x___\n",buf[0]);
|
||||
//return ret;
|
||||
continue;
|
||||
}
|
||||
ret = chip_erase_flash(client);
|
||||
if(ret)
|
||||
{
|
||||
printk("___erase flash fail___\n");
|
||||
//return ret;
|
||||
continue;
|
||||
}
|
||||
ret = chip_write_flash(client);
|
||||
if(ret)
|
||||
{
|
||||
printk("___write flash fail___\n");
|
||||
//return ret;
|
||||
continue;
|
||||
}
|
||||
vtl_ts_hw_reset();
|
||||
//chip_solfware_reset(client);
|
||||
ret = chip_get_fwchksum(client,&fw_checksum);
|
||||
if(ret)
|
||||
{
|
||||
printk("___get fwchksum fail___\n");
|
||||
//return ret;
|
||||
continue;
|
||||
}
|
||||
printk("___chip update end___\n");
|
||||
printk("bin_checksum = %x,fw_checksum = %x\n",bin_checksum,fw_checksum);
|
||||
}
|
||||
//vtl_ts_hw_reset();
|
||||
if(bin_checksum != fw_checksum)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int chip_get_chip_id(struct i2c_client *client,unsigned char *rx_buf)
|
||||
{
|
||||
unsigned char buf[3];
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
ret = chip_enter_idle_mode(client);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
ret = chip_read_bus_status(client,buf);
|
||||
if(buf[0]!= 0xaa)
|
||||
{
|
||||
printk("___i2c bus status = %x,ret = %d___\n",buf[0],ret);
|
||||
return -1;
|
||||
}
|
||||
mdelay(1);
|
||||
|
||||
buf[0] = 0xff;
|
||||
buf[1] = CHIP_ID_ADDR>>8;
|
||||
buf[2] = CHIP_ID_ADDR & 0x00ff;
|
||||
ret = chip_i2c_write(client,0x01, buf,3);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
mdelay(1);
|
||||
buf[0] = 0x00;
|
||||
ret = chip_i2c_write(client,0x01, buf,1);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
mdelay(1);
|
||||
ret = chip_i2c_read(client,0x01,rx_buf,1);
|
||||
//chip_solfware_reset(client);
|
||||
vtl_ts_hw_reset();
|
||||
|
||||
//printk("___chip ID = %d___\n",*rx_buf);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int chip_read_infoblk(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[20] = {0};
|
||||
|
||||
DEBUG();
|
||||
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x62;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x08;
|
||||
|
||||
chip_i2c_write(client,0x7F, buf,5);
|
||||
mdelay(1);
|
||||
chip_i2c_read(client,0x7f, buf,14);
|
||||
|
||||
if(buf[5] & 0x10)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chip_erase_infoblk(struct i2c_client *client)
|
||||
{
|
||||
unsigned char buf[20]={0};
|
||||
int ret = -1;
|
||||
|
||||
DEBUG();
|
||||
|
||||
// info block erase command
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x60;
|
||||
buf[2] = 0x00;
|
||||
chip_i2c_write(client, 0x7F, buf, 3);
|
||||
mdelay(10);
|
||||
|
||||
ret = chip_read_bus_status(client,buf);
|
||||
if(buf[0]!= 0xaa)
|
||||
{
|
||||
printk("___i2c bus status = %x,ret = %d___\n",buf[0],ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_write_infoblk(struct i2c_client *client)
|
||||
{
|
||||
//int ret = -1;
|
||||
unsigned char buf[20]={0};
|
||||
int cod;
|
||||
unsigned int flash_addr;
|
||||
|
||||
DEBUG();
|
||||
|
||||
flash_addr = 0x00;
|
||||
|
||||
// write info block 0
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x61;
|
||||
|
||||
for ( cod = 0; cod < 16; cod++ ) {
|
||||
// Flash address
|
||||
// data length
|
||||
buf[2] = (char)(flash_addr >> 8);
|
||||
buf[3] = (char)(flash_addr & 0xFF);
|
||||
buf[4] = 0x08;
|
||||
if ( flash_addr == 0x0000 )
|
||||
buf[6] = 0x17;
|
||||
else
|
||||
buf[6] = 0x00;
|
||||
|
||||
buf[7] = 0x00;
|
||||
buf[8] = 0x00;
|
||||
buf[9] = 0x00;
|
||||
buf[10] = 0x00;
|
||||
buf[11] = 0x00;
|
||||
buf[12] = 0x00;
|
||||
buf[13] = 0x00;
|
||||
|
||||
buf[5] = (~(buf[2]+buf[3]+buf[4]+buf[6]+buf[7]+buf[8]+buf[9]+buf[10]+buf[11]+buf[12]+buf[13]))+1;
|
||||
|
||||
chip_i2c_write(client, 0x7F, buf, 14);
|
||||
mdelay(10);
|
||||
|
||||
flash_addr += 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chip_trim_info_init(struct i2c_client *client)
|
||||
{
|
||||
int retry =5;
|
||||
|
||||
while(chip_read_infoblk(client) && (retry--))
|
||||
{
|
||||
chip_erase_infoblk(client);
|
||||
chip_write_infoblk(client);
|
||||
}
|
||||
vtl_ts_hw_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chip_init(void)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
unsigned char chip_id = 0xff;
|
||||
unsigned char retry;
|
||||
int ret = 0;
|
||||
|
||||
DEBUG();
|
||||
|
||||
ts_object = vtl_ts_get_object();
|
||||
|
||||
if(ts_object == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
client = ts_object->driver->client;
|
||||
|
||||
chip = NULL;
|
||||
for(retry = 0;retry<3;retry++)
|
||||
{
|
||||
ret = chip_get_chip_id(client,&chip_id);
|
||||
printk("___chip ID = %d___cnt = %d\n",chip_id,retry);
|
||||
switch(chip_id)
|
||||
{
|
||||
case 1: { //chip: CT362, CT363, CT365, CT368, CT369
|
||||
chip = ct36x_cmd;
|
||||
chip_trim_info_init(client);
|
||||
}break;
|
||||
|
||||
case 2: { //chip: CT360
|
||||
chip = ct360_cmd;
|
||||
}break;
|
||||
|
||||
case 6: { //chip: CT362M, CT363M, CT365M, CT368M, CT369M
|
||||
chip = ct36x_cmd;
|
||||
}break;
|
||||
|
||||
default : {
|
||||
|
||||
chip = NULL;
|
||||
}
|
||||
}
|
||||
if(chip != NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(chip == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if(CHIP_UPDATE_ENABLE)
|
||||
if(chip_update(client)<0)
|
||||
{
|
||||
printk("___chip updata faile___\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
12
drivers/input/touchscreen/vtl_ts/chip.h
Executable file
12
drivers/input/touchscreen/vtl_ts/chip.h
Executable file
@@ -0,0 +1,12 @@
|
||||
#ifndef _CHIP_H_
|
||||
#define _CHIP_H_
|
||||
|
||||
extern int chip_init(void);
|
||||
extern int chip_get_fwchksum(struct i2c_client *client,int *fwchksum);
|
||||
extern int chip_get_checksum(struct i2c_client *client,int *bin_checksum,int *fw_checksum);
|
||||
extern int update(struct i2c_client *client);
|
||||
extern int chip_update(struct i2c_client *client);
|
||||
extern int chip_enter_sleep_mode(void);
|
||||
extern int chip_solfware_reset(struct i2c_client *client);
|
||||
|
||||
#endif
|
||||
2048
drivers/input/touchscreen/vtl_ts/lx--js77_97_CT365_V01_E7DA_130419.dat
Executable file
2048
drivers/input/touchscreen/vtl_ts/lx--js77_97_CT365_V01_E7DA_130419.dat
Executable file
File diff suppressed because it is too large
Load Diff
683
drivers/input/touchscreen/vtl_ts/vtl_ts.c
Executable file
683
drivers/input/touchscreen/vtl_ts/vtl_ts.c
Executable file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
* VTL CTP driver
|
||||
*
|
||||
* Copyright (C) 2013 VTL Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
|
||||
#include "vtl_ts.h"
|
||||
#include "chip.h"
|
||||
#include "apk.h"
|
||||
|
||||
|
||||
#define TS_THREAD_PRIO 90
|
||||
static DECLARE_WAIT_QUEUE_HEAD(waiter);
|
||||
//static struct task_struct *ts_thread = NULL;
|
||||
static unsigned char thread_syn_flag =0;
|
||||
static volatile unsigned char thread_running_flag =0;
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// Globel or static variables
|
||||
// ****************************************************************************
|
||||
static struct ts_driver g_driver;
|
||||
|
||||
struct ts_info g_ts = {
|
||||
.driver = &g_driver,
|
||||
.debug = DEBUG_ENABLE,
|
||||
};
|
||||
struct ts_info *pg_ts = &g_ts;
|
||||
|
||||
static struct i2c_device_id vtl_ts_id[] = {
|
||||
{ DRIVER_NAME, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c,vtl_ts_id);
|
||||
|
||||
|
||||
/*
|
||||
static struct i2c_board_info i2c_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO(DRIVER_NAME, 0x01),
|
||||
.platform_data = NULL,
|
||||
},
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// Function declaration
|
||||
// ****************************************************************************
|
||||
|
||||
static int vtl_ts_config(struct ts_info *ts)
|
||||
{
|
||||
struct device *dev;
|
||||
//struct ts_config_info *ts_config_info;
|
||||
int err;
|
||||
|
||||
DEBUG();
|
||||
dev = &ts->driver->client->dev;
|
||||
|
||||
struct device_node *np = dev->of_node;
|
||||
enum of_gpio_flags rst_flags;
|
||||
unsigned long irq_flags;
|
||||
int val;
|
||||
/* ts config */
|
||||
ts->config_info.touch_point_number = TOUCH_POINT_NUM;
|
||||
if(dev->platform_data !=NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (of_property_read_u32(np, "screen_max_x", &val)) {
|
||||
dev_err(&ts->driver->client->dev, "no screen_max_x defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts->config_info.screen_max_x = val;
|
||||
if (of_property_read_u32(np, "screen_max_y", &val)) {
|
||||
dev_err(&ts->driver->client->dev, "no screen_max_y defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ts->config_info.screen_max_y = val;
|
||||
printk("the screen_x is %d , screen_y is %d \n",ts->config_info.screen_max_x,ts->config_info.screen_max_y);
|
||||
|
||||
ts->config_info.irq_gpio_number = of_get_named_gpio_flags(np, "irq_gpio_number", 0, (enum of_gpio_flags *)&irq_flags);
|
||||
ts->config_info.rst_gpio_number = of_get_named_gpio_flags(np, "rst_gpio_number", 0, &rst_flags);
|
||||
|
||||
ts->config_info.screen_max_x = ts->config_info.screen_max_x;
|
||||
ts->config_info.screen_max_y = ts->config_info.screen_max_y;
|
||||
ts->config_info.irq_gpio_number = ts->config_info.irq_gpio_number;
|
||||
ts->config_info.rst_gpio_number = ts->config_info.rst_gpio_number;
|
||||
|
||||
}
|
||||
|
||||
ts->config_info.irq_number = gpio_to_irq(ts->config_info.irq_gpio_number);/* IRQ config*/
|
||||
|
||||
err = gpio_request(ts->config_info.rst_gpio_number, "vtl_ts_rst");
|
||||
if ( err ) {
|
||||
return -EIO;
|
||||
}
|
||||
gpio_direction_output(ts->config_info.rst_gpio_number, 1);
|
||||
//gpio_set_value(ts->config_info.rst_gpio_number, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct ts_info * vtl_ts_get_object(void)
|
||||
{
|
||||
DEBUG();
|
||||
|
||||
return pg_ts;
|
||||
}
|
||||
static void vtl_ts_free_gpio(void)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
DEBUG();
|
||||
|
||||
gpio_free(ts->config_info.rst_gpio_number);
|
||||
}
|
||||
|
||||
void vtl_ts_hw_reset(void)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
DEBUG();
|
||||
|
||||
//gpio_set_value(ts->config_info.rst_gpio_number, 1);
|
||||
//msleep(10);
|
||||
gpio_set_value(ts->config_info.rst_gpio_number, 0);
|
||||
msleep(50);
|
||||
gpio_set_value(ts->config_info.rst_gpio_number, 1);
|
||||
//msleep(250);
|
||||
msleep(5);
|
||||
chip_solfware_reset(ts->driver->client);//20140306
|
||||
}
|
||||
|
||||
static void vtl_ts_wakeup(void)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
DEBUG();
|
||||
|
||||
gpio_set_value(ts->config_info.rst_gpio_number, 0);
|
||||
//msleep(50);
|
||||
msleep(20);
|
||||
gpio_set_value(ts->config_info.rst_gpio_number, 1);
|
||||
msleep(5);
|
||||
chip_solfware_reset(ts->driver->client);//20140306
|
||||
}
|
||||
|
||||
static irqreturn_t vtl_ts_irq(int irq, void *dev)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
|
||||
DEBUG();
|
||||
|
||||
disable_irq_nosync(ts->config_info.irq_number);// Disable ts interrupt
|
||||
thread_syn_flag=1;
|
||||
wake_up_interruptible(&waiter);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
static int vtl_ts_read_xy_data(struct ts_info *ts)
|
||||
{
|
||||
struct i2c_msg msgs;
|
||||
int ret;
|
||||
|
||||
DEBUG();
|
||||
|
||||
msgs.addr = ts->driver->client->addr;
|
||||
msgs.flags = 0x01; // 0x00: write 0x01:read
|
||||
msgs.len = sizeof(ts->xy_data.buf);
|
||||
msgs.buf = ts->xy_data.buf;
|
||||
msgs.scl_rate = TS_I2C_SPEED; ///only for rockchip platform
|
||||
ret = i2c_transfer( ts->driver->client->adapter, &msgs, 1);
|
||||
if(ret != 1){
|
||||
printk("___%s:i2c read xy_data err___\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#if 0
|
||||
ret = vtl_ts_i2c_read(client,client->addr,ts->xy_data.buf,sizeof(ts->xy_data.buf));
|
||||
if(ret){
|
||||
printk("___%s:i2c read err___\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vtl_ts_report_xy_coord(struct ts_info *ts)
|
||||
{
|
||||
int i;
|
||||
int id;
|
||||
int sync;
|
||||
int x, y;
|
||||
unsigned int press;
|
||||
unsigned char touch_point_number;
|
||||
static unsigned int release = 0;
|
||||
struct input_dev *input_dev;
|
||||
union ts_xy_data *xy_data;
|
||||
|
||||
DEBUG();
|
||||
|
||||
xy_data = &ts->xy_data;
|
||||
input_dev = ts->driver->input_dev;
|
||||
touch_point_number = ts->config_info.touch_point_number;
|
||||
|
||||
|
||||
|
||||
/* report points */
|
||||
sync = 0; press = 0;
|
||||
for ( id = 0; id <touch_point_number; id++ ) //down
|
||||
{
|
||||
if ((xy_data->point[id].xhi != 0xFF) && (xy_data->point[id].yhi != 0xFF) &&
|
||||
( (xy_data->point[id].status == 1) || (xy_data->point[id].status == 2)))
|
||||
{
|
||||
|
||||
#if(XY_SWAP_ENABLE)
|
||||
x = (xy_data->point[id].yhi<<4)|(xy_data->point[id].ylo&0xF);
|
||||
y = (xy_data->point[id].xhi<<4)|(xy_data->point[id].xlo&0xF);
|
||||
#else
|
||||
x = (xy_data->point[id].xhi<<4)|(xy_data->point[id].xlo&0xF);
|
||||
y = (xy_data->point[id].yhi<<4)|(xy_data->point[id].ylo&0xF);
|
||||
#endif
|
||||
#if(X_REVERSE_ENABLE)
|
||||
x = ts->config_info.screen_max_x - x;
|
||||
#endif
|
||||
#if(Y_REVERSE_ENABLE)
|
||||
y = ts->config_info.screen_max_y - y;
|
||||
#endif
|
||||
|
||||
//#if(DEBUG_ENABLE)
|
||||
//if((ts->debug)||(DEBUG_ENABLE)){
|
||||
if(ts->debug){
|
||||
printk("id = %d,status = %d,X = %d,Y = %d\n",xy_data->point[id].id,xy_data->point[id].status,x,y);
|
||||
//XY_DEBUG(xy_data->point[id].id,xy_data->point[id].status,x,y);
|
||||
}
|
||||
//#endif
|
||||
input_mt_slot(input_dev, xy_data->point[id].id - 1);
|
||||
input_report_abs(input_dev, ABS_MT_TRACKING_ID, xy_data->point[id].id-1);
|
||||
//input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
|
||||
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
|
||||
input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 1);
|
||||
|
||||
press |= 0x01 << (xy_data->point[id].id - 1);
|
||||
sync = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
release &= (release ^ press);//release point flag
|
||||
|
||||
for ( id = 0; id < touch_point_number; id++ ) //up
|
||||
{
|
||||
if ( release & (0x01<<id) )
|
||||
{
|
||||
input_mt_slot(input_dev, id);
|
||||
input_report_abs(input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
sync = 1;
|
||||
}
|
||||
}
|
||||
|
||||
release = press;
|
||||
if(sync)
|
||||
{
|
||||
input_sync(input_dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int vtl_ts_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
unsigned char i;
|
||||
ts =pg_ts;
|
||||
|
||||
DEBUG();
|
||||
if(ts->config_info.ctp_used)
|
||||
{
|
||||
disable_irq(ts->config_info.irq_number);
|
||||
chip_enter_sleep_mode();
|
||||
|
||||
for(i=0;i<ts->config_info.touch_point_number;i++)
|
||||
{
|
||||
input_mt_slot(ts->driver->input_dev,i);
|
||||
input_report_abs(ts->driver->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
//input_mt_report_slot_state(ts->driver->input_dev, MT_TOOL_FINGER, false);
|
||||
}
|
||||
input_sync(ts->driver->input_dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vtl_ts_resume(struct i2c_client *client)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
unsigned char i;
|
||||
ts =pg_ts;
|
||||
|
||||
DEBUG();
|
||||
if(ts->config_info.ctp_used)
|
||||
{
|
||||
/* Hardware reset */
|
||||
//vtl_ts_hw_reset();
|
||||
vtl_ts_wakeup();
|
||||
for(i=0;i<ts->config_info.touch_point_number;i++)
|
||||
{
|
||||
input_mt_slot(ts->driver->input_dev,i);
|
||||
input_report_abs(ts->driver->input_dev, ABS_MT_TRACKING_ID, -1);
|
||||
//input_mt_report_slot_state(ts->driver->input_dev, MT_TOOL_FINGER, false);
|
||||
}
|
||||
input_sync(ts->driver->input_dev);
|
||||
|
||||
enable_irq(ts->config_info.irq_number);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vtl_ts_early_suspend(struct early_suspend *handler)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
|
||||
DEBUG();
|
||||
|
||||
vtl_ts_suspend(ts->driver->client, PMSG_SUSPEND);
|
||||
}
|
||||
|
||||
static void vtl_ts_early_resume(struct early_suspend *handler)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
|
||||
DEBUG();
|
||||
|
||||
vtl_ts_resume(ts->driver->client);
|
||||
}
|
||||
|
||||
int vtl_ts_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ts_info *ts;
|
||||
ts =pg_ts;
|
||||
|
||||
DEBUG();
|
||||
|
||||
free_irq(ts->config_info.irq_number, ts);
|
||||
gpio_free(ts->config_info.rst_gpio_number);
|
||||
//vtl_ts_free_gpio();
|
||||
|
||||
//#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
//unregister_early_suspend(&ts->driver->early_suspend);
|
||||
tp_unregister_fb(&ts->tp);
|
||||
//#endif
|
||||
if(ts->driver->input_dev != NULL)
|
||||
{
|
||||
input_unregister_device(ts->driver->input_dev);
|
||||
input_free_device(ts->driver->input_dev);
|
||||
}
|
||||
|
||||
if ( ts->driver->proc_entry != NULL ){
|
||||
remove_proc_entry(DRIVER_NAME, NULL);
|
||||
}
|
||||
|
||||
if(ts->driver->ts_thread != NULL)
|
||||
{
|
||||
printk("___kthread stop start___\n");
|
||||
thread_syn_flag=1;
|
||||
wake_up_interruptible(&waiter);
|
||||
kthread_stop(ts->driver->ts_thread);
|
||||
ts->driver->ts_thread = NULL;
|
||||
printk("___kthread stop end___\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vtl_ts_init_input_dev(struct ts_info *ts)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
struct device *dev;
|
||||
int err;
|
||||
|
||||
DEBUG();
|
||||
|
||||
|
||||
dev = &ts->driver->client->dev;
|
||||
|
||||
/* allocate input device */
|
||||
ts->driver->input_dev = input_allocate_device();
|
||||
if ( ts->driver->input_dev == NULL ) {
|
||||
dev_err(dev, "Unable to allocate input device for device %s.\n", DRIVER_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
input_dev = ts->driver->input_dev;
|
||||
|
||||
input_dev->name = DRIVER_NAME;
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->id.vendor = 0xaaaa;
|
||||
input_dev->id.product = 0x5555;
|
||||
input_dev->id.version = 0x0001;
|
||||
|
||||
/* config input device */
|
||||
__set_bit(EV_SYN, input_dev->evbit);
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
|
||||
|
||||
//set_bit(BTN_TOUCH, input_dev->keybit);//20130923
|
||||
//set_bit(ABS_MT_POSITION_X, input_dev->absbit);//20130923
|
||||
//set_bit(ABS_MT_POSITION_Y, input_dev->absbit);//20130923
|
||||
|
||||
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
|
||||
|
||||
input_mt_init_slots(input_dev, TOUCH_POINT_NUM,0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ts->config_info.screen_max_x, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ts->config_info.screen_max_y, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,ts->config_info.touch_point_number, 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, 255, 0, 0);
|
||||
|
||||
|
||||
/* register input device */
|
||||
err = input_register_device(input_dev);
|
||||
if ( err ) {
|
||||
input_free_device(ts->driver->input_dev);
|
||||
ts->driver->input_dev = NULL;
|
||||
dev_err(dev, "Unable to register input device for device %s.\n", DRIVER_NAME);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int vtl_ts_handler(void *data)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev;
|
||||
struct ts_info *ts;
|
||||
//struct sched_param param = { .sched_priority = TS_THREAD_PRIO};
|
||||
DEBUG();
|
||||
//sched_setscheduler(current, SCHED_RR, ¶m);
|
||||
|
||||
ts = (struct ts_info *)data;
|
||||
dev = &ts->driver->client->dev;
|
||||
|
||||
|
||||
/* Request platform resources (gpio/interrupt pins) */
|
||||
ret = vtl_ts_config(ts);
|
||||
if(ret){
|
||||
|
||||
dev_err(dev, "VTL touch screen config Failed.\n");
|
||||
goto ERR_TS_CONFIG;
|
||||
}
|
||||
|
||||
vtl_ts_hw_reset();
|
||||
|
||||
|
||||
ret = chip_init();
|
||||
if(ret){
|
||||
|
||||
dev_err(dev, "vtl ts chip init failed.\n");
|
||||
goto ERR_CHIP_INIT;
|
||||
}
|
||||
|
||||
/*init input dev*/
|
||||
ret = vtl_ts_init_input_dev(ts);
|
||||
if(ret){
|
||||
|
||||
dev_err(dev, "init input dev failed.\n");
|
||||
goto ERR_INIT_INPUT;
|
||||
}
|
||||
|
||||
/* Create Proc Entry File */
|
||||
#if 0
|
||||
ts->driver->proc_entry = create_proc_entry(DRIVER_NAME, 0666/*S_IFREG | S_IRUGO | S_IWUSR*/, NULL);
|
||||
if ( ts->driver->proc_entry == NULL ) {
|
||||
dev_err(dev, "Failed creating proc dir entry file.\n");
|
||||
goto ERR_PROC_ENTRY;
|
||||
} else{
|
||||
ts->driver->proc_entry->proc_fops = &apk_fops;
|
||||
}
|
||||
#endif
|
||||
/* register early suspend */
|
||||
//#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
//ts->driver->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
|
||||
//ts->driver->early_suspend.suspend = vtl_ts_early_suspend;
|
||||
//ts->driver->early_suspend.resume = vtl_ts_early_resume;
|
||||
//register_early_suspend(&ts->driver->early_suspend);
|
||||
ts->tp.tp_resume = vtl_ts_early_resume;
|
||||
ts->tp.tp_suspend = vtl_ts_early_suspend;
|
||||
tp_register_fb(&ts->tp);
|
||||
|
||||
//#endif
|
||||
|
||||
/* Init irq */
|
||||
ret = request_irq(ts->config_info.irq_number, vtl_ts_irq, IRQF_TRIGGER_FALLING, DRIVER_NAME, ts);
|
||||
if ( ret ) {
|
||||
dev_err(dev, "Unable to request irq for device %s.\n", DRIVER_NAME);
|
||||
goto ERR_IRQ_REQ;
|
||||
}
|
||||
|
||||
ts->config_info.ctp_used =1;
|
||||
while (!kthread_should_stop())//while(1)
|
||||
{
|
||||
//set_current_state(TASK_INTERRUPTIBLE);
|
||||
wait_event_interruptible(waiter, thread_syn_flag);
|
||||
thread_syn_flag = 0;
|
||||
//set_current_state(TASK_RUNNING);
|
||||
//printk("__state = %x_%x_\n",current->state,ts->driver->ts_thread->state);
|
||||
ret = vtl_ts_read_xy_data(ts);
|
||||
|
||||
if(!ret){
|
||||
vtl_ts_report_xy_coord(ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("____read xy_data error___\n");
|
||||
}
|
||||
// Enable ts interrupt
|
||||
enable_irq(pg_ts->config_info.irq_number);
|
||||
}
|
||||
disable_irq(pg_ts->config_info.irq_number);
|
||||
printk("vtl_ts_Kthread exit,%s(%d)\n",__func__,__LINE__);
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
|
||||
ERR_IRQ_REQ:
|
||||
//#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
//unregister_early_suspend(&ts->driver->early_suspend);
|
||||
//#endif
|
||||
tp_unregister_fb(&ts->tp);
|
||||
if ( ts->driver->proc_entry ){
|
||||
remove_proc_entry(DRIVER_NAME, NULL);
|
||||
ts->driver->proc_entry = NULL;
|
||||
}
|
||||
|
||||
ERR_PROC_ENTRY:
|
||||
if(ts->driver->input_dev){
|
||||
input_unregister_device(ts->driver->input_dev);
|
||||
input_free_device(ts->driver->input_dev);
|
||||
ts->driver->input_dev = NULL;
|
||||
}
|
||||
ERR_INIT_INPUT:
|
||||
ERR_CHIP_INIT:
|
||||
gpio_free(ts->config_info.rst_gpio_number);
|
||||
ERR_TS_CONFIG:
|
||||
ts->config_info.ctp_used =0;
|
||||
printk("vtl_ts_Kthread exit,%s(%d)\n",__func__,__LINE__);
|
||||
//do_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int vtl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
int err = -1;
|
||||
unsigned char chip_id = 0xff;
|
||||
struct ts_info *ts;
|
||||
struct device *dev;
|
||||
|
||||
DEBUG();
|
||||
|
||||
ts = pg_ts;
|
||||
ts->driver->client = client;
|
||||
dev = &ts->driver->client->dev;
|
||||
|
||||
/* Check I2C Functionality */
|
||||
err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
|
||||
if ( !err ) {
|
||||
dev_err(dev, "Check I2C Functionality Failed.\n");
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
|
||||
//ts->driver->ts_thread = kthread_run(vtl_ts_handler, NULL, DRIVER_NAME);
|
||||
ts->driver->ts_thread = kthread_run(vtl_ts_handler, ts, DRIVER_NAME);
|
||||
if (IS_ERR(ts->driver->ts_thread)) {
|
||||
err = PTR_ERR(ts->driver->ts_thread);
|
||||
ts->driver->ts_thread = NULL;
|
||||
dev_err(dev, "failed to create kernel thread: %d\n", err);
|
||||
return -1;
|
||||
//goto ERR_CREATE_TS_THREAD;
|
||||
}
|
||||
|
||||
printk("___%s() end____ \n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static struct of_device_id vtl_ts_dt_ids[] = {
|
||||
{ .compatible = "ct,vtl_ts" },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct i2c_driver vtl_ts_driver = {
|
||||
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(vtl_ts_dt_ids),
|
||||
},
|
||||
.id_table = vtl_ts_id,
|
||||
.probe = vtl_ts_probe,
|
||||
//#ifndef CONFIG_HAS_EARLYSUSPEND
|
||||
//.suspend = vtl_ts_suspend,
|
||||
//.resume = vtl_ts_resume,
|
||||
//#endif
|
||||
.remove = vtl_ts_remove,
|
||||
};
|
||||
|
||||
|
||||
|
||||
int __init vtl_ts_init(void)
|
||||
{
|
||||
DEBUG();
|
||||
return i2c_add_driver(&vtl_ts_driver);
|
||||
}
|
||||
|
||||
void __exit vtl_ts_exit(void)
|
||||
{
|
||||
DEBUG();
|
||||
i2c_del_driver(&vtl_ts_driver);
|
||||
}
|
||||
|
||||
module_init(vtl_ts_init);
|
||||
module_exit(vtl_ts_exit);
|
||||
|
||||
MODULE_AUTHOR("yangdechu@vtl.com.cn");
|
||||
MODULE_DESCRIPTION("VTL touchscreen driver for rockchip,V1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
||||
179
drivers/input/touchscreen/vtl_ts/vtl_ts.h
Executable file
179
drivers/input/touchscreen/vtl_ts/vtl_ts.h
Executable file
@@ -0,0 +1,179 @@
|
||||
#ifndef _TS_CORE_H_
|
||||
#define _TS_CORE_H_
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include "../tp_suspend.h"
|
||||
|
||||
|
||||
/*vtl touch IC define*/
|
||||
#define CT36X 0x01//(CT36X:ct362,ct363,ct365)
|
||||
#define CT360 0x02//(CT360:ct360)
|
||||
|
||||
/*xy data protocol*/
|
||||
#define OLD_PROTOCOL 0x01
|
||||
#define NEW_PROTOCOL 0x02
|
||||
|
||||
|
||||
|
||||
/***********************vtl ts driver config ******************************************/
|
||||
|
||||
/*vtl chip ID*/
|
||||
#define CHIP_ID CT36X//CT360//
|
||||
|
||||
#define XY_DATA_PROTOCOL NEW_PROTOCOL//OLD_PROTOCOL//
|
||||
|
||||
#define TS_I2C_SPEED 400000 //for rockchip
|
||||
|
||||
|
||||
#define XY_SWAP_ENABLE 0
|
||||
|
||||
#define X_REVERSE_ENABLE 0
|
||||
|
||||
#define Y_REVERSE_ENABLE 1
|
||||
|
||||
#define CHIP_UPDATE_ENABLE 1
|
||||
|
||||
#define DEBUG_ENABLE 0
|
||||
|
||||
|
||||
/***********************vtl ts driver config end******************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*vtl ts driver name*/
|
||||
#define DRIVER_NAME "vtl_ts"
|
||||
//#define DEBUG_ENABLE 1
|
||||
#if(DEBUG_ENABLE)
|
||||
#define DEBUG() printk("___%s___\n",__func__);
|
||||
//#define XY_DEBUG(id,status,x,y) printk("id = %d,status = %d,X = %d,Y = %d\n",id,status,x,y);
|
||||
#else
|
||||
#define DEBUG()
|
||||
//#define XY_DEBUG(id,status,x,y)
|
||||
#endif
|
||||
|
||||
/*TOUCH_POINT_NUM define*/
|
||||
#if(CHIP_ID == CT360)
|
||||
#define TOUCH_POINT_NUM 5
|
||||
#elif(CHIP_ID == CT36X)
|
||||
#define TOUCH_POINT_NUM 10
|
||||
#endif
|
||||
|
||||
/*priate define and declare*/
|
||||
#if(CHIP_ID == CT360)
|
||||
struct xy_data {
|
||||
#if(XY_DATA_PROTOCOL == OLD_PROTOCOL)
|
||||
unsigned char status : 4; // Action information, 1: Down; 2: Move; 3: Up
|
||||
unsigned char id : 4; // ID information, from 1 to CFG_MAX_POINT_NUM
|
||||
#endif
|
||||
unsigned char xhi; // X coordinate Hi
|
||||
unsigned char yhi; // Y coordinate Hi
|
||||
unsigned char ylo : 4; // Y coordinate Lo
|
||||
unsigned char xlo : 4; // X coordinate Lo
|
||||
#if(XY_DATA_PROTOCOL == NEW_PROTOCOL)
|
||||
unsigned char status : 4; // Action information, 1: Down; 2: Move; 3: Up
|
||||
unsigned char id : 4; // ID information, from 1 to CFG_MAX_POINT_NUM
|
||||
#endif
|
||||
};
|
||||
#else
|
||||
struct xy_data {
|
||||
#if(XY_DATA_PROTOCOL == OLD_PROTOCOL)
|
||||
unsigned char status : 3; // Action information, 1: Down; 2: Move; 3: Up
|
||||
unsigned char id : 5; // ID information, from 1 to CFG_MAX_POINT_NUM
|
||||
#endif
|
||||
unsigned char xhi; // X coordinate Hi
|
||||
unsigned char yhi; // Y coordinate Hi
|
||||
unsigned char ylo : 4; // Y coordinate Lo
|
||||
unsigned char xlo : 4; // X coordinate Lo
|
||||
#if(XY_DATA_PROTOCOL == NEW_PROTOCOL)
|
||||
unsigned char status : 3; // Action information, 1: Down; 2: Move; 3: Up
|
||||
unsigned char id : 5; // ID information, from 1 to CFG_MAX_POINT_NUM
|
||||
#endif
|
||||
unsigned char area; // Touch area
|
||||
unsigned char pressure; // Touch Pressure
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
union ts_xy_data {
|
||||
struct xy_data point[TOUCH_POINT_NUM];
|
||||
unsigned char buf[TOUCH_POINT_NUM * sizeof(struct xy_data)];
|
||||
};
|
||||
|
||||
|
||||
struct ts_driver{
|
||||
|
||||
struct i2c_client *client;
|
||||
|
||||
/* input devices */
|
||||
struct input_dev *input_dev;
|
||||
|
||||
struct proc_dir_entry *proc_entry;
|
||||
|
||||
struct task_struct *ts_thread;
|
||||
|
||||
//#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
//struct early_suspend early_suspend;
|
||||
//#endif
|
||||
};
|
||||
|
||||
struct ts_config_info{
|
||||
|
||||
unsigned int screen_max_x;
|
||||
unsigned int screen_max_y;
|
||||
unsigned int irq_gpio_number;
|
||||
unsigned int irq_number;
|
||||
unsigned int rst_gpio_number;
|
||||
unsigned char touch_point_number;
|
||||
unsigned char ctp_used;
|
||||
//unsigned char i2c_bus_number;
|
||||
//unsigned char revert_x_flag;
|
||||
//unsigned char revert_y_flag;
|
||||
//unsigned char exchange_x_y_flag;
|
||||
};
|
||||
|
||||
struct ts_info{
|
||||
|
||||
struct ts_driver *driver;
|
||||
struct ts_config_info config_info;
|
||||
union ts_xy_data xy_data;
|
||||
unsigned char debug;
|
||||
struct tp_device tp;
|
||||
};
|
||||
|
||||
|
||||
//extern struct ts_info *pg_ts;
|
||||
extern struct ts_info * vtl_ts_get_object(void);
|
||||
extern void vtl_ts_hw_reset(void);
|
||||
|
||||
#endif
|
||||
|
||||
2048
drivers/input/touchscreen/vtl_ts/wgj36js07_A1_CT363_V01_0187_140306.dat
Executable file
2048
drivers/input/touchscreen/vtl_ts/wgj36js07_A1_CT363_V01_0187_140306.dat
Executable file
File diff suppressed because it is too large
Load Diff
BIN
drivers/input/touchscreen/vtl_ts/用户使用手册(driver).pdf
Executable file
BIN
drivers/input/touchscreen/vtl_ts/用户使用手册(driver).pdf
Executable file
Binary file not shown.
Reference in New Issue
Block a user