I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之触摸屏驱动移植

发布者:hxcp18最新更新时间:2020-12-29 来源: eefocus关键字:I  TQE9  BSP  触摸屏驱动  移植 手机看文章 扫描二维码
随时随地手机看文章

之所以说是驱动移植是因为之前已经在TQ210、AM335x两个平台上移植过了,因此,仅需要少量修改就可以将驱动移植到imx6q。下面开始触摸驱动移植。


DTS编写


参考其它DTS的i2c设备写法,我们可以添加如下内容:


&i2c1 {

clock-frequency = <100000>;

pinctrl-names = "default";

pinctrl-0 = <&pinctrl_i2c1_2>;

status = "okay";

 

gt811@5d {

compatible = "gt811,gt811_ts";  

    pinctrl-names = "default";  

reg = <0x5d>;  

interrupt-parent = <&gpio1>;  

interrupts = <9 2>;  

gpios = <&gpio1 5 0>;  

  

touchscreen-size-x = <800>;  

touchscreen-size-y = <480>;  

 

touchscreen-swap = <1>;  

touchscreen-revert-x = <1>;  

touchscreen-revert-y = <1>; 

};

};

添加以上内容后重新编译并烧写DTB。


驱动编写

其实移植AM335x的时候就是以DTB方式移植的,因此,除内核api变更的部分需要修改一下,其它代码基本是不需要修改的。驱动代码如下(不含event上报代码):


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

struct gt811_ts_platdata

{

u32 size_x;

u32 size_y;

u32 size_p;

u32 swap;

u32 revert_x;

u32 revert_y;

u32 reset_pin;

u32 interrupt_pin;

u32 ponits_max;

struct i2c_client *client;

struct input_dev *input;

struct work_struct work;

};

 

static const struct of_device_id gt811_ts_of_match[] = {

{ .compatible = "gt811,gt811_ts", .data = NULL },

{ }

};

 

static int i2c_write_bytes(struct i2c_client *client, uint8_t *data, int len){

struct i2c_msg msg;

 

msg.flags=!I2C_M_RD;

msg.addr=client->addr;

msg.len=len;

msg.buf=data;

 

return i2c_transfer(client->adapter,&msg, 1);

}

 

static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len){

struct i2c_msg msgs[2];

 

msgs[0].flags=!I2C_M_RD;

msgs[0].addr=client->addr;

msgs[0].len=2;

msgs[0].buf=&buf[0];

 

msgs[1].flags=I2C_M_RD;

msgs[1].addr=client->addr;

msgs[1].len=len-2;

msgs[1].buf=&buf[2];

 

return i2c_transfer(client->adapter,msgs, 2);

}

static void gt811_ts_handler(struct work_struct *work)

{

struct gt811_ts_platdata *pdata = container_of(work, struct gt811_ts_platdata, work);

struct device *dev = &pdata->client->dev;

uint8_t buffer[36] = {0x07, 0x21, 0};

struct input_mt_pos pos[5];

int slots[5], slot;

uint8_t count, index, flags, position;

 

buffer[0] = 0x0f;

buffer[1] = 0xff;

if (i2c_write_bytes(pdata->client,buffer,2) < 0) {

dev_err(dev, "Failed to write wakeup message.n");

goto reenable_irq;

}

 

buffer[0] = 0x07;

buffer[1] = 0x21;

if (i2c_read_bytes(pdata->client, buffer, sizeof(buffer)) < 0) {

dev_err(dev, "Failed to read touch message.n");

goto reenable_irq;

}

 

buffer[0] = 0x80;

buffer[1] = 0x00;

if (i2c_write_bytes(pdata->client, buffer, 2) < 0) {

dev_err(dev, "Failed to write sleep message.n");

goto reenable_irq;

}

 

buffer[25] = buffer[19];

buffer[19] = 0;

 

flags = buffer[2]&0x1f;

 

count = 0;

for (index = 0; index < 5 && flags; ++index, flags >>= 1) {

if (!(flags&0x1)) {

continue;

}

 

if (index < 3) {

position = 4 + index * 5;

}

else{

position = 25 + (index - 3) * 5;

}

 

pos[count].x = (buffer[position] << 8) | buffer[position + 1];

pos[count].y = (buffer[position + 2] << 8) | buffer[position + 3];

slots[count] = index;

 

if(pdata->swap) {

swap(pos[count].x, pos[count].y);

}

if(pdata->revert_x){

pos[count].x = pdata->size_x - pos[count].x;

}

if(pdata->revert_y){

pos[count].y = pdata->size_y - pos[count].y;

}

 

++count;

}

 

// 在这个位置添加event上报代码

...

 

reenable_irq:

enable_irq(pdata->client->irq);

}

 

static irqreturn_t gt811_ts_isr(int irq, void *dev_id)

{

struct gt811_ts_platdata* pdata = (struct gt811_ts_platdata*)dev_id;

 

disable_irq_nosync(pdata->client->irq);

schedule_work(&pdata->work);

 

return IRQ_HANDLED;

}

 

static int gt811_ts_initilize(struct i2c_client *client)

{

struct device *dev = &client->dev;

struct gt811_ts_platdata *pdata = (struct gt811_ts_platdata*)i2c_get_clientdata(client);

int status = 0, count = 0;

uint8_t version[4] = {0x7, 0x17, 0};

uint8_t config[] = {

0x06,0xA2,

0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,

0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,

0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,

0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,

0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,

0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,

0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01

};

 

config[62] = 480 >> 8;

config[61] = 480 & 0xff;

config[64] = 800 >> 8;

config[63] = 800 & 0xff;

 

if (!gpio_is_valid(pdata->reset_pin)) {

dev_err(dev, "The reset pin number is invalid.n");

return -EINVAL;

}

 

count = 3;

while (count--) {

gpio_direction_output(pdata->reset_pin, 0);

msleep(10);

gpio_direction_output(pdata->reset_pin, 1);

msleep(100);

 

if (i2c_read_bytes(client, version, sizeof(version)) < 0) {

dev_err(dev, "Failed to get the version of GT811, try again...n");

status = -ENODEV;

}

else {

dev_info(dev, "Gt811 detected, version(%04x)...n", (version[2]<<8)|version[3]);

status = 0;

break;

}

}

 

if (status) {

return status;

}

 

count = 3;

while (count--) {

if (i2c_write_bytes(client, config, sizeof(config)) < 0) {

dev_err(dev, "Failed to configure the GT811, try again...n");

status = -EINVAL;

}

else {

dev_info(dev, "Gt811 configue succeedn");

status = 0;

break;

}

}

 

return status;

}

 

static struct gt811_ts_platdata *gt811_ts_parse_devtree(struct i2c_client *client)

{

struct device *dev = &client->dev;

struct device_node *node;

struct gt811_ts_platdata *pdata;

enum of_gpio_flags flags;

 

node = dev->of_node;

if (!node) {

dev_err(dev, "The of_node is NULL.n");

return ERR_PTR(-ENODEV);

}

 

pdata = devm_kzalloc(dev, sizeof(struct device_node), GFP_KERNEL);

if (!pdata) {

dev_err(dev, "No enough memory left.n");

return ERR_PTR(-ENOMEM);

}

 

pdata->reset_pin = of_get_gpio_flags(node, 0, &flags);

if (pdata->reset_pin < 0) {

dev_err(dev, "Get RST pin failed!n");

return ERR_PTR(-EINVAL);

}

 

if (of_property_read_u32(node, "touchscreen-size-x", &pdata->size_x )) {

dev_err(dev, "Failed to get the touch screen x size.n");

return ERR_PTR(-EINVAL);

}

 

if (of_property_read_u32(node, "touchscreen-size-y", &pdata->size_y)) {

dev_err(dev, "Failed to get the touch screen y size.n");

return ERR_PTR(-EINVAL);

}

 

if (of_property_read_u32(node, "touchscreen-size-p", &pdata->size_p)) {

pdata->size_p = 255;

}

 

if (of_property_read_u32(node, "touchscreen-swap", &pdata->swap)) {

pdata->swap = 1;

}

 

if (of_property_read_u32(node, "touchscreen-revert-x", &pdata->revert_x)) {

pdata->revert_x = 1;

}

 

if (of_property_read_u32(node, "touchscreen-revert-y", &pdata->revert_y)) {

pdata->revert_y = 1;

}

 

return pdata;

}

 

static int gt811_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)

{

struct device *dev = &client->dev;

struct gt811_ts_platdata *pdata = dev_get_platdata(dev);

struct input_dev *input;

int error = 0;

 

if (!of_match_device(of_match_ptr(gt811_ts_of_match), dev)) {

dev_err(dev, "Failed to match.n");

return -EINVAL;

}

 

if (!pdata) {

pdata = gt811_ts_parse_devtree(client);

if (IS_ERR(pdata)) {

dev_err(dev, "Get device data from device tree failed!n");

error = -EINVAL;

goto failed_exit;

}

}

 

pdata->client = client;

 

i2c_set_clientdata(client, pdata);

 

error = devm_gpio_request_one(&client->dev, pdata->reset_pin,

GPIOF_OUT_INIT_HIGH, "gt811_rst_pin");

if (error < 0) {

dev_err(dev, "Failed to request gt811 reset pinn");

return error;

}

 

input = devm_input_allocate_device(dev);

if (!input) {

dev_err(dev, "Failed to allocate input devicen");

error = -ENOMEM;

goto pdata_free;

}

 

pdata->input = input;

 

input->name = client->name;

input->id.bustype = BUS_I2C;

input->id.product = 0xBEEF;

input->id.vendor  =0xDEAD;

input->dev.parent = &client->dev;

 

__set_bit(EV_KEY, input->evbit);

__set_bit(EV_ABS, input->evbit);

__set_bit(BTN_TOUCH, input->keybit);

input_set_abs_params(input, ABS_X, 0, pdata->size_x, 0, 0);

input_set_abs_params(input, ABS_Y, 0, pdata->size_y, 0, 0);

input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->size_x, 0, 0);

input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->size_y, 0, 0);

 

error = input_mt_init_slots(input, 5, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);

if (error) {

dev_err(dev, "Failed to initialize the multi-touch slots.n");

goto input_free;

}

 

input_set_drvdata(input, pdata);

 

error = input_register_device(input);

if (error) {

dev_err(dev, "Register input device failed!n");

goto input_free;

}

 

if (gt811_ts_initilize(client)) {

dev_err(dev, "Failed to initialize GT811.n");

}

 

INIT_WORK(&pdata->work, gt811_ts_handler);

 

error = devm_request_irq(dev, client->irq, gt811_ts_isr,

  IRQF_TRIGGER_FALLING, client->name, pdata);

if (error) {

dev_err(dev, "Failed to request irq(number:%d)n", client->irq);

[1] [2]
关键字:I  TQE9  BSP  触摸屏驱动  移植 引用地址:I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之触摸屏驱动移植

上一篇:I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之声卡驱动移植
下一篇:I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之LCD移植

推荐阅读最新更新时间:2024-11-11 13:59

05-S3C2440学习之内核(移植)linux3.4.2移植(1) 简单移植+修改MTD分区+制作jffs2文件系统
一、框架介绍及简单修改 1.1 Bootloader如何引导内核 Bootloader的工作: (1)讲内核读入内存中 (2)存一些内核启动参数到指定位置,内核启动时去解析 (3)启动内核,传入机器ID 1.2、内核的启动流程: 首先 内核的最终目的是挂接根文件系统,并启动应用程序。 想启动应用程序—需要挂接根文件系统—装载驱动程序(flash、网卡)--要解析参数(文件系统在哪)--根据R1判断内核是否支持该ID—支持调用初始化相关函数 每个开发板都有不同的硬件参数 内核移植过程中要决定我这个内核支持哪些硬件开发板 我在内核里针对这个开发板给他一个ID。Uboot启动的时候传入和内核中设置好的匹配
[单片机]
05-S3C2440学习之内核(<font color='red'>移植</font>)linux3.4.2<font color='red'>移植</font>(1) 简单<font color='red'>移植</font>+修改MTD分区+制作jffs2文件系统
Tiny6410移植tslib
一、将Tiny6410一线触摸程序改成输入设备(input device) 由于友善一线触摸下位机不开源,所以只能在官方提供的内核模块上进行修改。 官方源代码:http://pan.baidu.com/s/1bog4rZD 1、修改模块加载函数 1 static int __init dev_init(void) 2 { 3 int ret; 4 #ifdef TS_INPUT_DRIVER 5 /* alloc input system device */ 6 ts.input = input_allocate_device(); 7 8 ts.input- evbit = BI
[单片机]
Tiny6410<font color='red'>移植</font>tslib
i9-9900KS风冷超频到5.2GHz 全核5.2GHz跑分比i9-9900K典型分提高7%
Intel 此前预告,Core i9-9900KS处理器将于本月发售。但直到现在,确切日期仍未公布。 不过,捷克网友FR33_L35T3R却提前拿到了一颗零售版的i9-9900KS,并成功在风冷下将其超频到了5.2GHz,电压1.36V。 据悉, 测试 平台是基于华硕 ROG Maximus XI Hero ( Wi-Fi )主板和一对博帝DDR4-2666内存。 在Cinebench R20中,全核5.2GHz的i9-9900KS跑出5356分,比i9-9900K的典型分4984提高了7%,比 5G Hz的i9-9900KS的5266分提升了1.7%。 Core i9-9900KS发布于今年台北电脑展期间,它其实就是
[手机便携]
曝<font color='red'>i</font>9-9900KS风冷超频到5.2GHz 全核5.2GHz跑分比<font color='red'>i</font>9-9900K典型分提高7%
6 通道逻辑 / SPI / I2C μModule 隔离器
加利福尼亚州米尔皮塔斯 (MILPITAS, CA) – 2016 年 12 月 12 日 – 凌力尔特公司 (Linear Technology Corporation) 推出 6 通道 SPI / 数字或 I2C μModule® 隔离器 LTM2887,该器件面向低电压组件,包括较新的 DSP 和微处理器。两个经过良好稳压的可调电源轨 (高达 5V) 越过隔离势垒提供大于 100mA 的负载电流,并具有高达 62% 的效率。对于辅助电源,电压可调节到低至 0.6V,而对于 SPI 接口,隔离型逻辑电源则可低至 1.8V。每个电源提供一个精准的电流限值调整引脚,并能使用外部电阻器来调节电压。 在工业系统应用中,接地电位
[模拟电子]
6 通道逻辑 / SPI / <font color='red'>I</font>2C μModule 隔离器
LPC824-I2C接口(续二)
继续来看I2C中断使能设置及读取寄存器INTENSET,下表是它的全部位结构,其地址分别为0x40050008 (I2C0),0x40054008 (I2C1),0x40070008 (I2C2)和0x40074008 (I2C3))。 (1)第0位(MSTPENDINGEN)为主机挂起中断使能位。写0时主机挂起中断禁止,写1时主机挂起中断使能,默认为禁止。 (2)第1到3位保留位,读出的值未定义,写入时只能写0。 (3)第4位(MSTARBLOSSEN)为主机仲裁丢失中断使能位。写0时主机仲裁丢失中断禁止,写1时主机主机仲裁丢失中断使能,默认为禁止。 (4)第5位为保留位,读出的值未定义,写入时只能写0。 (5)
[单片机]
LPC824-<font color='red'>I</font>2C接口(续二)
ARM 内核移植中常见的错误
1.下载linux-2.6.36.1.tar.bz2 问题:tar -zxvf 解压压缩文件出现问题,无法识别. 解决:1.通过file linux-2.6.36.1.tar.bz2 查看压缩格式 2.通过命令 bzip2 -d linux-2.6.36.1.tar.bz2解压 3.再通过tar xvf linux-2.6.36.1.tar解压,不能使用 tar zxvf linux-2.6.22.6.tar解压 4.上面也可以通过一条指令bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf - 其中XX为内核压缩包文件名 2.下载p
[单片机]
STM32模拟I2C时序读写EEPROM精简版
平台:STM32ZET6(核心板)+ST-LINK/V2+SD卡+USB串口线+外部EEPROM(不需要上拉电阻) 工程介绍:主要文件在USER组中,bsp_i2c_ee.c,bsp_i2c_ee.h,bsp_eeprom.c,bsp_eeprom.h和main.c,其中bsp_i2c_ee.c中主要时基本的模拟I2C时序,而bsp_eeprom.c中主要利用前一个文件中定义的基本操作,进行EEPROM的读写操作。其他类似I2C时序的协议,均可以保留bsp_i2c_ee.c的基础上添加新的内容。本文有些内容借鉴了其他网友的总结,在此表示感谢。 1.硬件部分:电路连接较为简单,笔者在淘宝上买的24C02N主要有四根线,两根电
[单片机]
STM32模拟<font color='red'>I</font>2C时序读写EEPROM精简版
单片机控制GSM模块(TC35I)电路设计
虽然单片机和TC35I模块都是TTL电平,但是TC35模块输入输出的TTL正电平逻辑不是+5V,而是+2.9V,但是单片机的输入输出的TTL正电平逻辑是+5V,所以如果直接将TC35I的RX,TX与单片机的TX,RX对应连接后,当然也要连接GND,是不会通信的,因为电平不统一。 解决方法; 1.给单片机的RX TX的IO口加上拉电阻,也就是分压,叫它那两个IO的电压等于2.9V左右,和GSM模块匹配。 2。给GSM模块上面的RX,TX加OC门驱动,提高电压。 3。单片机和GSM模块上面如果都有DB9(串口)和MAX232,那么可以直接将单片机的DB9和GSM模块的DB9上面的2-3.3-2.5-5这样连接。 O
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved