自学内容网 自学内容网

RK3288 android7.1 适配 ilitek i2c接口TP

一,Ilitek 触摸屏简介

  1. Ilitek 提供多种型号的触控屏控制器,如 ILI6480、ILI9341 等,采用 I2C 接口。
    这些控制器能够支持多点触控,并具有优秀的灵敏度和响应速度。

  2. Ilitek 的触摸屏控制器监测屏幕上的触摸事件。
    当触摸发生时,控制器将触摸坐标(通常是 x 和 y 坐标)通过 I2C 总线发送给主机。


二,DTS配置

在这里插入图片描述

&i2c1 {
       status = "okay";

       ilitek@41 {
               compatible = "tchip,ilitek";
               reg = <0x41>;
               ilitek,irq-gpio = <&gpio7 6 GPIO_ACTIVE_HIGH>;
               ilitek,reset-gpio = <&gpio7 15 GPIO_ACTIVE_HIGH>; //修改相对应的gpio参数
               pinctrl-names = "default";
               pinctrl-0 = <&ilitek_gpio_e>;
               status = "okay";
    };
};

&pinctrl {

       touchscreen {
        ilitek_gpio_e: ilitek-gpio-e {
            rockchip,pins =
                <7 6 RK_FUNC_GPIO &pcfg_pull_up>,
                <7 15 RK_FUNC_GPIO &pcfg_pull_up>;
       };
       };
};

注:一定要对应的I2C bus节点(硬件原理图上会有标注)。


三,驱动文件配置

在这里插入图片描述

1. ilitek_lim.c

static int ilitek_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
int revert_x=0;
int revert_y=0;
        int revert_x_y=0;
struct device_node *param_node;
#ifdef ILI_UPDATE_FW
#ifdef UPDATE_THREADE
struct task_struct *thread_update = NULL;
#endif
#endif

#ifdef RECOGNITION_LONGTIME_BUTTON
struct task_struct *thread_longtime_button = NULL;
#endif

#ifdef WRITE_2210_CFG
struct task_struct *thread_write_cfg = NULL;
#endif

#if IC2120
int i = 0;
#endif
//int i = 0;
//uint8_t buf[8] = {0};
#ifdef DEBUG_NETLINK
struct netlink_kernel_cfg cfg = {
.groups = 0,
.input= udp_receive,
};

#endif
tp_log_info("Enter ilitek_i2c_probe +++++++++ client->addr = 0x%x++++++\n", client->addr);
if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
tp_log_err("%s, I2C_FUNC_I2C not support\n", __func__);
return -1;
}
// initialize global variable
#ifdef TOOL
memset(&dev_ilitek, 0, sizeof(struct dev_data));
#endif
memset(&i2c, 0, sizeof(struct i2c_data));

// initialize mutex object
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
init_MUTEX(&i2c.wr_sem);
#else
sema_init(&i2c.wr_sem,1);
#endif

i2c.wr_sem.count = 1;
mutex_init(&(i2c.irq_mutex));
i2c.report_status = 1;

i2c.client = client;

#ifdef CONFIG_ENABLE_REGULATOR_POWER_ON
ret = ilitek_get_regulator();
if (ret) {
tp_log_err("%s, ilitek_get_regulator failed\n", __func__);
return ret;
}
ret = ilitek_power_on(true);
if (ret) {
tp_log_err("%s, power on failed\n", __func__);
return ret;
}
#endif

//
ret = ilitek_request_io_port(client);
if (ret != 0)
{
tp_log_err("%s, io error", __func__);
return ret;
}

       param_node = of_find_node_by_path("/smdt_param");
       if (!param_node){
               printk("gt9xx wxl error smdt_param not node!!!\n");
       }

       of_property_read_u32(param_node, "ctp_revert_x_flag", &revert_x);
       of_property_read_u32(param_node, "ctp_revert_y_flag", &revert_y);
       of_property_read_u32(param_node, "ctp_exchange_x_y_flag", &revert_x_y);
       
       if(revert_x == 1 )
           REVERT_X = 1;
       else    
           REVERT_X = 0;
       if(revert_y == 1 )
           REVERT_Y = 1;
       else    
           REVERT_Y = 0;
       if(revert_x_y == 1 )
           EXCHANG_XY = 1;
       else    
           EXCHANG_XY = 0;


i2c.client->irq  = gpio_to_irq(i2c.irq_gpio);
tp_log_info("ilitek i2c.irq_gpio = %d, i2c.client->irq = %d\n", i2c.irq_gpio, i2c.client->irq);
i2c.valid_i2c_register = 1;
#if 1
ilitek_reset(i2c.reset_gpio);
#endif
#if !IC2120
mdelay(200);
#else
for (i = 0; i < 30; i++ ) {
ret = ilitek_poll_int();
tp_log_info("ilitek int status = %d\n", ret);
if (ret == 0) {
break;
}
else {
mdelay(5);
}
}

if (i >= 30) {

#ifdef ILI_UPDATE_FW
tp_log_info("ilitek reset but int not pull low so driver_upgrade_flag = true\n");
driver_upgrade_flag = true;
#endif
}
else 
#endif
{
#if 0
msleep(2000);
for (i = 0; i < 127; i++) {
//buf[0] = 0x10;
client->addr = i;
ret = ilitek_i2c_write_and_read(i2c.client, buf, 0, 10, buf, 4);
tp_log_info("ilitek %s, write 0x10 read buf = %X, %X, %X\n", __func__, buf[0], buf[1], buf[2]);
if (ret < 0) {
mdelay(5);
}
else {
tp_log_info("ilitek %s, client->addr = 0x%X, read buf = %X, %X, %X\n", __func__, client->addr, buf[0], buf[1], buf[2]);
tp_log_info("ilitek %s, client->addr = 0x%X, read buf = %X, %X, %X\n", __func__, client->addr, buf[0], buf[1], buf[2]);
tp_log_info("ilitek %s, client->addr = 0x%X, read buf = %X, %X, %X\n", __func__, client->addr, buf[0], buf[1], buf[2]);
tp_log_info("ilitek %s, client->addr = 0x%X, read buf = %X, %X, %X\n", __func__, client->addr, buf[0], buf[1], buf[2]);
tp_log_info("ilitek %s, client->addr = 0x%X, read buf = %X, %X, %X\n", __func__, client->addr, buf[0], buf[1], buf[2]);
break;
}
}
#endif
// read touch parameter
ret = ilitek_i2c_read_tp_info();
if(ret < 0){
tp_log_err("ilitek read tp info fail free gpio\n");
if (gpio_is_valid(i2c.irq_gpio)) {
gpio_free(i2c.irq_gpio);
}
if (gpio_is_valid(i2c.reset_gpio)) {
gpio_free(i2c.reset_gpio);
}
return ret;
}
}
#ifdef CLOCK_INTERRUPT
#ifdef REPORT_THREAD
i2c.thread = kthread_run(ilitek_i2c_touchevent_thread, NULL, "ilitek_i2c_thread");
if(i2c.thread == (struct task_struct*)ERR_PTR){
i2c.thread = NULL;
tp_log_err("%s, kthread create, error\n", __func__);
}
#endif
#endif
ilitek_handle_irqorpolling();
i2c.input_dev = input_allocate_device();
if(i2c.input_dev == NULL){
tp_log_err("%s, allocate input device, error\n", __func__);
return -1;
}

ilitek_set_input_param(i2c.input_dev, i2c.max_tp, i2c.max_x, i2c.max_y);
ret = input_register_device(i2c.input_dev);
if(ret){
tp_log_err("%s, register input device, error\n", __func__);
return ret;
}
i2c.valid_input_register = 1;
tp_log_info("%s, register input device, success\n", __func__);
#ifdef ILI_UPDATE_FW
#ifndef UPDATE_THREADE
{
update_wait_flag = 1;
ret = ilitek_upgrade_firmware();
if(ret == ILITEK_UPDATE_OK) {
tp_log_info("update end\n");
}
else if(ret == ILITEK_I2C_TRANSFER_ERR) {
tp_log_info("i2c communication error\n");
}
if(i2c.reset_request_success){
ilitek_reset(i2c.reset_gpio);
}

// read touch parameter
ret=ilitek_i2c_read_tp_info();
if(ret < 0)
{
tp_log_err("ilitek_i2c_read_tp_info err\n");
return ret;
}
update_wait_flag = 0;
#if 1
input_unregister_device(i2c.input_dev);
#if 1
i2c.input_dev = input_allocate_device();
if(i2c.input_dev == NULL){
tp_log_err("%s, allocate input device, error\n", __func__);
return -1;
}
#endif
// register input device
//memset(i2c.input_dev, 0, sizeof(struct input_dev));
// register input device
ilitek_set_input_param(i2c.input_dev, i2c.max_tp, i2c.max_x, i2c.max_y);
ret = input_register_device(i2c.input_dev);
if(ret){
tp_log_err("%s, register input device, error\n", __func__);
return ret;
}
tp_log_info("%s, register input device, success\n", __func__);
#endif
}
#else
{
thread_update= kthread_run(ilitek_i2c_update_thread, NULL, "ilitek_i2c_updatethread");
if(thread_update == (struct task_struct*)ERR_PTR){
thread_update = NULL;
tp_log_err("%s,thread_update kthread create, error\n", __func__);
}
}
#endif
#endif

#ifdef WRITE_2210_CFG
thread_write_cfg = kthread_run(ilitek_i2c_write_cfg_thread, NULL, "ilitek_i2c_write_cfg_thread");
if(thread_write_cfg == (struct task_struct*)ERR_PTR){
thread_write_cfg = NULL;
tp_log_err("%s,thread_write_cfg kthread create, error\n", __func__);
}
#endif

#ifdef RECOGNITION_LONGTIME_BUTTON
thread_longtime_button = kthread_run(ilitek_i2c_check_longtime_button_thread, NULL, "ilitek_i2c_check_longtime_button_thread");
if(thread_longtime_button == (struct task_struct*)ERR_PTR){
thread_longtime_button = NULL;
tp_log_err("%s,thread_longtime_button kthread create, error\n", __func__);
}
#endif

#ifdef GESTURE
ilitek_system_resume = 1;
input_set_capability(i2c.input_dev, EV_KEY, KEY_POWER);
input_set_capability(i2c.input_dev, EV_KEY, KEY_W);
input_set_capability(i2c.input_dev, EV_KEY, KEY_LEFT);
input_set_capability(i2c.input_dev, EV_KEY, KEY_RIGHT);
input_set_capability(i2c.input_dev, EV_KEY, KEY_UP);
input_set_capability(i2c.input_dev, EV_KEY, KEY_DOWN);
input_set_capability(i2c.input_dev, EV_KEY, KEY_O);
input_set_capability(i2c.input_dev, EV_KEY, KEY_C);
input_set_capability(i2c.input_dev, EV_KEY, KEY_E);
input_set_capability(i2c.input_dev, EV_KEY, KEY_M);
#endif

#ifdef TOOL
ret = create_tool_node();
#endif

#ifdef SENSOR_TEST
#ifdef SYS_ATTR_FILE
ilitek_sensor_test_init();
#endif
#endif

#ifdef HALL_CHECK
#if HALL_CHECK == HALL_CHECK_OTHER
ilitek_hall_check_init();
#elif HALL_CHECK == HALL_CHECK_HW
ilitek_hall_check_hw_init();
#endif //end of HALL_CHECK
#endif
Report_Flag=0;

#ifdef PLAT_ROCKCHIP
    i2c.tp.tp_resume = ilitek_i2c_late_resume;
    i2c.tp.tp_suspend = ilitek_i2c_early_suspend;
    tp_register_fb(&i2c.tp);
#endif

#ifdef ILITEK_ESD_CHECK
 INIT_DELAYED_WORK(&esd_work, ilitek_touch_esd_func);
 esd_wq = create_singlethread_workqueue("esd_wq"); 
 if (!esd_wq) {
 return -ENOMEM;
 }
 queue_delayed_work(esd_wq, &esd_work, delay);
#endif 

#ifdef WRITE_2210_CFG
ret = sysfs_create_group(&client->dev.kobj, &ilitek_test_attribute_group);
if (ret) {
dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
ret);
return ret;
}
#endif
#ifdef DEBUG_NETLINK
//netlink_sock = netlink_kernel_create(&init_net, 21, 0,udp_receive, NULL, THIS_MODULE);
netlink_sock = netlink_kernel_create(&init_net, 21, &cfg);

#endif
device_init_wakeup(&client->dev, 1);
return 0;
}

ilitek_i2c_probe 函数是 I2C 设备的初始化函数,在设备被识别和加载驱动时调用。它的主要职责包括:

  • 初始化设备:根据 I2C 客户端信息和设备 ID 来配置和初始化设备。
  • 分配所需资源:如内存、GPIO 等。
  • 设置中断处理程序(如适用):为设备配置中断。
  • 注册输入设备:根据设备类型设置输入设备的相关参数。

2. ilitek_ts.h

ilitek_ts.h用于定义驱动相关的数据结构、常量、函数原型以及其他必要的包含。该头文件的内容用于抽象和管理与 Ilitek 触摸屏控制器之间的接口。

3. ILI25110CN080O0003_CRC.ili

ILI25110CN080O0003_CRC.ili 可能是与 Ilitek 触摸屏控制器 ILI2511 系列相关的文件。

4. 驱动移植

a.将原厂提供的的驱动(ilitek)拷贝到下面的文件夹:

./kernel/drivers/input/touchscreen

b. 然后修改 touchscreen 目录下的 Makefile以及Kconfig。这个Makefile中定义的就是要编译哪个平台的触摸屏驱动的。

kernel/drivers/input/touchscreen/Makefile中添加:
obj-$(CONFIG_TOUCHSCREEN_ILITEK)     += ilitek/

--------------------------------------------------------
kernel/drivers/input/touchscreen/Kconfig中添加:
config TOUCHSCREEN_ILITEK
       tristate "ILITEK touchscreens matched with screen support for rockchip platform"
       depends on I2C && ARCH_ROCKCHIP
       help
         Say Y here if you have a touchscreen interface using the ILITEK
         touchscreen chip on Rockchip platform, and your board-specific
         initialization code includes that in its table of IIC devices.
         If unsure, say N.

c. 内核中加载驱动:

kernel/arch/arm/configs/rockchip_defconfig中添加:
CONFIG_TOUCHSCREEN_ILITEK=y

四,调试

  1. 确认 /sys/bus/i2c/devices 下有裝置节点 (-0041);
    在这里插入图片描述
  2. 报点问题:
    有触摸效果,只是坐标 mapping 问题。

X、Y 需要交換。
將 ILITEK_ROTATE_FLAG 设定值由 0 改为 1 或由 1 改为 0。

X、Y 值要做鏡像变化。
將 ILITEK_REVERT_X 或 ILITEK_REVERT_Y 的设定值由 0 改为 1 或由 1 改为 0。

若需要指定显示屏的解析度。
则开放 ILITEK_USE_LCM_RESOLUTION 宏,同时將TOUCH_SCREEN_X_MAX 和 TOUCH_SCREEN_Y_MAX 设为正确值。


原文地址:https://blog.csdn.net/weixin_45639314/article/details/143628352

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!