GT1151多点触摸屏例程

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/ratelimit.h>

#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>



#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;i<touch_num;i++)                                    // 读取全部有效坐标
        {   // 读坐标
            ret = gt1151_read_regs(dev, GT_TP1_REG+GT_TP_OFFSET*i, touch_data, 5);
            id = touch_data[0] & 0xF;
            x  = touch_data[1] | (touch_data[2] << 8);
            y  = touch_data[3] | (touch_data[4] << 8);

            input_mt_slot(dev->input, 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;i<MAX_SUPPORT_POINTS;i++)
        {
            input_mt_slot(dev->input, 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(&gt1151tsc, 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, &gt1151tsc);
	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, &gt1151tsc);
    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(&gt1151tsc, GT_PID_H_REG, &chipID);                // 调试代码-读REG
    productID = (u16)chipID<<8;
    gt1151_read_reg(&gt1151tsc, GT_PID_L_REG, &chipID);
    productID += chipID;
    printk("productID=0x%4x", productID);

    // gt1151 irq init
    ret = gt1151_irq_init(client, &gt1151tsc);                        // 中断初始化
    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(&gt1151_driver);
}


/******************************************************************************
 * Function:
 * Description:
 * ***************************************************************************/
static void __exit gt1151_exit(void)
{
    i2c_del_driver(&gt1151_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.感觉有点不合理。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值