1.开发板简单介绍
讯为4412开发板用的触摸芯片是ft5306,通讯方式是I2C。
如上图所示,要驱动这个触摸芯片,需要控制四个引脚:INT,RST,SDA,SCL。
2.驱动程序分析
(1)初始化触摸芯片
static int __init ft5x0x_ts_init(void)
{
int ret;
int type;
type = get_lcd_type();
#if 1
//TP1_EN
//printk("==%s: TP1_EN==\n", __FUNCTION__);//触摸芯片初始化
ret = gpio_request(EXYNOS4_GPL0(2), "TP1_EN");
if (ret) {
printk(KERN_ERR "failed to request TP1_EN for "
"I2C control\n");
//return err;
}
gpio_direction_output(EXYNOS4_GPL0(2), 1);
s3c_gpio_cfgpin(EXYNOS4_GPL0(2), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPL0(2));
mdelay(5);
#endif
#if 1
printk("==%s: reset==\n", __FUNCTION__);//启动的时候复位触摸芯片
ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3");
if (ret) {
gpio_free(EXYNOS4_GPX0(3));
ret = gpio_request(EXYNOS4_GPX0(3), "GPX0_3");
if(ret)
{
printk("ft5xox: Failed to request GPX0_3 \n");
}
}
gpio_direction_output(EXYNOS4_GPX0(3), 0);//复位引脚拉低再拉高
mdelay(200);
gpio_direction_output(EXYNOS4_GPX0(3), 1);
s3c_gpio_cfgpin(EXYNOS4_GPX0(3), S3C_GPIO_OUTPUT);
gpio_free(EXYNOS4_GPX0(3));
msleep(300);
............................
return i2c_add_driver(&ft5x0x_ts_driver);
}
(2)触摸芯片注册
static int ft5x0x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct ft5x0x_i2c_platform_data *pdata;
struct ft5x0x_ts_data *ts;
struct input_dev *input_dev;
unsigned char val;
// unsigned int ctp_id;
int err = -EINVAL;
//cym ctp_id = get_ctp();
//if (ctp_id != CTP_FT5X06 && ctp_id != CTP_AUTO) {
// return -ENODEV;
//}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit_check_functionality_failed;
}
ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (!ts) {
err = -ENOMEM;
goto exit_alloc_data_failed;
}
pdata = client->dev.platform_data;
if (!pdata) {
dev_err(&client->dev, "failed to get platform data\n");
goto exit_no_pdata;
}
ts->screen_max_x = pdata->screen_max_x;
ts->screen_max_y = pdata->screen_max_y;
ts->pressure_max = pdata->pressure_max;
ts->gpio_irq = pdata->gpio_irq;
if (ts->gpio_irq != -EINVAL) {
client->irq = gpio_to_irq(ts->gpio_irq);
} else {
goto exit_no_pdata;
}
if (pdata->irq_cfg) {
s3c_gpio_cfgpin(ts->gpio_irq, pdata->irq_cfg);
s3c_gpio_setpull(ts->gpio_irq, S3C_GPIO_PULL_NONE);
}
ts->gpio_wakeup = pdata->gpio_wakeup;
ts->gpio_reset = pdata->gpio_reset;
INIT_WORK(&ts->work, ft5x0x_ts_pen_irq_work);//注册中断处理队列程序,用于中断后段处理:ft5x0x_ts_pen_irq_work
this_client = client;
i2c_set_clientdata(client, ts);
/*创建工作队列线程,用于检测触摸信号*/
ts->queue = create_singlethread_workqueue(dev_name(&client->dev));
if (!ts->queue) {
err = -ESRCH;
goto exit_create_singlethread;
}
/*分配输入设备*/
input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
dev_err(&client->dev, "failed to allocate input device\n");
goto exit_input_dev_alloc_failed;
}
ts->input_dev = input_dev;
/*设置输入设备模式*/
set_bit(EV_SYN, input_dev->evbit);
set_bit(EV_ABS, input_dev->evbit);
set_bit(EV_KEY, input_dev->evbit);
#ifdef CONFIG_FT5X0X_MULTITOUCH
set_bit(ABS_MT_TRACKING_ID, input_dev->absbit);
set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
set_bit(ABS_MT_POSITION_X, input_dev->absbit);
set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
/*绑定输入设备参数*/
input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ts->screen_max_x, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ts->screen_max_y, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, ts->pressure_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, FT5X0X_PT_MAX, 0, 0);
#else
set_bit(ABS_X, input_dev->absbit);
set_bit(ABS_Y, input_dev->absbit);
set_bit(ABS_PRESSURE, input_dev->absbit);
set_bit(BTN_TOUCH, input_dev->keybit);
input_set_abs_params(input_dev, ABS_X, 0, ts->screen_max_x, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, ts->screen_max_y, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, ts->pressure_max, 0 , 0);
#endif
input_dev->name = FT5X0X_NAME;
input_dev->id.bustype = BUS_I2C;
input_dev->id.vendor = 0x12FA;
input_dev->id.product = 0x2143;
input_dev->id.version = 0x0100;
/*注册输入设备*/
err = input_register_device(input_dev);
if (err) {
input_free_device(input_dev);
dev_err(&client->dev, "failed to register input device %s, %d\n",
dev_name(&client->dev), err);
goto exit_input_dev_alloc_failed;
}
msleep(3);
err = ft5x0x_read_fw_ver(&val);
if (err < 0) {
dev_err(&client->dev, "chip not found\n");
goto exit_irq_request_failed;
}
/*申请i2c的中断资源*/
err = request_irq(client->irq, ft5x0x_ts_interrupt,
IRQ_TYPE_EDGE_FALLING /*IRQF_TRIGGER_FALLING*/, "ft5x0x_ts", ts);
if (err < 0) {
dev_err(&client->dev, "Request IRQ %d failed, %d\n", client->irq, err);
goto exit_irq_request_failed;
}
disable_irq(client->irq);
dev_info(&client->dev, "Firmware version 0x%02x\n", val);//读取触摸芯片的固件版本号
#ifdef CONFIG_HAS_EARLYSUSPEND
ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;//EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
ts->early_suspend.suspend = ft5x0x_ts_suspend;
ts->early_suspend.resume = ft5x0x_ts_resume;
register_early_suspend(&ts->early_suspend);
#endif
enable_irq(client->irq);
//cym 4412_set_ctp(CTP_FT5X06);
dev_info(&client->dev, "FocalTech ft5x0x TouchScreen initialized\n");
return 0;
exit_irq_request_failed:
input_unregister_device(input_dev);
exit_input_dev_alloc_failed:
cancel_work_sync(&ts->work);
destroy_workqueue(ts->queue);
exit_create_singlethread:
i2c_set_clientdata(client, NULL);
exit_no_pdata:
kfree(ts);
exit_alloc_data_failed:
exit_check_functionality_failed:
dev_err(&client->dev, "probe ft5x0x TouchScreen failed, %d\n", err);
return err;
}