I.MX6Q(TQIMX6Q/TQE9)學習筆記——新版BSP之觸控螢幕驅動移植,tqimx6qtqe9

來源:互聯網
上載者:User

I.MX6Q(TQIMX6Q/TQE9)學習筆記——新版BSP之觸控螢幕驅動移植,tqimx6qtqe9

之所以說是驅動移植是因為之前已經在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 <linux/module.h>#include <linux/i2c.h>#include <linux/platform_device.h>#include <linux/gpio.h>#include <linux/of.h>#include <linux/of_platform.h>#include <linux/of_gpio.h>#include <linux/input.h>#include <linux/input/mt.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/io.h>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 succeed\n");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 pin\n");return error;}input = devm_input_allocate_device(dev);if (!input) {dev_err(dev, "Failed to allocate input device\n");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);goto input_free;}return 0;input_free:devm_kfree(dev, input);pdata_free:devm_kfree(dev, pdata);failed_exit:return error;}static int gt811_ts_remove(struct i2c_client *client){struct gt811_ts_platdata *pdata = (struct gt811_ts_platdata*)i2c_get_clientdata(client);devm_free_irq(&client->dev, client->irq, i2c_get_clientdata(client));input_unregister_device(pdata->input);devm_kfree(&client->dev, pdata);return 0;}static const struct i2c_device_id gt811_ts_id[] = {{ "gt811_ts", 0 },{ }};static struct i2c_driver gt811_ts_driver = {.driver = {.owner= THIS_MODULE,.name= "gt811_ts",.of_match_table = of_match_ptr(gt811_ts_of_match),},.probe= gt811_ts_probe,.remove= gt811_ts_remove,.id_table   = gt811_ts_id,};module_i2c_driver(gt811_ts_driver);MODULE_AUTHOR("girlkoo <nightmeng@gmail.com>");MODULE_DESCRIPTION("GT811 I2C Touchscreen Driver");MODULE_LICENSE("GPL");

編譯以上代碼得到相應的ko檔案,然後將該ko拷貝SD卡的根檔案系統內。完整的代碼下載連結如下(賺點下載積分^_^):

http://download.csdn.net/detail/girlkoo/8710677

測試方法

我認為最實用的測試方法就是tslib,tslib的配置方法請參考TQ210的移植筆記或者自己網上搜尋資料,我這裡就不重複了,安裝好tslib後先通過ts_calibrate校準觸控螢幕(實際上電容屏是不需要校準的,僅僅是為了使用tslib),然後運行ts_test並點draw按鈕,即可隨意畫圖。下面是實測:

至此,觸控螢幕驅動就移植完成了。有問題請幫忙指出,有任何疑問歡迎留言討論。






本文作者:girlkoo

本文連結:http://blog.csdn.net/girlkoo/article/details/45803223

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.