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