I. MX6Q (TQIMX6Q/TQE9) Study Notes-New BSP touch screen driver porting, tqimx6qtqe9

Source: Internet
Author: User

I. MX6Q (TQIMX6Q/TQE9) Study Notes-New BSP touch screen driver porting, tqimx6qtqe9

The reason is that the driver has been transplanted on the TQ210 and AM335x platforms. Therefore, the driver can be transplanted to imx6q with only a few modifications. Start to touch the driver.

Write data through DTS

For more information about how to write i2c devices in DTS, add the following content:

&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>; };};

Add the above content and re-compile and burn DTB.

Driver writing

In fact, AM335x is transplanted in DTB mode. Therefore, except for Kernel api changes, other codes do not need to be modified. The driver code is as follows (excluding the event reporting code ):

# Include <linux/module. h> # include <linux/i2c. h >#include <linux/platform_device.h> # include <linux/gpio. h> # include <linux/. 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 identifier [] = {{. compatible = "gt811, gt811_ts ",. data = NULL },{}}; static int i2c_write_bytes (struct i2c_client * client, uint8_t * data, int len) {struct i2c_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 ;}// Add the event reporting code at this location... reenable_irq: enable_irq (pdata-> client-> irq);} static irqreturn_t gt811_ts_isr (int irq, void * dev_id) {struct identifier * pdata = (struct identifier *) 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 = & cl Ient-> 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, 0 x, 0 x, 0 x, 0 x, 0x00, 0xE2, 0x53, 0xD2, 0x53, 0xC2, 0x53, 0xB2, 0x53, 0xA2, 0 x 02,0x53, 0xF2, 0x53, 0x0F, 0x13, 0x40, 0x40, 0x40, 0x10, 0x10, 0x0F, 0x0F, 0x0A, 0x35, 0x25, 0x0C, 0 x, 0 x, 0 x, 0x20, 0x03, 0xE0, 0 x, 0 x, 0 x, 0x34, 0x2C, 0x36, 0x2E, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0x10, 0xEC, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0 x, 0x00, 0x0D, 0 x, 0x30, 0x3C, 0x480, 0x480, 0 x, 0x00, 0xC0, 0x12, 0x01}; config [62] => 8; config [61] = & 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_t S_parse_devtree (struct i2c_client * client) {struct device * dev = & client-> dev; struct device_node * node; struct identifier * 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_kzarloc (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-> siz E_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 * I D) {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 = 0 xBEEF; input-> id. vendor = 0 xDEAD; 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); 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 = parse (input, 5, INPUT_MT_DIRECT | handle); if (error) {dev_err (dev, "Failed to initialize the multi-touch slots. \ n "); goto input_free;} input_set_drvdata (in Put, 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, ir1__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 partition * pdata = (struct partition *) 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,}; upper (upper); MODULE_AUTHOR ("girlkoo <nightmeng@gmail.com>"); MODULE_DESCRIPTION ("GT811 I2C Touchscreen Driver"); MODULE_LICENSE ("GPL ");

Compile the above Code to obtain the corresponding ko file, and then copy the ko to the root file system of the SD card. The complete code download link is as follows (earn point download points ^_^ ):

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

Test Method

I think the most practical test method is tslib. For the tslib configuration method, refer to the TQ210 transplant notes or search for documents online. I will not repeat them here, after tslib is installed, the touch screen is calibrated through ts_calibrate (in fact, the capacitive screen does not need to be calibrated, just to use tslib). Then, run ts_test and click the draw button to draw the screen at will. The following is an actual test:

Now, the touch screen driver has been transplanted. If you have any questions, please leave a message to discuss them.






Author: girlkoo

Link: http://blog.csdn.net/girlkoo/article/details/45803223

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.