#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MY_DEV_CNT 1
#define MY_DEV_NAME "my-gt1151"
#define GT_CTRL_REG 0X8040 /* GT1151控制命令 */
#define GT_MOD_SW_REG 0X804D /* GT1151模式切换命令 */
#define GT_9xx_CFGS_REG 0X8047 /* GT1151配置 */
#define GT_1xx_CFGS_REG 0X8050 /* GT1151配置 */
#define GT_CHECK_REG 0X80FF /* GT1151 */
#define GT_PID_H_REG 0X8140 /* GT1151 PID高字节 */
#define GT_PID_L_REG 0X8141 /* GT1151 PID低字节 */
#define GT_STATE_REG 0X814E /* GT1151触摸状态寄存器*/
#define GT_TP1_REG 0X814F /* 触摸点1起始寄存器 */
#define GT_TP2_REG 0X8157 /* 触摸点2起始寄存器 */
#define GT_TP3_REG 0X815F /* 触摸点3起始寄存器 */
#define GT_TP4_REG 0X8167 /* 触摸点4起始寄存器 */
#define GT_TP5_REG 0X816F /* 触摸点5起始寄存器 */
#define GT_TP6_REG 0X8177 /* 触摸点6起始寄存器 */
#define GT_TP7_REG 0X817F /* 触摸点7起始寄存器 */
#define GT_TP8_REG 0X8187 /* 触摸点8起始寄存器 */
#define GT_TP9_REG 0X818F /* 触摸点9起始寄存器 */
#define GT_TP10_REG 0X819F /* 触摸点10起始寄存器 */
#define GT_TP_OFFSET 8
#define MAX_SUPPORT_POINTS 10 /* 鏈€澶?0鐐圭數瀹硅Е鎽?*/
struct gt1151_dev
{
struct device_node *nd;
int irq_pin;
int reset_pin;
int irqnum;
void *private_data;
struct input_dev *input;
struct i2c_client *client;
};
struct gt1151_dev gt1151tsc;
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static int gt1151_read_regs(struct gt1151_dev *dev, u16 reg, void *val, int len)
{
int ret;
struct i2c_msg msg[2];
struct i2c_client *client = dev->client;
u8 reg8[2];
reg8[0] = reg>>8;
reg8[1] = reg&0xff;
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].buf = reg8;
msg[0].len = sizeof(reg8);
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].buf = val;
msg[1].len = len;
ret = i2c_transfer(client->adapter, msg, 2);
if(2==ret) ret = 0;
else ret = -EREMOTEIO;
return ret;
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static s32 gt1151_write_regs(struct gt1151_dev *dev, u16 reg, u8 *buf, u8 len)
{
u8 *wrbuf;
struct i2c_msg msg;
struct i2c_client *client = dev->client;
wrbuf = devm_kmalloc(&client->dev, (len+2), GFP_KERNEL);
if(IS_ERR(wrbuf)) return -ENOMEM;
wrbuf[0] = reg>>8;
wrbuf[1] = reg&0xff;
memcpy(&wrbuf[2], buf, len);
msg.addr = client->addr;
msg.flags = 0;
msg.buf = wrbuf;
msg.len = (len+2);
return i2c_transfer(client->adapter, &msg, 1);
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static void gt1151_read_reg(struct gt1151_dev *dev, u16 reg, u8 *pdata)
{
gt1151_read_regs(dev, reg, pdata, 1);
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static void gt1151_write_reg(struct gt1151_dev *dev, u16 reg, u8 data)
{
gt1151_write_regs(dev, reg, &data, 1);
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static irqreturn_t gt1151_irq_handler(int irq, void *dev_id)
{
struct gt1151_dev *dev = dev_id;
int x, y;
int id = 0;
u8 data;
u8 touch_num;
u8 touch_data[5];
int ret;
int i;
// invalid interrut
ret = gt1151_read_regs(dev, GT_STATE_REG, &data, 1); // GT1151标志
if(0==(data&0x80)) goto irq_out;
// get touch points
touch_num = data&0xf;
if(touch_num>0)
{
for(i=0;iinput, id);
input_mt_report_slot_state(dev->input, MT_TOOL_FINGER, true); //上报按键状态
input_report_abs(dev->input, ABS_MT_POSITION_X, x); // 上报坐标
input_report_abs(dev->input, ABS_MT_POSITION_Y, y);
}
}
else // 无触摸-全为抬起
{
for(i=0;iinput, i);
input_mt_report_slot_state(dev->input, MT_TOOL_FINGER, false);
}
}
input_mt_report_pointer_emulation(dev->input, true);
input_sync(dev->input);
data = 0x00; // 清除中断标志
gt1151_write_regs(dev, GT_STATE_REG, &data, 1);
irq_out:
return IRQ_HANDLED;
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static int gt1151_ts_reset(struct i2c_client *client, struct gt1151_dev *dev)
{
int ret = 0;
if(gpio_is_valid(dev->reset_pin))
{
ret = devm_gpio_request_one(&client->dev, dev->reset_pin, \
GPIOF_OUT_INIT_LOW, "gt1151-rst");
if(ret) return ret;
}
msleep(5);
gpio_set_value(dev->reset_pin, 1);
msleep(300);
// abandon first touch event
gt1151_write_reg(>1151tsc, GT_STATE_REG, 0); // 先清一次标志
return 0;
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static int gt1151_irq_init(struct i2c_client *client, struct gt1151_dev *dev)
{
int ret;
if(gpio_is_valid(dev->irq_pin))
{
ret = devm_gpio_request_one(&client->dev, dev->irq_pin, GPIOF_IN, "gt1151-irq");
if(ret)
{
dev_err(&client->dev, "request GPIO%d, error %d\n", dev->irq_pin, ret);
return ret;
}
}
printk("irq request success!\r\n");
// 申请中断
ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, \
gt1151_irq_handler, \
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, \
client->name, >1151tsc);
if(ret)
{
dev_err(&client->dev, "request irq faile!\n");
return ret;
}
return 0;
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static int gt1151_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret;
u8 chipID;
u16 productID;
gt1151tsc.client = client;
gt1151tsc.irq_pin = of_get_named_gpio(client->dev.of_node, "interrupt-gpios", 0);
gt1151tsc.reset_pin = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0);
printk("irq-pin=%d,rst-pin=%d\r\n",gt1151tsc.irq_pin,gt1151tsc.reset_pin);
// gt1151 reset
ret = gt1151_ts_reset(client, >1151tsc);
if(ret) goto fail;
// input device register
gt1151tsc.input = devm_input_allocate_device(&client->dev);
if(!gt1151tsc.input)
{
ret = -ENOMEM;
goto fail;
}
gt1151tsc.input->name = client->name;
gt1151tsc.input->id.bustype = BUS_I2C;
gt1151tsc.input->dev.parent = &client->dev;
__set_bit(EV_KEY, gt1151tsc.input->evbit); // 使能按键事件
__set_bit(EV_ABS, gt1151tsc.input->evbit); // 使能触摸事件
__set_bit(BTN_TOUCH, gt1151tsc.input->keybit); // 使能触摸按键
input_set_abs_params(gt1151tsc.input, ABS_X, 0, 800, 0, 0); // 设备坐标范围
input_set_abs_params(gt1151tsc.input, ABS_Y, 0, 480, 0, 0);
input_set_abs_params(gt1151tsc.input, ABS_MT_POSITION_X, 0, 800, 0, 0);
input_set_abs_params(gt1151tsc.input, ABS_MT_POSITION_Y, 0, 480, 0, 0);
ret = input_mt_init_slots(gt1151tsc.input, MAX_SUPPORT_POINTS, 0);// 同时触摸点数
if(ret) goto fail;
ret = input_register_device(gt1151tsc.input);
if(ret) goto fail;
printk("register my input success!\r\n");
// read product ID
gt1151_read_reg(>1151tsc, GT_PID_H_REG, &chipID); // 调试代码-读REG
productID = (u16)chipID<<8;
gt1151_read_reg(>1151tsc, GT_PID_L_REG, &chipID);
productID += chipID;
printk("productID=0x%4x", productID);
// gt1151 irq init
ret = gt1151_irq_init(client, >1151tsc); // 中断初始化
if(ret) goto fail;
return 0;
fail:
return ret;
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static int gt1151_remove(struct i2c_client *client)
{
input_unregister_device(gt1151tsc.input);
return 0;
}
const struct i2c_device_id gt1151_id_tab[] =
{
{"my_gt1151_tsc",0},
{},
};
const struct of_device_id gt1151_of_match_tab[] =
{
{.compatible="goodix,goodix-gt1151",},
{},
};
static struct i2c_driver gt1151_driver =
{
.probe = gt1151_probe,
.remove = gt1151_remove,
.driver = {
.name = MY_DEV_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gt1151_of_match_tab),
},
.id_table = gt1151_id_tab,
};
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static int __init gt1151_init(void)
{
return i2c_add_driver(>1151_driver);
}
/******************************************************************************
* Function:
* Description:
* ***************************************************************************/
static void __exit gt1151_exit(void)
{
i2c_del_driver(>1151_driver);
}
module_init(gt1151_init);
module_exit(gt1151_exit);
MODULE_LICENSE("GPL");
注意要点:
1.必须先读状态寄存器,如果无有效数据的话,就直接退出中断,不要去清状态标志。
如果数据无效时清了状态标志,就会一直读不到有效数。
2.无法上报抬起事件,只有全部手指抬起后一起上报所有通道的抬起事件。
不过这样不影响使用。在TSLIB上画线没有问题,最多的时候画了5条线也可以。
3.第一个被追踪到的ID永远都是0。当多个手指依次放在触摸屏上,会依次追踪到id0、id1、、、
但是当有手指抬起时,通道0上报的就不一定是id0了,也有可能是id2或其它的。
4.当一个通道无效时(没有检测到触摸手指),那这个通道的id=0.但第一个检测到的有效触摸
的id也是0.感觉有点不合理。