历史上的今天
返回首页

历史上的今天

今天是:2024年12月29日(星期日)

2020年12月29日 | I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之触摸屏驱动移植

2020-12-29 来源:eefocus

之所以说是驱动移植是因为之前已经在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);

推荐阅读

史海拾趣

GS Technology公司的发展小趣事
在工业自动化和监测系统中,用于显示各种物理量的峰值。
Electromagnetic Industries Llp公司的发展小趣事

在技术创新的同时,EMI公司也注重市场拓展。公司根据市场需求和产品特点,制定了有针对性的营销策略。一方面,公司积极参加国内外各种电子展会和论坛,展示产品和技术实力;另一方面,公司加强与客户的沟通和合作,深入了解客户需求,提供个性化的解决方案。通过这些努力,EMI公司的市场份额不断扩大,品牌影响力也逐渐提升。

汇科公司的发展小趣事

随着技术的不断成熟和市场的不断拓展,苏州汇科技术股份有限公司开始在全国范围内进行产业布局。公司通过设立办事处、加强与客户的沟通合作等方式,进一步扩大了市场份额。同时,公司还积极寻求与国际知名企业的合作,共同开发新产品、新技术和新市场,为公司的未来发展奠定了坚实基础。

德旭电子(DEXU)公司的发展小趣事

在电子行业的浪潮中,德旭电子(DEXU)于XXXX年悄然成立。当时,创始人李先生凭借对电子技术的深刻理解和市场的前瞻性判断,决定涉足这一领域。初创时期的德旭电子面临着资金短缺、技术薄弱、市场竞争激烈等多重挑战。然而,李先生带领的团队凭借坚定的信念和不懈的努力,成功研发出首款具有竞争力的电子产品,并在市场上获得了一定的认可。

为了提升产品质量和技术水平,德旭电子不断加大研发投入,积极引进先进技术和设备。同时,公司还注重人才培养和团队建设,吸引了一批具有丰富经验和专业技能的人才加入。这些努力为德旭电子的后续发展奠定了坚实的基础。

格莱尔(GLE)公司的发展小趣事

格莱尔始终将技术创新视为企业发展的核心动力。公司不断投入研发资源,引进先进的生产设备和高精度的检测仪器,确保产品质量的稳步提升。同时,格莱尔还通过了ISQ9001质量管理体系和IATF16949汽车质量管理体系认证,全部产品实现了符合RoHS标准的无铅化生产,达到了欧盟的环保要求。这些努力使得格莱尔的产品在市场上赢得了良好的口碑和广泛的认可。

Alpha (Taiwan)公司的发展小趣事

Alpha (Taiwan)公司自创立之初,便致力于电子技术的研发与创新。面对日益激烈的市场竞争,公司不断投入资金,引进先进设备,吸引了一批优秀的研发人才。这些人才凭借深厚的专业知识和敏锐的市场洞察力,成功开发出一系列具有竞争力的电子产品,如高性能的芯片、精密的传感器等。这些产品的推出,不仅提升了公司的市场地位,也为公司的快速发展奠定了坚实基础。

问答坊 | AI 解惑

推荐ATMEL9260+Zigbee开发套件完美版

产品名称:ATMEL9260ARM + JN5139Zigbee    售价:1188元 产品规格:14*9.2cm      10*6cm 产品型号:CA-9260-ZB-EK                     &nb ...…

查看全部问答>

有谁用过红色飓风二代FPGA开发板的么?求助~

我手里的CY1C12开发板上的芯片是FPGA的EP1C12Q240C8,今天我用一个小程序,试图点亮那四个七段数码管。用的动态显示。然而,当我配置管脚,下载到板上后,数码管能够顺序点亮,但是不是之前程序里面设计的数字,有些乱码的感觉。 我怀疑是管脚配置 ...…

查看全部问答>

XILINX FPGA 设计的点滴

XILINX FPGA 设计的点滴 1、为时钟信号选用全局时钟缓冲器BUFG 2、尽量只用一个时钟沿来寄存数据 3、除了用CLKDLL或DCM产生的时钟外不要在内部产生时钟 4、注意状态机编码的可靠性:状态机转移状态改变的位数越少,则功能越可靠。 5、逻辑 ...…

查看全部问答>

windows CE6.0 USB 键盘鼠标

大家好,我在订制系统的时候,想添加USB键盘鼠标的支持,请问一下 需要添加那些组建,Reg文件 和 BIB文件需要添加那些东西 ?…

查看全部问答>

急! 使用wininet API 实现Http下载

刚刚接触Wince 6.0 现在要实现一个使用url链接下载的功能 ,参考了网上一些程序编写如下代码 void CHttpGet::Download(CString url) {         try         { CStdioFile* pSFile=NULL; CInternetSession ...…

查看全部问答>

EVC4的使用问题

请问大虾们EVC4-TOOL-WINDOWS CE PLATFORM MANAGER CONFIGURATION选项有什么用处? 如何在该选项里添加一个项目(前面带+号的那个东西)? 我是新人,百度上搜了很久没有答案,请大家帮帮忙,谢谢了。…

查看全部问答>

keil3 编译问题

我将ADS1.2下一个工程移植到Keil3 IDE下时,在解决了一些编译错误问题后,也参考了一些说明,编译完成后没有错误,当然有一堆的警告,什么字符串无效,最后一行没空等,但是连接没有生成默认该生成的.axf文件,导致调试也找不到.axf文件,当然也生 ...…

查看全部问答>

evc中怎样编辑多国语言

evc中怎样编辑多国语言 比如说我要SetWindowText(_T(\"? ?? ??\")); 但在Evc中成了SetWindowText(_T(\"? ?? ??\")); …

查看全部问答>

io口扩展问题

我想做个控制板上16个继电器,再留出一个可控制的扩展板接口也是控制16个继电器的。 我目前想用16f877单片机进行控制,不知道io扩展芯片用什么好 有什么好的设计方案,请帮忙,谢谢!…

查看全部问答>

EE_FPGA V1.0 调试进展(2010.10.17更新)

正面:   反面: 目前进展: 1. 最小系统工作 2. LED工作 3. key工作 4. usb转串口驱动正常,串口工作正常   稍后上图,敬请关注     10.17更新 [ 本帖最后由 chenzhufly 于 2010-10-17 14:20 编辑 ]…

查看全部问答>