在goodix官网上搜索gt911找到如下信息:
Channe(DxS) | Package | Size | Points | |
---|---|---|---|---|
GT911 | 26x14 | QFN52, 6x6 | 7”~8” | 5 |
late_initcall(goodix_ts_init);//驱动程序入口点
进入函数goodix_ts_init,可以看到如下内容:
/*******************************************************
Function:
Driver Install function.
Input:
None.
Output:
Executive Outcomes. 0---succeed.
********************************************************/
static int __devinit goodix_ts_init(void)
{
s32 ret;
GTP_DEBUG_FUNC();
GTP_INFO("GTP driver installing...");
goodix_wq = create_singlethread_workqueue("goodix_wq");//创建一个工作队列
if (!goodix_wq)
{
GTP_ERROR("Creat workqueue failed.");
return -ENOMEM;
}
#if GTP_ESD_PROTECT
INIT_DELAYED_WORK(>p_esd_check_work, gtp_esd_check_func);
gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
#endif
ret = i2c_add_driver(&goodix_ts_driver);//向系统注册驱动
return ret;
}
/* use a define to avoid include chaining to get THIS_MODULE */
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
extern int i2c_register_driver(struct module *, struct i2c_driver *);//注册I2C
驱动
/*注册的驱动结构定义*/
static struct i2c_driver goodix_ts_driver = {
.probe = goodix_ts_probe,
.remove = goodix_ts_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND//查询内核配置文件后可知,未定义此项,故包含下面这两个函数定义
.suspend = goodix_ts_suspend,
.resume = goodix_ts_resume,
#endif
.id_table = goodix_ts_id,//支持的设备ID号
.driver = {
.name = GTP_I2C_NAME,//驱动名称
.owner = THIS_MODULE,
},
};
I2C是一种总线结构,当设备插入时,如果设备ID包含在id_table中,驱动程序会和设备绑定在一起,然后支持该设备。
id_table定义:
static const struct i2c_device_id goodix_ts_id[] = {
{ GTP_I2C_NAME, 0 },
{ }
};
#define GTP_I2C_NAME "Goodix-TS"
name定义:
.name = GTP_I2C_NAME,//驱动名称
主要的是probe和remove函数:
probe函数定义:
/*******************************************************
Function:
I2c probe.
Input:
client: i2c device struct.
id: device id.
Output:
Executive outcomes.
0: succeed.
*******************************************************/
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
s32 ret = -1;
struct goodix_ts_data *ts;//设备自有结构体
u16 version_info;
GTP_DEBUG_FUNC();
//do NOT remove these logs
GTP_INFO("GTP Driver Version: %s", GTP_DRIVER_VERSION);
GTP_INFO("GTP Driver Built@%s, %s", __TIME__, __DATE__);
GTP_INFO("GTP I2C Address: 0x%02x", client->addr);
i2c_connect_client = client;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))//检测是否可用
{
GTP_ERROR("I2C check functionality failed.");
return -ENODEV;
}
ts = kzalloc(sizeof(*ts), GFP_KERNEL);/*分配一个结构体*/
if (ts == NULL)
{
GTP_ERROR("Alloc GFP_KERNEL memory failed.");
return -ENOMEM;
}
memset(ts, 0, sizeof(*ts));
INIT_WORK(&ts->work, goodix_ts_work_func);//初始化工作队列,处理函数为goodix_ts_work_func
ts->client = client;
spin_lock_init(&ts->irq_lock); // 2.6.39 later
// ts->irq_lock = SPIN_LOCK_UNLOCKED; // 2.6.39 & before
i2c_set_clientdata(client, ts);
ts->gtp_rawdiff_mode = 0;
ret = gtp_request_io_port(ts);/*请求RESET和INT端口*/
if (ret < 0)
{
GTP_ERROR("GTP request IO port failed.");
kfree(ts);
return ret;
}
ret = gtp_i2c_test(client);/*I2C功能测试*/
if (ret < 0)
{
GTP_ERROR("I2C communication ERROR!");
}
ret = gtp_read_version(client, &version_info);/*读固件版本号*/
if (ret < 0)
{
GTP_ERROR("Read version failed.");
}
ret = gtp_init_panel(ts);/*初始化gtp*/
if (ret < 0)
{
GTP_ERROR("GTP init panel failed.");
ts->abs_x_max = GTP_MAX_WIDTH;
ts->abs_y_max = GTP_MAX_HEIGHT;
ts->int_trigger_type = GTP_INT_TRIGGER;
}
ret = gtp_request_input_dev(ts);/*注册到输入系统中*/
if (ret < 0)
{
GTP_ERROR("GTP request input dev failed");
}
ret = gtp_request_irq(ts);/*请求中断*/
if (ret < 0)
{
GTP_INFO("GTP works in polling mode.");
}
else
{
GTP_INFO("GTP works in interrupt mode.");
}
if (ts->use_irq)
{
gtp_irq_enable(ts);
}
return 0;
}
//设备自有结构体定义
struct goodix_ts_data {
spinlock_t irq_lock;//自旋锁
struct i2c_client *client;//i2c_client
struct input_dev *input_dev;//输入设备
struct hrtimer timer;//high-resolution kernel timer
struct work_struct work;//工作队列
s32 irq_is_disable;//标识irq是否被禁用
s32 use_irq;
u16 abs_x_max;
u16 abs_y_max;
u8 max_touch_num;
u8 int_trigger_type;//中断触发类型;
u8 green_wake_mode;
u8 enter_update;
u8 gtp_is_suspend;
u8 gtp_rawdiff_mode;
u8 gtp_cfg_len;
u8 fixed_cfg;
u8 fw_error;
u8 pnl_init_error;
};
请求中断函数
/*******************************************************
Function:
Request interrupt.
Input:
ts: private data.
Output:
Executive outcomes.
0: succeed, -1: failed.
*******************************************************/
static s8 gtp_request_irq(struct goodix_ts_data *ts)
{
s32 ret = -1;
const u8 irq_table[] = GTP_IRQ_TAB;
GTP_DEBUG_FUNC();
GTP_DEBUG("INT trigger type:%x", ts->int_trigger_type);
/*申请中断irq,并注册中断处理函数goodix_ts_irq_handler ,返回值0表示成功,负数表示错误*/
ret = request_irq(ts->client->irq,
goodix_ts_irq_handler,
irq_table[ts->int_trigger_type],
ts->client->name,
ts);
if (ret)//若失败
{
GTP_ERROR("Request IRQ failed!ERRNO:%d.", ret);
GTP_GPIO_AS_INPUT(GTP_INT_PORT);
GTP_GPIO_FREE(GTP_INT_PORT);
hrtimer_init(&ts->timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);/*初始化定时器*/
ts->timer.function = goodix_ts_timer_handler;/*定时器处理函数*/
hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);/*启动定时器*/
return -1;
}
else
{
gtp_irq_disable(ts)/*禁止中断处理函数*/;
ts->use_irq = 1;/*设置标识位use_irq*/
return 0;
}
}
//中断处理函数goodix_ts_irq_handler
/*******************************************************
Function:
External interrupt service routine for interrupt mode.
Input:
irq: interrupt number.
dev_id: private data pointer
Output:
Handle Result.
IRQ_HANDLED: interrupt handled successfully
*********************************************************/
static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
{
struct goodix_ts_data *ts = dev_id;
GTP_DEBUG_FUNC();
gtp_irq_disable(ts);/*禁止中断*/
queue_work(goodix_wq, &ts->work);
return IRQ_HANDLED;
}
Queue_work=> queue_work_on=> __queue_work
Remove函数
Remove函数比较简单,主要释放在probe阶段申请到的资源。具体如下:
static int goodix_ts_remove(struct i2c_client *client)
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
GTP_DEBUG_FUNC();
if (ts)
{
if (ts->use_irq)/*若申请中断成功,释放中断资源*/
{
GTP_GPIO_AS_INPUT(GTP_INT_PORT);
GTP_GPIO_FREE(GTP_INT_PORT);
free_irq(client->irq, ts);
}
else
{
hrtimer_cancel(&ts->timer);
}
}
GTP_INFO("GTP driver removing...");
i2c_set_clientdata(client, NULL);
input_unregister_device(ts->input_dev);/*注销input_device*/
kfree(ts);/*释放在probe中申请的内存*/
return 0;
}
//suspend函数
static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
int ret = 0;
GTP_DEBUG_FUNC();
ts->gtp_is_suspend = 1;
if (ts->use_irq)
{
gtp_irq_disable(ts);
}
else
{
hrtimer_cancel(&ts->timer);
}
ret = gtp_enter_sleep(ts);
if (ret < 0)
{
GTP_ERROR("GTP early suspend failed.");
}
// to avoid waking up while not sleeping
// delay 48 + 10ms to ensure reliability
msleep(58);
return 0;
}
//resume函数
static int goodix_ts_resume(struct i2c_client *client)
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
int ret = 0;
GTP_DEBUG_FUNC();
ret = gtp_wakeup_sleep(ts);
if (ret < 0)
{
GTP_ERROR("GTP later resume failed.");
}
{
gtp_send_cfg(ts->client);
}
if (ts->use_irq)
{
gtp_irq_enable(ts);
}
else
{
hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
}
ts->gtp_is_suspend = 0;
return 0;
}
//出口函数
module_exit(goodix_ts_exit);//驱动程序出口点
static void __exit goodix_ts_exit(void)
{
GTP_DEBUG_FUNC();
GTP_INFO("GTP driver exited.");
i2c_del_driver(&goodix_ts_driver);/*卸载驱动*/
if (goodix_wq)
{
destroy_workqueue(goodix_wq);
}
}
定义goodix_ts_data私有数据结构和寄存器等。