首页
Web开发
Windows程序
编程语言
数据库
移动开发
系统相关
微信
其他好文
会员
首页
>
其他好文
> 详细
gt811 driver
时间:
2015-04-10 06:37:39
阅读:
193
评论:
0
收藏:
0
[点我收藏+]
标签:
#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>
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};
uint8_t count, index, flags, position;
int x, y;
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;
while (flags) {
if (!(flags&0x1)) {
continue;
}
if (index < 3) {
position = 4 + index * 5;
}
else{
position = 25 + (index - 3) * 5;
}
x = (buffer[position] << 8) | buffer[position + 1];
y = (buffer[position + 2] << 8) | buffer[position + 3];
if(pdata->swap) {
swap(x, y);
}
if(pdata->revert_x){
x = pdata->size_x - x;
}
if(pdata->revert_y){
y = pdata->size_y - y;
}
printk(
"point:(x:%03d, y:%03d)\n", x, y);
}
// 组织检测出来的触摸点信息上报到输入子系统节点即可
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-x", &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);
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_any_context_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");
gt811 driver
标签:
原文地址:http://www.cnblogs.com/zym0805/p/4413351.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年07月29日 (22)
2021年07月28日 (40)
2021年07月27日 (32)
2021年07月26日 (79)
2021年07月23日 (29)
2021年07月22日 (30)
2021年07月21日 (42)
2021年07月20日 (16)
2021年07月19日 (90)
2021年07月16日 (35)
周排行
更多
分布式事务
2021-07-29
OpenStack云平台命令行登录账户
2021-07-29
getLastRowNum()与getLastCellNum()/getPhysicalNumberOfRows()与getPhysicalNumberOfCells()
2021-07-29
【K8s概念】CSI 卷克隆
2021-07-29
vue3.0使用ant-design-vue进行按需加载原来这么简单
2021-07-29
stack栈
2021-07-29
抽奖动画 - 大转盘抽奖
2021-07-29
PPT写作技巧
2021-07-29
003-核心技术-IO模型-NIO-基于NIO群聊示例
2021-07-29
Bootstrap组件2
2021-07-29
友情链接
兰亭集智
国之画
百度统计
站长统计
阿里云
chrome插件
新版天听网
关于我们
-
联系我们
-
留言反馈
© 2014
mamicode.com
版权所有 联系我们:gaon5@hotmail.com
迷上了代码!