天嵌 ARM开发社区

 找回密码
 注册
查看: 4167|回复: 4

I.MX6Q学习笔记——新版BSP之触摸屏驱动移植

[复制链接]
freewing 发表于 2015-5-21 15:25:11 | 显示全部楼层 |阅读模式
  之所以说是驱动移植是因为之前已经在TQ210、AM335x两个平台上移植过了,因此,仅需要少量修改就可以将驱动移植到imx6q。下面开始触摸驱动移植。本文由技术博主girlkoo进行编写。

  DTS编写

  参考其它DTS的i2c设备写法,我们可以添加如下内容:
  1. &i2c1 {  
  2.     clock-frequency = <100000>;  
  3.     pinctrl-names = "default";  
  4.     pinctrl-0 = <&pinctrl_i2c1_2>;  
  5.     status = "okay";  
  6.   
  7.     gt811@5d {  
  8.         compatible = "gt811,gt811_ts";   
  9.         pinctrl-names = "default";   
  10.         reg = <0x5d>;   
  11.         interrupt-parent = <&gpio1>;   
  12.         interrupts = <9 2>;   
  13.         gpios = <&gpio1 5 0>;   
  14.             
  15.         touchscreen-size-x = <800>;   
  16.         touchscreen-size-y = <480>;   
  17.   
  18.         touchscreen-swap = <1>;   
  19.         touchscreen-revert-x = <1>;   
  20.         touchscreen-revert-y = <1>;   
  21.     };  
  22. };  
复制代码




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

  驱动编写

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




  1. #include <linux/module.h>  
  2. #include <linux/i2c.h>  
  3. #include <linux/platform_device.h>  
  4. #include <linux/gpio.h>  
  5. #include <linux/of.h>  
  6. #include <linux/of_platform.h>  
  7. #include <linux/of_gpio.h>  
  8. #include <linux/input.h>  
  9. #include <linux/input/mt.h>  
  10. #include <linux/interrupt.h>  
  11. #include <linux/delay.h>  
  12. #include <linux/io.h>  
  13.   
  14. struct gt811_ts_platdata  
  15. {  
  16.     u32 size_x;  
  17.     u32 size_y;  
  18.     u32 size_p;  
  19.     u32 swap;  
  20.     u32 revert_x;  
  21.     u32 revert_y;  
  22.     u32 reset_pin;  
  23.     u32 interrupt_pin;  
  24.     u32 ponits_max;  
  25.     struct i2c_client *client;  
  26.     struct input_dev *input;  
  27.     struct work_struct work;  
  28. };  
  29.   
  30. static const struct of_device_id gt811_ts_of_match[] = {  
  31.     { .compatible = "gt811,gt811_ts", .data = NULL },  
  32.     { }  
  33. };  
  34.   
  35. static int i2c_write_bytes(struct i2c_client *client, uint8_t *data, int len){  
  36.     struct i2c_msg msg;  
  37.   
  38.     msg.flags=!I2C_M_RD;  
  39.     msg.addr=client->addr;  
  40.     msg.len=len;  
  41.     msg.buf=data;  
  42.   
  43.     return i2c_transfer(client->adapter,&msg, 1);  
  44. }  
  45.   
  46. static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len){  
  47.     struct i2c_msg msgs[2];  
  48.   
  49.     msgs[0].flags=!I2C_M_RD;  
  50.     msgs[0].addr=client->addr;  
  51.     msgs[0].len=2;  
  52.     msgs[0].buf=&buf[0];  
  53.   
  54.     msgs[1].flags=I2C_M_RD;  
  55.     msgs[1].addr=client->addr;  
  56.     msgs[1].len=len-2;  
  57.     msgs[1].buf=&buf[2];  
  58.   
  59.     return i2c_transfer(client->adapter,msgs, 2);  
  60. }  
  61. static void gt811_ts_handler(struct work_struct *work)  
  62. {  
  63.     struct gt811_ts_platdata *pdata = container_of(work, struct gt811_ts_platdata, work);  
  64.     struct device *dev = &pdata->client->dev;  
  65.     uint8_t buffer[36] = {0x07, 0x21, 0};  
  66.     struct input_mt_pos pos[5];  
  67.     int slots[5], slot;  
  68.     uint8_t count, index, flags, position;  
  69.   
  70.     buffer[0] = 0x0f;  
  71.     buffer[1] = 0xff;  
  72.     if (i2c_write_bytes(pdata->client,buffer,2) < 0) {  
  73.         dev_err(dev, "Failed to write wakeup message.\n");  
  74.         goto reenable_irq;  
  75.     }  
  76.   
  77.     buffer[0] = 0x07;  
  78.     buffer[1] = 0x21;  
  79.     if (i2c_read_bytes(pdata->client, buffer, sizeof(buffer)) < 0) {  
  80.         dev_err(dev, "Failed to read touch message.\n");  
  81.         goto reenable_irq;  
  82.     }  
  83.   
  84.     buffer[0] = 0x80;  
  85.     buffer[1] = 0x00;  
  86.     if (i2c_write_bytes(pdata->client, buffer, 2) < 0) {  
  87.         dev_err(dev, "Failed to write sleep message.\n");  
  88.         goto reenable_irq;  
  89.     }  
  90.   
  91.     buffer[25] = buffer[19];  
  92.     buffer[19] = 0;  
  93.   
  94.     flags = buffer[2]&0x1f;  
  95.   
  96.     count = 0;  
  97.     for (index = 0; index < 5 && flags; ++index, flags >>= 1) {  
  98.         if (!(flags&0x1)) {  
  99.             continue;  
  100.         }  
  101.   
  102.         if (index < 3) {  
  103.             position = 4 + index * 5;  
  104.         }  
  105.         else{  
  106.             position = 25 + (index - 3) * 5;  
  107.         }  
  108.   
  109.         pos[count].x = (buffer[position] << 8) | buffer[position + 1];  
  110.         pos[count].y = (buffer[position + 2] << 8) | buffer[position + 3];  
  111.         slots[count] = index;  
  112.   
  113.         if(pdata->swap) {  
  114.             swap(pos[count].x, pos[count].y);  
  115.         }  
  116.         if(pdata->revert_x){  
  117.             pos[count].x = pdata->size_x - pos[count].x;  
  118.         }  
  119.         if(pdata->revert_y){  
  120.             pos[count].y = pdata->size_y - pos[count].y;  
  121.         }  
  122.   
  123.         ++count;  
  124.     }  
  125.   
  126.     // 在这个位置添加event上报代码  
  127.     ...  
  128.   
  129. reenable_irq:  
  130.     enable_irq(pdata->client->irq);  
  131. }  
  132.   
  133. static irqreturn_t gt811_ts_isr(int irq, void *dev_id)  
  134. {  
  135.     struct gt811_ts_platdata* pdata = (struct gt811_ts_platdata*)dev_id;  
  136.   
  137.     disable_irq_nosync(pdata->client->irq);  
  138.     schedule_work(&pdata->work);  
  139.   
  140.     return IRQ_HANDLED;  
  141. }  
  142.   
  143. static int gt811_ts_initilize(struct i2c_client *client)  
  144. {  
  145.     struct device *dev = &client->dev;  
  146.     struct gt811_ts_platdata *pdata = (struct gt811_ts_platdata*)i2c_get_clientdata(client);  
  147.     int status = 0, count = 0;  
  148.     uint8_t version[4] = {0x7, 0x17, 0};  
  149.     uint8_t config[] = {  
  150.         0x06,0xA2,  
  151.         0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,  
  152.         0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,  
  153.         0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,  
  154.         0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,  
  155.         0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,  
  156.         0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,  
  157.         0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01  
  158.     };  
  159.   
  160.     config[62] = 480 >> 8;  
  161.     config[61] = 480 & 0xff;  
  162.     config[64] = 800 >> 8;  
  163.     config[63] = 800 & 0xff;  
  164.   
  165.     if (!gpio_is_valid(pdata->reset_pin)) {  
  166.         dev_err(dev, "The reset pin number is invalid.\n");  
  167.         return -EINVAL;  
  168.     }  
  169.   
  170.     count = 3;  
  171.     while (count--) {  
  172.         gpio_direction_output(pdata->reset_pin, 0);  
  173.         msleep(10);  
  174.         gpio_direction_output(pdata->reset_pin, 1);  
  175.         msleep(100);  
  176.   
  177.         if (i2c_read_bytes(client, version, sizeof(version)) < 0) {  
  178.             dev_err(dev, "Failed to get the version of GT811, try again...\n");  
  179.             status = -ENODEV;  
  180.         }  
  181.         else {  
  182.             dev_info(dev, "Gt811 detected, version(%04x)...\n", (version[2]<<8)|version[3]);  
  183.             status = 0;  
  184.             break;  
  185.         }  
  186.     }  
  187.   
  188.     if (status) {  
  189.         return status;  
  190.     }  
  191.   
  192.     count = 3;  
  193.     while (count--) {  
  194.         if (i2c_write_bytes(client, config, sizeof(config)) < 0) {  
  195.             dev_err(dev, "Failed to configure the GT811, try again...\n");  
  196.             status = -EINVAL;  
  197.         }  
  198.         else {  
  199.             dev_info(dev, "Gt811 configue succeed\n");  
  200.             status = 0;  
  201.             break;  
  202.         }  
  203.     }  
  204.   
  205.     return status;  
  206. }  
  207.   
  208. static struct gt811_ts_platdata *gt811_ts_parse_devtree(struct i2c_client *client)  
  209. {  
  210.     struct device *dev = &client->dev;  
  211.     struct device_node *node;  
  212.     struct gt811_ts_platdata *pdata;  
  213.     enum of_gpio_flags flags;  
  214.   
  215.     node = dev->of_node;  
  216.     if (!node) {  
  217.         dev_err(dev, "The of_node is NULL.\n");  
  218.         return ERR_PTR(-ENODEV);  
  219.     }  
  220.   
  221.     pdata = devm_kzalloc(dev, sizeof(struct device_node), GFP_KERNEL);  
  222.     if (!pdata) {  
  223.         dev_err(dev, "No enough memory left.\n");  
  224.         return ERR_PTR(-ENOMEM);  
  225.     }  
  226.   
  227.     pdata->reset_pin = of_get_gpio_flags(node, 0, &flags);  
  228.     if (pdata->reset_pin < 0) {  
  229.         dev_err(dev, "Get RST pin failed!\n");  
  230.         return ERR_PTR(-EINVAL);  
  231.     }  
  232.   
  233.     if (of_property_read_u32(node, "touchscreen-size-x", &pdata->size_x )) {  
  234.         dev_err(dev, "Failed to get the touch screen x size.\n");  
  235.         return ERR_PTR(-EINVAL);  
  236.     }  
  237.   
  238.     if (of_property_read_u32(node, "touchscreen-size-y", &pdata->size_y)) {  
  239.         dev_err(dev, "Failed to get the touch screen y size.\n");  
  240.         return ERR_PTR(-EINVAL);  
  241.     }  
  242.   
  243.     if (of_property_read_u32(node, "touchscreen-size-p", &pdata->size_p)) {  
  244.         pdata->size_p = 255;  
  245.     }  
  246.   
  247.     if (of_property_read_u32(node, "touchscreen-swap", &pdata->swap)) {  
  248.         pdata->swap = 1;  
  249.     }  
  250.   
  251.     if (of_property_read_u32(node, "touchscreen-revert-x", &pdata->revert_x)) {  
  252.         pdata->revert_x = 1;  
  253.     }  
  254.   
  255.     if (of_property_read_u32(node, "touchscreen-revert-y", &pdata->revert_y)) {  
  256.         pdata->revert_y = 1;  
  257.     }  
  258.   
  259.     return pdata;  
  260. }  
  261.   
  262. static int gt811_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)  
  263. {  
  264.     struct device *dev = &client->dev;  
  265.     struct gt811_ts_platdata *pdata = dev_get_platdata(dev);  
  266.     struct input_dev *input;  
  267.     int error = 0;  
  268.   
  269.     if (!of_match_device(of_match_ptr(gt811_ts_of_match), dev)) {  
  270.         dev_err(dev, "Failed to match.\n");  
  271.         return -EINVAL;  
  272.     }  
  273.   
  274.     if (!pdata) {  
  275.         pdata = gt811_ts_parse_devtree(client);  
  276.         if (IS_ERR(pdata)) {  
  277.             dev_err(dev, "Get device data from device tree failed!\n");  
  278.             error = -EINVAL;  
  279.             goto failed_exit;  
  280.         }  
  281.     }  
  282.   
  283.     pdata->client = client;  
  284.   
  285.     i2c_set_clientdata(client, pdata);  
  286.   
  287.     error = devm_gpio_request_one(&client->dev, pdata->reset_pin,  
  288.                 GPIOF_OUT_INIT_HIGH, "gt811_rst_pin");  
  289.     if (error < 0) {  
  290.         dev_err(dev, "Failed to request gt811 reset pin\n");  
  291.         return error;  
  292.     }  
  293.   
  294.     input = devm_input_allocate_device(dev);  
  295.     if (!input) {  
  296.         dev_err(dev, "Failed to allocate input device\n");  
  297.         error = -ENOMEM;  
  298.         goto pdata_free;  
  299.     }  
  300.   
  301.     pdata->input = input;  
  302.   
  303.     input->name = client->name;  
  304.     input->id.bustype = BUS_I2C;  
  305.     input->id.product = 0xBEEF;  
  306.     input->id.vendor  =0xDEAD;  
  307.     input->dev.parent = &client->dev;  
  308.   
  309.     __set_bit(EV_KEY, input->evbit);  
  310.     __set_bit(EV_ABS, input->evbit);  
  311.     __set_bit(BTN_TOUCH, input->keybit);  
  312.     input_set_abs_params(input, ABS_X, 0, pdata->size_x, 0, 0);  
  313.     input_set_abs_params(input, ABS_Y, 0, pdata->size_y, 0, 0);  
  314.     input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->size_x, 0, 0);  
  315.     input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->size_y, 0, 0);  
  316.   
  317.     error = input_mt_init_slots(input, 5, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);  
  318.     if (error) {  
  319.         dev_err(dev, "Failed to initialize the multi-touch slots.\n");  
  320.         goto input_free;  
  321.     }  
  322.   
  323.     input_set_drvdata(input, pdata);  
  324.   
  325.     error = input_register_device(input);  
  326.     if (error) {  
  327.         dev_err(dev, "Register input device failed!\n");  
  328.         goto input_free;  
  329.     }  
  330.   
  331.     if (gt811_ts_initilize(client)) {  
  332.         dev_err(dev, "Failed to initialize GT811.\n");  
  333.     }  
  334.   
  335.     INIT_WORK(&pdata->work, gt811_ts_handler);  
  336.   
  337.     error = devm_request_irq(dev, client->irq, gt811_ts_isr,  
  338.                       IRQF_TRIGGER_FALLING, client->name, pdata);  
  339.     if (error) {  
  340.         dev_err(dev, "Failed to request irq(number:%d)\n", client->irq);  
  341.         goto input_free;  
  342.     }  
  343.   
  344.     return 0;  
  345.   
  346. input_free:  
  347.     devm_kfree(dev, input);  
  348. pdata_free:  
  349.     devm_kfree(dev, pdata);  
  350. failed_exit:  
  351.     return error;  
  352. }  
  353.   
  354. static int gt811_ts_remove(struct i2c_client *client)  
  355. {  
  356.     struct gt811_ts_platdata *pdata = (struct gt811_ts_platdata*)i2c_get_clientdata(client);  
  357.   
  358.     devm_free_irq(&client->dev, client->irq, i2c_get_clientdata(client));  
  359.   
  360.     input_unregister_device(pdata->input);  
  361.   
  362.     devm_kfree(&client->dev, pdata);  
  363.     return 0;  
  364. }  
  365.   
  366. static const struct i2c_device_id gt811_ts_id[] = {  
  367.     { "gt811_ts", 0 },  
  368.     { }  
  369. };  
  370.   
  371. static struct i2c_driver gt811_ts_driver = {  
  372.     .driver = {  
  373.         .owner  = THIS_MODULE,  
  374.         .name   = "gt811_ts",  
  375.         .of_match_table = of_match_ptr(gt811_ts_of_match),  
  376.     },  
  377.     .probe      = gt811_ts_probe,  
  378.     .remove     = gt811_ts_remove,  
  379.     .id_table   = gt811_ts_id,  
  380. };  
  381.   
  382. module_i2c_driver(gt811_ts_driver);  
  383.   
  384. MODULE_AUTHOR("girlkoo <nightmeng@gmail.com>");  
  385. MODULE_DESCRIPTION("GT811 I2C Touchscreen Driver");  
  386. MODULE_LICENSE("GPL");  
复制代码




  编译以上代码得到相应的ko文件,然后将该ko拷贝SD卡的根文件系统内。完整的代码下载链接如下(赚点下载积分^_^):
  http://download.csdn.net/detail/girlkoo/8710677

  测试方法

  我认为最实用的测试方法就是tslib,tslib的配置方法请参考TQ210的移植笔记或者自己网上搜索资料,我这里就不重复了,安装好tslib后先通过ts_calibrate校准触摸屏(实际上电容屏是不需要校准的,仅仅是为了使用tslib),然后运行ts_test并点draw按钮,即可随意画图。下面是实测效果图:

  至此,触摸屏驱动就移植完成了。有问题请帮忙指出,有任何疑问欢迎留言讨论。



gefsmile 发表于 2015-6-2 22:48:22 | 显示全部楼层
你好,我在使用源码的过程中出现了这个错误:Failed to get the version of GT811, try again...
请问一下,可能是什么原因?
hflw 发表于 2015-10-30 13:16:49 | 显示全部楼层
e9的板子,5寸屏,自己制作的根文件系统,自己编译的tslib,为什么ts_calibrate,校准时,没有任何反应,但是运行ts_print_raw很正常。但是我用官方给的文件系统,里面的QT程序运行时,触摸屏运行的也正常。谁遇到这个问题没
山鹰之念 发表于 2015-11-22 15:30:58 | 显示全部楼层
hflw 发表于 2015-10-30 13:16
e9的板子,5寸屏,自己制作的根文件系统,自己编译的tslib,为什么ts_calibrate,校准时,没有任何反应,但 ...

哥们  问题解决了吗?我也遇到了同样的问题
416604093 发表于 2018-4-13 15:28:25 | 显示全部楼层
你好,请问移植过gslX680驱动吗?加入设置触摸事件中断引脚的话,要修改哪些地方呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-3-28 23:44 , Processed in 1.031250 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表