• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

STM32MP157驱动开发——多点电容触摸屏驱动

武飞扬头像
Amonter
帮助5


参考文章:【正点原子】I.MX6U嵌入式Linux驱动开发——多点电容触摸屏

一、简介

  一开始出现的触摸屏是电阻触摸屏,只能单点触摸,在以前的学习机、功能机时代被广泛使用。2007年苹果的一代 iPhone,也就是 iPhone 2G上使用了多点电容触摸屏。和电阻触摸屏相比,电容触摸屏最大的优点是支持多点触摸(现在的电阻屏也支持多点触控了)。此外,电容屏只需要手指轻触即可,而电阻屏是需要手指给予一定的压力才有反应,而且电容屏不需要校准。
  正点原子的触摸屏采用的是 LCD 触摸屏结合的方式。底下是 LCD 面板,上面是触摸面板,将两个封装到一起就成了带有触摸屏的 LCD 屏幕。电容触摸屏需要一个驱动 IC 来实现,一般使用的是 IIC 接口。主控制器可以通过 I2C 接口来读取驱动 IC里面的触摸坐标数据。原子的 ATK-7016、ATK-7084 触控 IC 为 FT5426,ATK-4342 使用的触控 IC 为 GT9147。
  本节就对 FT5426 进行开发。FT5426 的 I2C 设备地址为 0X38,ATK-7016 的电容触摸屏部分有 4 个 IO 用于连接主控制器:SCL、SDA、RST 和 INT,SCL 和 SDA 是 I2C 引脚,RST 是复位引脚,INT 是中断引脚。一般通过 INT 引脚来通知主控制器有触摸点按下,然后在 INT 中断服务函数中读取触摸数据。

二、电容触摸屏驱动框架简介

多点触摸(MT)协议详解

电容触摸屏驱动其实就是以下几种 linux 驱动框架的组合:

  • IIC 设备驱动,因为电容触摸 IC 基本都是 IIC 接口的,因此大框架就是 IIC 设备驱动
  • 通过中断引脚(INT)向 linux 内核上报触摸信息,因此需要用到 linux 中断驱动框架。坐标的上报在中断服务函数中完成。
  • 触摸屏的坐标信息、屏幕按下和抬起信息都属于 linux 的 input 子系统,因此向 linux 内核上报触摸屏坐标信息就得使用 input 子系统。
  • 在中断处理程序中按照 linux 的 MT 协议上报坐标信息。

linux内核中有一份文档详细的讲解了多点电容触摸屏协议,文档路径为:Documentation/input/multitouch-protocol.txt。且老版本中不支持此协议。
MT 协议被分为两种类型,TypeA 和 TypeB:
Type A:适用于触摸点不能被区分或者追踪,此类型的设备通常上报原始数据(此类型在实际使用中非常少!)
Type B:适用于有硬件追踪并能区分触摸点的触摸设备,此类型设备通过 slot 更新某一个触摸点的信息,FT5426 就属于此类型,一般的多点电容触摸屏 IC 都有此能力。
Type A时序:x1–>y1–>mt-sync–>x2–>y2–>mt-sync–>input-sync。
Type B时序:mt-slot–>mt-id–>x1–>y1–…–>sync

在电容触摸屏驱动框架中,会通过中断来向系统上报触摸点坐标信息的。但是此中断的申请,使用的是 devm_request_threaded_irq 函数,而不是之前学习的 request_threaded_irq,此函数的作用是中断线程化。
硬件中断具有最高优先级,不论什么时候只要硬件中断发生,内核都会终止当前正在执行的操作,转而去执行中断处理程序(不考虑关闭中断和中断优先级的情况),如果中断非常频繁,那么内核将会频繁的执行中断处理程序,导致任务得不到及时的处理。中断线程化以后中断将作为内核线程运行,而且也可以被赋予不同的优先级,任务的优先级可能比中断线程的优先级高,这样做的目的就是保证高优先级的任务能被优先处理。
对于触摸屏而言,只要手指放到屏幕上,它可能就会一直产生中断(视具体芯片而定,FT5426 是这样的),中断处理程序里面需要通过 I2C 读取触摸信息并上报给内核,I2C 的速度最大只有 400KHz,算是低速外设。不断的产生中断、读取触摸信息、上报信息会导致处理器在触摸中断上花费大量的时间,但是触摸相对来说不是那么重要的事件,因此可以将触摸中断线程化。
使用“devm_”前缀的函数申请到的资源可以由系统自动释放,不需要手动处理。例:之前的驱动里面申请了很多资源,比如:gpio、irq、input_dev,那么就需要添加很多 goto 语句对其做处理,当这样的标签多了以后代码看起来就不整洁了。使用 devm_request_threaded_irq 函数来申请中断,那么就不需要再调用 free_irq 函数对其进行释放。
中断处理函数中上报信息示例:

1 static irqreturn_t xxx_handler(int irq, void *dev_id)
2 {
3 
4 		int num; /* 触摸点数量 */
5 		int x[n], y[n]; /* 保存坐标值 */
6 
7		/* 1、从触摸芯片获取各个触摸点坐标值 */
8 ......
9
10 		/* 2、上报每一个触摸点坐标 */
11 		for (i = 0; i < num; i  ) {
12 			input_mt_slot(input, id);
13 			input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
14 			input_report_abs(input, ABS_MT_POSITION_X, x[i]);
15 			input_report_abs(input, ABS_MT_POSITION_Y, y[i]);
16 		}
17 ......
18
19 		input_sync(input);
20 ......
21
22 		return IRQ_HANDLED;
23 }
学新通

三、驱动开发

原理图:
学新通
I2C2_SCL 和 I2C2_SDA 对应的引脚为 PH4 和 PH5。CT_INT 对应的引脚为 PI1,CT_RST 对应的引脚为 PH15。
对于中断触发模式,当 FT5426 检测到有触摸事件发生时,会将中断信号拉低,所以对主机控制器来说,是一个下降沿中断触发方式;当一直按着触摸屏不松开,则会一直触发中断,现在大部分的触摸 IC 都是这样设计的。

1.添加 FT5426 设备节点

在 stm32mp15-pinctrl.dtsi 中,添加引脚配置信息:

ft5426int_reset_pins_a: ft5426int_reset_pins-0 {
	pins1 {
		pinmux = <STM32_PINMUX('I', 1, GPIO)>, /* ft5426 INT */
				 <STM32_PINMUX('H', 15, GPIO)>; /* ft5426 RESET */
		bias-pull-up;
		slew-rate = <0>;
	};
};

2.FT5426 节点配置

FT5426这个触控 IC 挂载在I2C2 总线接口上,因此需要向 I2C2 节点下添加一个子节点(省略了之前的hdmi节点):

&i2c2 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2c2_pins_a>;
	pinctrl-1 = <&i2c2_pins_sleep_a>;
	status = "okay";
	
	ft5426: ft5426@38 {
		compatible = "edt,edt-ft5426";
		pinctrl-0 = <&ft5426int_reset_pins_a>;
		reg = <0x38>;
		irq-gpios = <&gpioi 1 GPIO_ACTIVE_LOW>;
		reset-gpios = <&gpioh 15 GPIO_ACTIVE_LOW>;
		status = "okay";
	};
};

FT5426 的器件地址为0X38,irq-gpios 属性描述中断 IO 对应的 GPIO 为 PI1,reset-gpios 属性描述复位 IO 对应的 GPIO 为 PH15。

3.驱动编写

ft5x06.c:

#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/interrupt.h>

/* FT5426寄存器相关宏定义 */
#define FT5426_DEVIDE_MODE_REG	    0x00	// 模式寄存器
#define FT5426_TD_STATUS_REG    	0x02  	// 状态寄存器
#define FT5426_TOUCH_DATA_REG   	0x03   	// 触摸数据读取的起始寄存器
#define FT5426_ID_G_MODE_REG    	0xA4  	// 中断模式寄存器

#define MAX_SUPPORT_POINTS		5    	// ft5426最大支持5点触摸

#define TOUCH_EVENT_DOWN      	0x00    // 按下
#define TOUCH_EVENT_UP          0x01    // 抬起
#define TOUCH_EVENT_ON         	0x02    // 接触
#define TOUCH_EVENT_RESERVED  	0x03    // 保留

struct edt_ft5426_dev {
    struct i2c_client *client;
    struct input_dev *input;
    int reset_gpio;
    int irq_gpio;
};

static int edt_ft5426_ts_write(struct edt_ft5426_dev *ft5426, u8 addr, u8 *buf, u16 len)
{
    struct i2c_client *client = ft5426->client;
    struct i2c_msg msg;
    u8 send_buf[6] = {0};
    int ret;

    send_buf[0] = addr;
    memcpy(&send_buf[1], buf, len);

    msg.flags = 0;                  //i2c写
    msg.addr = client->addr;
    msg.buf = send_buf;
    msg.len = len   1;

    ret = i2c_transfer(client->adapter, &msg, 1);
    if (1 == ret)
        return 0;
    else {
        dev_err(&client->dev, "%s: write error, addr=0x%x len=%d.\n", __func__, addr, len);
        return -1;
    }
}

static int edt_ft5426_ts_read(struct edt_ft5426_dev *ft5426, u8 addr, u8 *buf, u16 len)
{
    struct i2c_client *client = ft5426->client;
    struct i2c_msg msg[2];
    int ret;

    msg[0].flags = 0;             	// i2c写
    msg[0].addr = client->addr;
    msg[0].buf = &addr;
    msg[0].len = 1;              	// 1个字节

    msg[1].flags = I2C_M_RD;    	//i2c读
    msg[1].addr = client->addr;
    msg[1].buf = buf;
    msg[1].len = len;

    ret = i2c_transfer(client->adapter, msg, 2);
    if (2 == ret)
        return 0;
    else {
        dev_err(&client->dev, "%s: read error, addr=0x%x len=%d.\n", __func__, addr, len);
        return -1;
    }
}

static int edt_ft5426_ts_reset(struct edt_ft5426_dev *ft5426)
{
    struct i2c_client *client = ft5426->client;
    int ret;

    /* 从设备树中获取复位管脚 */
    ft5426->reset_gpio = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0);
    if (!gpio_is_valid(ft5426->reset_gpio)) {
        dev_err(&client->dev, "Failed to get ts reset gpio\n");
        return ft5426->reset_gpio;
    }

    /* 申请使用管脚 */
    ret = devm_gpio_request_one(&client->dev, ft5426->reset_gpio, GPIOF_OUT_INIT_HIGH, "ft5426 reset");
    if (ret < 0)
        return ret;

    msleep(20);
    gpio_set_value_cansleep(ft5426->reset_gpio, 0);    	// 拉低复位引脚
    msleep(5);
    gpio_set_value_cansleep(ft5426->reset_gpio, 1);   	// 拉高复位引脚,结束复位

    return 0;
}

static irqreturn_t edt_ft5426_ts_isr(int irq, void *dev_id)
{
    struct edt_ft5426_dev *ft5426 = dev_id;
    u8 rdbuf[30] = {0};
    int i, type, x, y, id;
    bool down;
    int ret;

    /* 读取FT5426触摸点坐标从0x02寄存器开始,连续读取29个寄存器 */
    ret = edt_ft5426_ts_read(ft5426, FT5426_TD_STATUS_REG, rdbuf, 29);
    if (ret)
        goto out;

    for (i = 0; i < MAX_SUPPORT_POINTS; i  ) {

        u8 *buf = &rdbuf[i * 6   1];

        /* 以第一个触摸点为例,寄存器TOUCH1_XH(地址0x03),各bit位描述如下:
         * bit7:6  Event flag  0:按下 1:释放 2:接触 3:没有事件
         * bit5:4  保留
         * bit3:0  X轴触摸点的11~8位
         */
        type = buf[0] >> 6;                     // 获取触摸点的Event Flag
        if (type == TOUCH_EVENT_RESERVED)
            continue;

        /* 我们所使用的触摸屏和FT5426是反过来的 */
        x = ((buf[2] << 8) | buf[3]) & 0x0fff;
        y = ((buf[0] << 8) | buf[1]) & 0x0fff;

        /* 以第一个触摸点为例,寄存器TOUCH1_YH(地址0x05),各bit位描述如下:
         * bit7:4  Touch ID  触摸ID,表示是哪个触摸点
         * bit3:0  Y轴触摸点的11~8位。
         */
        id = (buf[2] >> 4) & 0x0f;
        down = type != TOUCH_EVENT_UP;

        input_mt_slot(ft5426->input, id);
        input_mt_report_slot_state(ft5426->input, MT_TOOL_FINGER, down);

        if (!down)
            continue;

        input_report_abs(ft5426->input, ABS_MT_POSITION_X, x);
        input_report_abs(ft5426->input, ABS_MT_POSITION_Y, y);
    }

    input_mt_report_pointer_emulation(ft5426->input, true);
    input_sync(ft5426->input);

out:
    return IRQ_HANDLED;
}

static int edt_ft5426_ts_irq(struct edt_ft5426_dev *ft5426)
{
    struct i2c_client *client = ft5426->client;
    int ret;

    /* 从设备树中获取中断管脚 */
    ft5426->irq_gpio = of_get_named_gpio(client->dev.of_node, "irq-gpios", 0);
    if (!gpio_is_valid(ft5426->irq_gpio)) {
        dev_err(&client->dev, "Failed to get ts interrupt gpio\n");
        return ft5426->irq_gpio;
    }

    /* 申请使用管脚 */
    ret = devm_gpio_request_one(&client->dev, ft5426->irq_gpio, GPIOF_IN, "ft5426 interrupt");
    if (ret < 0)
        return ret;

    /* 注册中断服务函数 */
    ret = devm_request_threaded_irq(&client->dev, gpio_to_irq(ft5426->irq_gpio),
                NULL, edt_ft5426_ts_isr, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                client->name, ft5426);
    if (ret) {
        dev_err(&client->dev, "Failed to request touchscreen IRQ.\n");
        return ret;
    }

    return 0;
}

static int edt_ft5426_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    struct edt_ft5426_dev *ft5426;
    struct input_dev *input;
    u8 data;
    int ret;

    /* 实例化一个struct edt_ft5426_dev对象 */
    ft5426 = devm_kzalloc(&client->dev, sizeof(struct edt_ft5426_dev), GFP_KERNEL);
    if (!ft5426) {
        dev_err(&client->dev, "Failed to allocate ft5426 driver data.\n");
        return -ENOMEM;
    }

    ft5426->client = client;

    /* 复位FT5426触摸芯片 */
    ret = edt_ft5426_ts_reset(ft5426);
    if (ret)
        return ret;

    msleep(5);

    /* 初始化FT5426 */
    data = 0;
    edt_ft5426_ts_write(ft5426, FT5426_DEVIDE_MODE_REG, &data, 1);
    data = 1;
    edt_ft5426_ts_write(ft5426, FT5426_ID_G_MODE_REG, &data, 1);

    /* 申请、注册中断服务函数 */
    ret = edt_ft5426_ts_irq(ft5426);
    if (ret)
        return ret;

    /* 注册input设备 */
    input = devm_input_allocate_device(&client->dev);
    if (!input) {
        dev_err(&client->dev, "Failed to allocate input device.\n");
        return -ENOMEM;
    }

    ft5426->input = input;
    input->name = "FocalTech FT5426 TouchScreen";
    input->id.bustype = BUS_I2C;

    input_set_abs_params(input, ABS_MT_POSITION_X, 0, 1024, 0, 0);
    input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 600, 0, 0);

    ret = input_mt_init_slots(input, MAX_SUPPORT_POINTS, INPUT_MT_DIRECT);
    if (ret) {
        dev_err(&client->dev, "Failed to init MT slots.\n");
        return ret;
    }

    ret = input_register_device(input);
    if (ret)
        return ret;

    i2c_set_clientdata(client, ft5426);
    return 0;
}

static int edt_ft5426_ts_remove(struct i2c_client *client)
{
    struct edt_ft5426_dev *ft5426 = i2c_get_clientdata(client);
    input_unregister_device(ft5426->input);
    return 0;
}

static const struct of_device_id edt_ft5426_of_match[] = {
    { .compatible = "edt,edt-ft5426", },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, edt_ft5426_of_match);

static struct i2c_driver edt_ft5426_ts_driver = {
    .driver = {
        .owner     		= THIS_MODULE,
        .name          	= "edt_ft5426",
        .of_match_table	= of_match_ptr(edt_ft5426_of_match),
    },
    .probe    = edt_ft5426_ts_probe,
    .remove   = edt_ft5426_ts_remove,
};

module_i2c_driver(edt_ft5426_ts_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("amonter");
MODULE_INFO(intree, "Y");
学新通

①自定义结构体 edt_ft5426_dev,用于描述 FT5426 设备,其中包括 I2C 从机设备指针 client、input 输入设备指针 input、一个复位引脚 reset_gpio 以及一个中断引脚 irq_gpio。
②自定义函数 edt_ft5426_ts_write,用于向 FT5426 内部寄存器连续写入数据,可指定写入数据字节长度。
③自定义函数 edt_ft5426_ts_read,用于连续读取 FT5426 内部寄存器中的数据,可指定读取数据字节长度。
④自定义函数 edt_ft5426_ts_reset,用于复位 FT5426 触摸芯片,FT5426 的复位 IO 为低电平有效。FT5426 的复位过程没有什么特殊要求,直接将复位 IO 拉低,延时 5ms 然后再将其拉高即可。复位结束之后先延时一段时间再进行读写寄存器操作。
⑤edt_ft5426_ts_isr 函数,触摸屏中断服务函数,触摸点坐标的上报就是在此函数中完成的。从 0x02 这个地址开始,一共 29 个寄存器,是存储的所有触摸点信息。使用for循环一个一个上报,使用 Type B 时序,最后通过 input_sync 函数上报 SYN_REPORT 事件。
⑥自定义函数 edt_ft5426_ts_irq,用于初始化 FT5426 中断 IO,使用函数 devm_request_threaded_irq 申请并注册中断,为下降沿触发。
⑦I2C 总线的 probe 函数 edt_ft5426_ts_probe,当 I2C 从机设备与驱动匹配成功之后就会执行这个函数,一般在此函数中完成一些初始化工作。
⑧input_mt_init_slots 函数是用来初始化 slots,第二个参数表示触摸屏设置支持的最大触摸点数量,FT5426 是个 5 点电容触摸芯片,因此一共 5 个 slot;最后一个参数是一个标志位,表示设备类型,INPUT_MT_DIRECT 表示为触摸屏设备类型。
⑨edt_ft5426_ts_remove 函数用来卸载驱动模块,因为前面很多资源都是用“ devm_”前缀函数来申请的,因此不需要手动释放。此函数只需要调用 input_unregister_device 来释放掉前面添加到内核中的 input_dev。

4.运行测试

将驱动文件编译,放入nfs指定目录然后启动开发板。加载驱动模块后就会生成/dev/input/eventX(X=1,2,3…)。
学新通
数据解析:
使用hexdump /dev/input/event1命令,然后手动操作电容屏,终端就可以接受到数据。上报的信息是按照 input_event 类型呈现的。
学新通
学新通

5.将驱动添加到内核中

将驱动添加到内核,系统启动时就会自动挂载,不需要再手动挂载了。

1)将驱动文件放到合适的位置

ft5x06.c 是个触摸屏驱动,linux 内核里将触摸屏驱动放到了 drivers/input/touchscreen 目录下,因此将 ft5x06.c 也拷贝到此目录下。

2)修改Makefile

修改 drivers/input/touchscreen 目录下的 Makefile,在最下面添加一行:

obj-y  = ft5x06.o

这样就将驱动文件添加进了内核编译。修改完成以后重新编译 linux 内核,然后用新的 uImage 启动开发板。如果驱动添加成功,系统启动的时候就会输出下图信息:
学新通

6.tslib 移植与使用

  tslib 是一个开源的第三方库,用于触摸屏性能调试,使用电阻屏的时候一般使用 tslib 进行校准。虽然电容屏不需要校准,但是由于电容屏加工的原因,有的时候其不一定精准,因此有时候也需要进行校准。
  在 buildroot 的 menuconfig 中使能 tslib 库:
学新通
然后使用sudo make编译出文件系统,并解压到 nfs 的对应目录即可。
测试
校准命令:ts_calibrate,如果对校准结果不满意,直接删除掉 /etc/pointercal 文件。
使用ts_test_mt命令测试触摸屏工作是否正常,以及多点触摸是否有效。此时会打开一个测试界面,有三个按钮“Drag”、“Draw”和“Quit”,这三个按钮的功能如下:
Drag:拖拽按钮,默认就是此功能,可以看到屏幕中间有一个十字光标,可以通过触摸屏幕来拖拽此光标。一个触摸点一个十字光标,对于 5 点电容触摸屏,如果 5 个手指都放到屏幕上,那么就有 5 个光标,一个手指一个。
Draw:绘制按钮,按下此按钮就可以在屏幕上进行简单的绘制,可以通过此功能检测多点触摸工作是否正常。
Quit:退出按钮,退出 ts_test_mt 测试软件。
点击“Draw”按钮,使用绘制功能,5 个手指一起划过屏幕,如果多点电容屏工作正常的话就会在屏幕上留下 5 条线。

四、使用内核自带的驱动

内核自带的 FT5426 的驱动文件为 drivers/input/touchscreen/edt-ft5x06.c,此驱动文件不仅能够驱动 FT5426,FT5206、FT5406 这些都可以驱动。
先将之前添加进内核编译的自己的驱动去除,将Makefile中添加的命令去掉即可。

1.使能内核自带的 FT5X06 驱动

在 Linux 内核的 menuconfig 进行使能:
学新通

2.修改设备树

修改之前编写的 ft5426 设备节点,添加 compatible 属性。edt-ft5x06.c 所支持的 compatible 属性列表如下:
学新通
将 compatible 属性修改为某一个兼容值即可。

ft5426: ft5426@38 {
		compatible = "edt,edt-ft5406";
		pinctrl-0 = <&ft5426int_reset_pins_a>;
		reg = <0x38>;
		irq-gpios = <&gpioi 1 GPIO_ACTIVE_LOW>;
		reset-gpios = <&gpioh 15 GPIO_ACTIVE_LOW>;
		status = "okay";
};

修改完成后重新编译出 uImage 和设备树,然后启动开发板即可。

五、4.3寸屏驱动

  4.3寸屏幕的驱动 IC 都是 GT9147,因此本质上就是编写 GT9147 驱动。

1.修改设备树

在 i2c2 节点下添加一个子节点:

gt9147: gt9147@14 {
	compatible = "atk-gt9147";
	reg = <0x14>;
	interrupt-parent = <&gpioi>;
	interrupts = <1 IRQ_TYPE_EDGE_RISING>;
	interrupt-gpios = <&gpioi 1 GPIO_ACTIVE_LOW>;
	reset-gpios = <&gpioh 15 GPIO_ACTIVE_LOW>;
	status = "okay";
};

在 ST 官方的内核配置中,已经把 gt9147 这个驱动编译进内核了,所以这里的 compatible 的属性值为“atk-gt9147”,免得使用内核的 gt9147 驱动代码。

2.添加屏幕参数

在 drivers/gpu/drm/panel/panel-simple.c 文件下,添加对应屏幕的参数,4.3 寸 800480 和 480272 这两款屏幕参数如下:

static const struct drm_display_mode ATK4384_mode = {
	.clock = 33300,
	.hdisplay = 800,
	.hsync_start = 800   88,
	.hsync_end = 800   88   48,
	.htotal = 800   88   48   40,
	.vdisplay = 480,
	.vsync_start = 480   32,
	.vsync_end = 480   32   3,
	.vtotal = 480   32   3   13,
	.vrefresh = 60,
};
static const struct drm_display_mode ATK4342_mode = {
	.clock = 9000,
	.hdisplay = 480,
	.hsync_start = 480   40,
	.hsync_end = 480   40   1,
	.htotal = 480   40   1   5,
	.vdisplay = 272,
	.vsync_start = 272   8,
	.vsync_end = 272   8   1,
	.vtotal = 272   8   1   8,
	.vrefresh = 60,
};
static const struct panel_desc alientek_desc = {
	.modes = &ATK7016_mode,
	.num_modes = 1,
	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
};
学新通

前两个为 800480 和 480272 两个屏的参数,第三个中,modes 属性为“ATK7016_mode”,如果屏为 480*272 就把 modes 属性修改为 ATK4342_mode。
将原子的驱动文件拷贝进来然后编译,编译完成后手动挂载即可。如果在使用 tslib 的时候提示找不到设备,使用export TSLIB_TSDEVICE=/dev/input/event1命令手动声明设备即可。

注:如果想直接使用 Linux 自带的 gt9147 驱动,直接修改设备树的 compatible 属性值为“goodix,gt9147”即可。另外,原子哥的驱动中,因为 GT9147 没有硬件检测每个触摸点的按下和抬起,因此只能单点触摸。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfheehh
系列文章
更多 icon
同类精品
更多 icon
继续加载