历史上的今天
今天是: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);
史海拾趣
|
产品名称:ATMEL9260ARM + JN5139Zigbee 售价:1188元 产品规格:14*9.2cm 10*6cm 产品型号:CA-9260-ZB-EK &nb ...… 查看全部问答> |
|
我手里的CY1C12开发板上的芯片是FPGA的EP1C12Q240C8,今天我用一个小程序,试图点亮那四个七段数码管。用的动态显示。然而,当我配置管脚,下载到板上后,数码管能够顺序点亮,但是不是之前程序里面设计的数字,有些乱码的感觉。 我怀疑是管脚配置 ...… 查看全部问答> |
|
XILINX FPGA 设计的点滴 1、为时钟信号选用全局时钟缓冲器BUFG 2、尽量只用一个时钟沿来寄存数据 3、除了用CLKDLL或DCM产生的时钟外不要在内部产生时钟 4、注意状态机编码的可靠性:状态机转移状态改变的位数越少,则功能越可靠。 5、逻辑 ...… 查看全部问答> |
|
刚刚接触Wince 6.0 现在要实现一个使用url链接下载的功能 ,参考了网上一些程序编写如下代码 void CHttpGet::Download(CString url) { try { CStdioFile* pSFile=NULL; CInternetSession ...… 查看全部问答> |
|
我将ADS1.2下一个工程移植到Keil3 IDE下时,在解决了一些编译错误问题后,也参考了一些说明,编译完成后没有错误,当然有一堆的警告,什么字符串无效,最后一行没空等,但是连接没有生成默认该生成的.axf文件,导致调试也找不到.axf文件,当然也生 ...… 查看全部问答> |
|
evc中怎样编辑多国语言 比如说我要SetWindowText(_T(\"? ?? ??\")); 但在Evc中成了SetWindowText(_T(\"? ?? ??\")); … 查看全部问答> |
|
EE_FPGA V1.0 调试进展(2010.10.17更新) 正面: 反面: 目前进展: 1. 最小系统工作 2. LED工作 3. key工作 4. usb转串口驱动正常,串口工作正常 稍后上图,敬请关注 10.17更新 [ 本帖最后由 chenzhufly 于 2010-10-17 14:20 编辑 ]… 查看全部问答> |




