gt9xx.c和gt9xx.h文件分析

在goodix官网上搜索gt911找到如下信息:

Channe(DxS)PackageSizePoints
GT91126x14QFN52, 6x67”~8”5

1.gt9xx.c源码分析:

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(&gtp_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);
    }
}

2.gt9xx.h源码分析

定义goodix_ts_data私有数据结构和寄存器等。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
gt9xx.h 是 Linux 中 Goodix 公司触摸屏芯片驱动的头文件,其中定义了一些宏和数据结构,用于描述触摸屏芯片的各种属性和操作。 在该头文件中,主要的宏包括: - GT9XX_NAME:表示触摸屏芯片的名称,通常为 "gt9xx"。 - GT9XX_I2C_ADDR:表示触摸屏芯片的 I2C 地址,通常为 0x5d。 - GT9XX_MAX_TOUCH:表示触摸屏芯片最多支持的触摸点数。 - GT9XX_MAX_CONTACT_SIZE:表示每个触摸点的最大尺寸。 - GT9XX_REG_CONFIG_DATA:表示触摸屏芯片的配置数据寄存器地址。 - GT9XX_REG_READ_COORD:表示触摸屏芯片的坐标数据寄存器地址。 - GT9XX_REG_READ_STATUS:表示触摸屏芯片的状态寄存器地址。 - GT9XX_REG_FIRMWARE:表示触摸屏芯片的固件版本寄存器地址。 - GT9XX_REG_PRODUCT_ID:表示触摸屏芯片的产品 ID 寄存器地址。 - GT9XX_REG_VENDOR_ID:表示触摸屏芯片的厂商 ID 寄存器地址。 - GT9XX_REG_POINT_RATE:表示触摸屏芯片的采样率寄存器地址。 除了上述宏之外,该头文件中还定义了一些数据结构,例如 gt9xx_ts_data 和 gt9xx_config,分别用于保存触摸数据和触摸屏芯片的配置信息。此外,该头文件还声明了一些函数原型,例如 gt9xx_probe、gt9xx_remove、gt9xx_suspend 和 gt9xx_resume,用于初始化触摸屏芯片驱动、卸载驱动、挂起和恢复操作等。 总的来说,gt9xx.h 头文件是 Linux 中 Goodix 公司触摸屏芯片驱动的头文件,定义了一些宏和数据结构,用于描述触摸屏芯片的各种属性和操作,并声明了一些函数原型,用于初始化和控制触摸屏芯片驱动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值