修改设备树
修改 pinctrl_tsc
原来配置如下:
pinctrl_tsc: tscgrp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0xb0
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xb0
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0xb0
MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0xb0
>;
};
修改后配置如下:
pinctrl_tsc: tscgrp {
fsl,pins = <
MX6UL_PAD_GPIO1_IO09__GPIO1_IO09 0XF080
>;
};
删除复用IO
添加节点
gt9147是使用i2c进行通信,从机地址是0x14,在i2c2添加如下
gt9147:gt9147@14 {
compatible = "goodix,gt9147", "goodix,gt9xx";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tsc>;
reg = <0x14>;
interrupt-parent = <&gpio1>;
interrupts = <9 0>;
reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
status = "okay";
};
编译设备树更新到开发板
添加驱动程序,驱动代码如下
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/i2c.h>
#define GT_CTRL_REG 0X8040
#define GT_MODSW_REG 0X804D
#define GT_CFGS_REG 0X8047
#define GT_CHECK_REG 0X80FF
#define GT_PID_REG 0X8140
#define GT_GSTID_REG 0X814E
#define GT_TP1_REG 0X814F
#define GT_TP2_REG 0X8157
#define GT_TP3_REG 0X815F
#define GT_TP4_REG 0X8167
#define GT_TP5_REG 0X816F
#define MAX_SUPPORT_POINTS 5
struct gt9147_dev {
int irq_pin,reset_pin;
int irqnum;
void *private_data;
struct input_dev *input;
struct i2c_client *client;
};
struct gt9147_dev gt9147;
const unsigned char GT9147_CT[]=
{
0x48,0xe0,0x01,0x10,0x01,0x05,0x0d,0x00,0x01,0x08,
0x28,0x05,0x50,0x32,0x03,0x05,0x00,0x00,0xff,0xff,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x28,0x0a,
0x17,0x15,0x31,0x0d,0x00,0x00,0x02,0x9b,0x03,0x25,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,
0x00,0x0f,0x94,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,
0x8d,0x13,0x00,0x5c,0x1e,0x00,0x3c,0x30,0x00,0x29,
0x4c,0x00,0x1e,0x78,0x00,0x1e,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,
0x18,0x1a,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x00,0x02,0x04,0x05,0x06,0x08,0x0a,0x0c,
0x0e,0x1d,0x1e,0x1f,0x20,0x22,0x24,0x28,0x29,0xff,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
};
static int gt9147_ts_reset(struct i2c_client *client, struct gt9147_dev *dev)
{
int ret = 0;
if (gpio_is_valid(dev->reset_pin)) {
ret = devm_gpio_request_one(&client->dev,
dev->reset_pin, GPIOF_OUT_INIT_HIGH,
"gt9147 reset");
if (ret) {
return ret;
}
}
if (gpio_is_valid(dev->irq_pin)) {
ret = devm_gpio_request_one(&client->dev,
dev->irq_pin, GPIOF_OUT_INIT_HIGH,
"gt9147 int");
if (ret) {
return ret;
}
}
gpio_set_value(dev->reset_pin, 0);
msleep(10);
gpio_set_value(dev->reset_pin, 1);
msleep(10);
gpio_set_value(dev->irq_pin, 0);
msleep(50);
gpio_direction_input(dev->irq_pin);
return 0;
}
static int gt9147_read_regs(struct gt9147_dev *dev, u16 reg, u8 *buf, int len)
{
int ret;
u8 regdata[2];
struct i2c_msg msg[2];
struct i2c_client *client = (struct i2c_client *)dev->client;
regdata[0] = reg >> 8;
regdata[1] = reg & 0xFF;
msg[0].addr = client->addr;
msg[0].flags = !I2C_M_RD;
msg[0].buf = ®data[0];
msg[0].len = 2;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].buf = buf;
msg[1].len = len;
ret = i2c_transfer(client->adapter, msg, 2);
if(ret == 2) {
ret = 0;
} else {
ret = -EREMOTEIO;
}
return ret;
}
static s32 gt9147_write_regs(struct gt9147_dev *dev, u16 reg, u8 *buf, u8 len)
{
u8 b[256];
struct i2c_msg msg;
struct i2c_client *client = (struct i2c_client *)dev->client;
b[0] = reg >> 8;
b[1] = reg & 0XFF;
memcpy(&b[2],buf,len);
msg.addr = client->addr;
msg.flags = 0;
msg.buf = b;
msg.len = len + 2;
return i2c_transfer(client->adapter, &msg, 1);
}
static irqreturn_t gt9147_irq_handler(int irq, void *dev_id)
{
int touch_num = 0;
int input_x, input_y;
int id = 0;
int ret = 0;
u8 data;
u8 touch_data[5];
struct gt9147_dev *dev = dev_id;
ret = gt9147_read_regs(dev, GT_GSTID_REG, &data, 1);
if (data == 0x00) {
goto fail;
} else {
touch_num = data & 0x0f;
}
if(touch_num) {
gt9147_read_regs(dev, GT_TP1_REG, touch_data, 5);
id = touch_data[0] & 0x0F;
if(id == 0) {
input_x = touch_data[1] | (touch_data[2] << 8);
input_y = touch_data[3] | (touch_data[4] << 8);
input_mt_slot(dev->input, id);
input_mt_report_slot_state(dev->input, MT_TOOL_FINGER, true);
input_report_abs(dev->input, ABS_MT_POSITION_X, input_x);
input_report_abs(dev->input, ABS_MT_POSITION_Y, input_y);
}
} else if(touch_num == 0){
input_mt_slot(dev->input, id);
input_mt_report_slot_state(dev->input, MT_TOOL_FINGER, false);
}
input_mt_report_pointer_emulation(dev->input, true);
input_sync(dev->input);
data = 0x00;
gt9147_write_regs(dev, GT_GSTID_REG, &data, 1);
fail:
return IRQ_HANDLED;
}
static int gt9147_ts_irq(struct i2c_client *client, struct gt9147_dev *dev)
{
int ret = 0;
ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
gt9147_irq_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->name, >9147);
if (ret) {
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
return ret;
}
return 0;
}
void gt9147_send_cfg(struct gt9147_dev *dev, unsigned char mode)
{
unsigned char buf[2];
unsigned int i = 0;
buf[0] = 0;
buf[1] = mode;
for(i = 0; i < (sizeof(GT9147_CT)); i++)
buf[0] += GT9147_CT[i];
buf[0] = (~buf[0]) + 1;
gt9147_write_regs(dev, GT_CFGS_REG, (u8 *)GT9147_CT, sizeof(GT9147_CT));
gt9147_write_regs(dev, GT_CHECK_REG, buf, 2);
}
int gt9147_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
u8 data, ret;
gt9147.client = client;
gt9147.irq_pin = of_get_named_gpio(client->dev.of_node, "interrupt-gpios", 0);
gt9147.reset_pin = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0);
ret = gt9147_ts_reset(client, >9147);
if(ret < 0) {
goto fail;
}
data = 0x02;
gt9147_write_regs(>9147, GT_CTRL_REG, &data, 1);
mdelay(100);
data = 0x0;
gt9147_write_regs(>9147, GT_CTRL_REG, &data, 1);
mdelay(100);
gt9147.input = devm_input_allocate_device(&client->dev);
if (!gt9147.input) {
ret = -ENOMEM;
goto fail;
}
gt9147.input->name = client->name;
gt9147.input->id.bustype = BUS_I2C;
gt9147.input->dev.parent = &client->dev;
__set_bit(EV_KEY, gt9147.input->evbit);
__set_bit(EV_ABS, gt9147.input->evbit);
__set_bit(BTN_TOUCH, gt9147.input->keybit);
input_set_abs_params(gt9147.input, ABS_X, 0, 480, 0, 0);
input_set_abs_params(gt9147.input, ABS_Y, 0, 272, 0, 0);
input_set_abs_params(gt9147.input, ABS_MT_POSITION_X,0, 480, 0, 0);
input_set_abs_params(gt9147.input, ABS_MT_POSITION_Y,0, 272, 0, 0);
ret = input_mt_init_slots(gt9147.input, MAX_SUPPORT_POINTS, 0);
if (ret) {
goto fail;
}
ret = input_register_device(gt9147.input);
if (ret)
goto fail;
ret = gt9147_ts_irq(client, >9147);
if(ret < 0) {
goto fail;
}
return 0;
fail:
return ret;
}
int gt9147_remove(struct i2c_client *client)
{
input_unregister_device(gt9147.input);
return 0;
}
const struct i2c_device_id gt9147_id_table[] = {
{ "goodix,gt9147", 0, },
{ }
};
const struct of_device_id gt9147_of_match_table[] = {
{.compatible = "goodix,gt9147" },
{ }
};
struct i2c_driver gt9147_i2c_driver = {
.driver = {
.name = "gt9147",
.owner = THIS_MODULE,
.of_match_table = gt9147_of_match_table,
},
.id_table = gt9147_id_table,
.probe = gt9147_probe,
.remove = gt9147_remove,
};
module_i2c_driver(gt9147_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jankin");
编译KO 移植到开发板
.测试触摸是否可用,使用如下指令查看触摸中断次数,及查看驱动是否正常加载
cat /proc/interrupts
添加完成!!!
|