Linux capacitive touch screen Driver Based on FT5x06

Source: Internet
Author: User

**************************************** **************************************** **************************************** ***
Author: EasyWave time: 2013.02.06

Category: Linux kernel driver source code analysis statement: reprinted, please keep the link

NOTE: If any error occurs, please correct it. These are my Learning Log articles ......

**************************************** **************************************** **************************************** ***

I. Introduction to FT5X06 capacitive touch IC

The FT5x06 series ICs is a single-chip capacitive touch screen controller IC with a built-in 8-Bit Microcontroller Unit (MCU ). Using the method of mutual capacitance, in combination with the mutual capacitive touch panel, it supports real multi-point touch function. FT5x06 features user-friendly input, which can be applied on many portable devices, such as cellular phones, mobile internet devices, netbooks and laptops. The FT5x06 series ICS include FT5206, FT5306, and FT5406. Specific functions are shown in:

 

Ii. hardware interface design

From datasheet of FT5X06, we can see that FT5X06 can work in both the SPI interface mode and I2C interface mode, whether working in SPI or I2C, in terms of the hardware interface design, the following control ports need to be connected. As shown in:

1): The INT pin, which is a mid-range signal. It is used to notify the HOST terminal that FT5X06 is ready for reading.

2): WAKE pin: this function is mainly used to convert FT5X06 from sleep to working.

3):/RST pin: reset signal of the FT5X06 chip.

How can we design hardware interfaces? We can see from datasheet in FT5X06. First, let's look at the power-on sequence of FT5X06, as shown in:

Power-on sequence of FT5X06

RESET sequence of FT5X06

Wakeup sequence of FT5X06

The minimum time limits are as follows:

Therefore, from the above image and table, we can see that in poweron, we must ensure that the level of wakeup is high after power-on, as for INT signal, as long as there is no INT signal, this INT is high. We can see from the time sequence of poweron that it is a low-level action, which is what the driver is doing.

Next, determine the I2C slave address, as shown in:[Reference from the network below]

The slave address's high position must be 3, and the low position must be determined based on the value set by i2ccon.

According to the instructions in the FT5406 Data Manual, we first understand how the driver achieves multi-point touch on the capacitive screen. In fact, it is very simple to use the touch screen IC FT5406 to capture multi-point data, this capacitive screen basically supports capturing more than 2 points, while FT5406 can capture 5 touch points. When writing a driver, you only need to get the data of these points and then report it. As shown in:[Reference from the network below]

02 H: Number of captured touch points 03 H-1EH: x and y coordinate values for each point.

 

Iii. Linux driver source code

The I2C driver is based on the specific ARM chip. Generally, the original IC will usually have the I2C driver in the linux bsp. We do not need to write this part, we only need to match the FT5X06 and the I2C driver in the BSP package. The same is true for the entire FT5X06. In the linu kernel, i2c usually has this function: i2c_board_info () i2c_board_info is used to build the information table to list the existing I2C devices. This information is used to increase the driver model tree of the new I2C driver. For the motherboard, it uses i2c_register_board_info () for static creation. For sub-boards, use known adapters to dynamically create using i2c_new_device.

struct i2c_board_info {    char type[I2C_NAME_SIZE];      unsigned short flags;      unsigned short addr;      void *platform_data;      struct dev_archdata *archdata;      int irq;  };static struct i2c_board_info i2c_devs0[] __initdata = {#ifdef CONFIG_TOUCHSCREEN_CDTLCD{I2C_BOARD_INFO("ft5x0x_ts", 0x3x),.irq = IRQ_EINT1,},#endif };


Finally, call int i2c_register_board_info (int busnum, struct i2c_board_info const * info, unsigned len) in the kernel initialization part. The following is a detailed explanation:
@ Busnum: Specifies the bus to which these devices belong.
@ Info: I2C device descriptor Vector
@ Len: Number of descriptors in the vector. to reserve a specific bus number, it can be 0.
I2c_register_board_info (0, i2c_devs0, ARRAY_SIZE (i2c_devs0 ));


The following code is pasted :[The following code is the Linux driver in Android. If you want to modify it to a general Linux kernel, You need to modify]

static int ft5x0x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){struct ft5x0x_ts_data *ft5x0x_ts;struct input_dev *input_dev;int err = 0;unsigned char uc_reg_value; #if CFG_SUPPORT_TOUCH_KEY    int i;#endifprintk("[FTS] ft5x0x_ts_probe, driver version is %s.\n", CFG_FTS_CTP_DRIVER_VERSION);if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {err = -ENODEV;goto exit_check_functionality_failed;}ft5x0x_ts = kzalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);//ft5x0x_ts = kmalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);if (!ft5x0x_ts){err = -ENOMEM;goto exit_alloc_data_failed;}//memset(ft5x0x_ts, 0, sizeof(struct ft5x0x_ts_data));this_client = client;i2c_set_clientdata(client, ft5x0x_ts);mutex_init(&ft5x0x_ts->device_mode_mutex);INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work);ft5x0x_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev));if (!ft5x0x_ts->ts_workqueue) {err = -ESRCH;goto exit_create_singlethread;}err = request_irq(IRQ_EINT(6), ft5x0x_ts_interrupt, IRQF_TRIGGER_FALLING, "ft5x0x_ts", ft5x0x_ts);if (err < 0) {dev_err(&client->dev, "ft5x0x_probe: request irq failed\n");goto exit_irq_request_failed;}disable_irq(IRQ_EINT(6));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;}ft5x0x_ts->input_dev = input_dev;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);input_set_abs_params(input_dev,     ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);input_set_abs_params(input_dev,     ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);input_set_abs_params(input_dev,     ABS_MT_TOUCH_MAJOR, 0, PRESS_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, 5, 0, 0);    set_bit(EV_KEY, input_dev->evbit);    set_bit(EV_ABS, input_dev->evbit);#if CFG_SUPPORT_TOUCH_KEY    //setup key code area    set_bit(EV_SYN, input_dev->evbit);    set_bit(BTN_TOUCH, input_dev->keybit);    input_dev->keycode = tsp_keycodes;    for(i = 0; i < CFG_NUMOFKEYS; i++)    {        input_set_capability(input_dev, EV_KEY, ((int*)input_dev->keycode)[i]);        tsp_keystatus[i] = KEY_RELEASE;    }#endifinput_dev->name= FT5X0X_NAME;//dev_name(&client->dev)err = input_register_device(input_dev);if (err) {dev_err(&client->dev,"ft5x0x_ts_probe: failed to register input device: %s\n",dev_name(&client->dev));goto exit_input_register_device_failed;}#ifdef CONFIG_HAS_EARLYSUSPENDprintk("==register_early_suspend =\n");ft5x0x_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;ft5x0x_ts->early_suspend.suspend = ft5x0x_ts_suspend;ft5x0x_ts->early_suspend.resume= ft5x0x_ts_resume;register_early_suspend(&ft5x0x_ts->early_suspend);#endif    msleep(150);  //make sure CTP already finish startup process        //get some register information    uc_reg_value = ft5x0x_read_fw_ver();    printk("[FTS] Firmware version = 0x%x\n", uc_reg_value);    ft5x0x_read_reg(FT5X0X_REG_PERIODACTIVE, &uc_reg_value);    printk("[FTS] report rate is %dHz.\n", uc_reg_value * 10);    ft5x0x_read_reg(FT5X0X_REG_THGROUP, &uc_reg_value);    printk("[FTS] touch threshold is %d.\n", uc_reg_value * 4);#if CFG_SUPPORT_AUTO_UPG    fts_ctpm_auto_upg();#endif    #if CFG_SUPPORT_UPDATE_PROJECT_SETTING    fts_ctpm_update_project_setting();#endif    enable_irq(IRQ_EINT(6));   //create sysfs   err = sysfs_create_group(&client->dev.kobj, &ft5x0x_attribute_group);   if (0 != err)  {dev_err(&client->dev, "%s() - ERROR: sysfs_create_group() failed: %d\n", __FUNCTION__, err);sysfs_remove_group(&client->dev.kobj, &ft5x0x_attribute_group);  }   else    {        printk("ft5x0x:%s() - sysfs_create_group() succeeded.\n", __FUNCTION__);    }printk("[FTS] ==probe over =\n");    return 0;exit_input_register_device_failed:input_free_device(input_dev);exit_input_dev_alloc_failed://free_irq(client->irq, ft5x0x_ts);free_irq(IRQ_EINT(6), ft5x0x_ts);exit_irq_request_failed://exit_platform_data_null:cancel_work_sync(&ft5x0x_ts->pen_event_work);destroy_workqueue(ft5x0x_ts->ts_workqueue);exit_create_singlethread:printk("==singlethread error =\n");i2c_set_clientdata(client, NULL);kfree(ft5x0x_ts);exit_alloc_data_failed:exit_check_functionality_failed:return err;}static int __devexit ft5x0x_ts_remove(struct i2c_client *client){struct ft5x0x_ts_data *ft5x0x_ts;printk("==ft5x0x_ts_remove=\n");ft5x0x_ts = i2c_get_clientdata(client);unregister_early_suspend(&ft5x0x_ts->early_suspend);//free_irq(client->irq, ft5x0x_ts);mutex_destroy(&ft5x0x_ts->device_mode_mutex);free_irq(IRQ_EINT(6), ft5x0x_ts);input_unregister_device(ft5x0x_ts->input_dev);kfree(ft5x0x_ts);cancel_work_sync(&ft5x0x_ts->pen_event_work);destroy_workqueue(ft5x0x_ts->ts_workqueue);i2c_set_clientdata(client, NULL); del_timer(&test_timer);return 0;}static const struct i2c_device_id ft5x0x_ts_id[] = {{ FT5X0X_NAME, 0x3x },{ }};MODULE_DEVICE_TABLE(i2c, ft5x0x_ts_id);static struct i2c_driver ft5x0x_ts_driver = {.probe= ft5x0x_ts_probe,.remove= __devexit_p(ft5x0x_ts_remove),.id_table= ft5x0x_ts_id,.driver= {.name= FT5X0X_NAME,.owner= THIS_MODULE,},};static int __init ft5x0x_ts_init(void){int ret;printk("==ft5x0x_ts_init==\n");ret = i2c_add_driver(&ft5x0x_ts_driver);printk("ret=%d\n",ret);return ret;}static void __exit ft5x0x_ts_exit(void){printk("==ft5x0x_ts_exit==\n");i2c_del_driver(&ft5x0x_ts_driver);}module_init(ft5x0x_ts_init);module_exit(ft5x0x_ts_exit);MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver");MODULE_LICENSE("GPL");


Porting to a general Linux kernel won't be written. Study it by yourself.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.