您的位置:首页 > 编程语言 > PHP开发

MTK平台tp驱动详解

2016-05-10 11:52 1061 查看

MTK平台tp驱动详解

本博文将讲解基于Goodix触控芯片的tp驱动程序。这里有对应的驱动程序。

初始化

static int __init tpd_driver_init(void)
{
GTP_INFO("MediaTek gt91xx touch panel driver init\n");
#if defined(TPD_I2C_NUMBER)
i2c_register_board_info(TPD_I2C_NUMBER, &i2c_tpd, 1);
#else
i2c_register_board_info(0, &i2c_tpd, 1);
#endif
if (tpd_driver_add(&tpd_device_driver) < 0)
GTP_INFO("add generic driver failed\n");

return 0;
}


tpd_driver_init
中主要做了两件事情:

1、注册一个i2c设备

i2c_register_board_info
在 kernel\drivers\i2c\i2c-boardinfo.c 中定义。

对应的函数说明如下:

i2c_register_board_info - statically declare I2C devices

* @busnum: identifies the bus to which these devices belong

* @info: vector of i2c device descriptors

* @len: how many descriptors in the vector; may be zero to reserve

* the specified bus number.

因此我们可知道:

TPD_I2C_NUMBER
表示的是当前注册的i2c设备是在哪个总线上面,需要查看硬件连接图;

i2c_tpd
表示的是该i2c设备的描述,包括设备名”gt9xx”和i2c的设备地址“(0xBA >> 1)”

static struct i2c_board_info __initdata i2c_tpd = { I2C_BOARD_INFO("gt9xx", (0xBA >> 1))};


2、添加一个驱动到静态数组
tpd_driver_list
数组中


if (tpd_driver_add(&tpd_device_driver) < 0)
GTP_INFO("add generic driver failed\n");


其中
tpd_device_driver
的定义为:

static struct tpd_driver_t tpd_device_driver =
{
.tpd_device_name = "gt9xx",
.tpd_local_init = tpd_local_init,
.suspend = tpd_suspend,
.resume = tpd_resume,
#ifdef TPD_HAVE_BUTTON
.tpd_have_button = 1,
#else
.tpd_have_button = 0,
#endif
};


这几个选项都是必须的。

其中的
tpd_device_name
不能为”generic”,那样的话就会识别为R-Touch(推测此处表示为电阻屏),被保存到
tpd_driver_list[0]
中。否则为C-Touch(推测此处表示为电容屏),保存到
tpd_driver_list
的非0位置处。在TP驱动中要自己实现这几个函数的所有内容。

tpd_local_init()

static int tpd_local_init(void)
{
#if GTP_ESD_PROTECT
clk_tick_cnt = 2 * HZ;   // HZ: clock ticks in 1 second generated by system
GTP_DEBUG("Clock ticks for an esd cycle: %d", clk_tick_cnt);
INIT_DELAYED_WORK(>p_esd_check_work, gtp_esd_check_func);
gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
spin_lock_init(&esd_lock);          // 2.6.39 & later
// esd_lock = SPIN_LOCK_UNLOCKED;   // 2.6.39 & before
#endif

#if GTP_SUPPORT_I2C_DMA
tpd->dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
gpDMABuf_va = (u8 *)dma_alloc_coherent(&tpd->dev->dev, GTP_DMA_MAX_TRANSACTION_LENGTH, &gpDMABuf_pa, GFP_KERNEL);
if(!gpDMABuf_va)
{
GTP_INFO("[Error] Allocate DMA I2C Buffer failed!\n");
}
memset(gpDMABuf_va, 0, GTP_DMA_MAX_TRANSACTION_LENGTH);
#endif
if (i2c_add_driver(&tpd_i2c_driver) != 0)
{
GTP_INFO("unable to add i2c driver.\n");
return -1;
}

if (tpd_load_status == 0) //if(tpd_load_status == 0) // disable auto load touch driver for linux3.0 porting
{
GTP_INFO("add error touch panel driver.\n");
i2c_del_driver(&tpd_i2c_driver);
return -1;
}
input_set_abs_params(tpd->dev, ABS_MT_TRACKING_ID, 0, (GTP_MAX_TOUCH-1), 0, 0);

#ifdef TPD_HAVE_BUTTON
if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())  // cty 2014-08-14
{
tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local_factory, tpd_keys_dim_local);// initialize tpd button data
}
else
{
tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data
}
#endif

#if (defined(TPD_WARP_START) && defined(TPD_WARP_END))
TPD_DO_WARP = 1;
memcpy(tpd_wb_start, tpd_wb_start_local, TPD_WARP_CNT * 4);
memcpy(tpd_wb_end, tpd_wb_start_local, TPD_WARP_CNT * 4);
#endif

#if (defined(TPD_HAVE_CALIBRATION) && !defined(TPD_CUSTOM_CALIBRATION))
memcpy(tpd_calmat, tpd_def_calmat_local, 8 * 4);
memcpy(tpd_def_calmat, tpd_def_calmat_local, 8 * 4);
#endif

// set vendor string
tpd->dev->id.vendor = 0x00;
tpd->dev->id.product = tpd_info.pid;
tpd->dev->id.version = tpd_info.vid;

GTP_INFO("end %s, %d\n", __FUNCTION__, __LINE__);
tpd_type_cap = 1;

return 0;
}


该函数主要做以下几项工作:

1、GTP_ESD_PROTECT的内容暂时不知道做啥的。

2、GTP_SUPPORT_I2C_DMA主要是申请I2C DMA的空间,由
gpDMABuf_va
指向。

tpd->dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
表示这个设备能寻址的物理地址的范围为
DMA_BIT_MASK(32)
,这个值相当于
0xffffffffUL
。关于这个成员的解释可以参见 linux下platform_device中的dma_mask与coherent_dma_mask

接下来的
dma_alloc_coherent()
申请DMA空间。返回值为
gpDMABuf_va
表示虚拟地址,以及返回
gpDMABuf_pa
表示DMA实际物理地址。至于这两个怎么用还不是很懂。详见:Dynamic DMA mapping using the generic device

3、注册i2c设备驱动

if (i2c_add_driver(&tpd_i2c_driver) != 0)
{
GTP_INFO("unable to add i2c driver.\n");
return -1;
}
if (tpd_load_status == 0) //if(tpd_load_status == 0) // disable auto load touch driver for linux3.0 porting
{
GTP_INFO("add error touch panel driver.\n");
i2c_del_driver(&tpd_i2c_driver);
return -1;
}


probe探测到总线上的设备并把设备和驱动建立连接以完成设备的初始化。这个中间会调用
tpd_i2c_driver
中的
tpd_i2c_probe()
来完成初始化工作。

static struct i2c_driver tpd_i2c_driver =
{
.probe = tpd_i2c_probe,
.remove = tpd_i2c_remove,
.detect = tpd_i2c_detect,
.driver.name = "b_gt9xx_hotknot",
.id_table = tpd_i2c_id,
.address_list = (const unsigned short *) forces,
};


这里面的内容都要自己去实现,特别是
tpd_i2c_probe()
。如果
tpd_i2c_probe()
中初始化设备全部完成,则要置位全局变量
tpd_load_status
为1标记成功初始化,否则的话匹配失败需要调用
i2c_del_driver()
删除已注册的驱动。

4、设置input设备
tpd->dev
支持的最大手指触摸个数


input_set_abs_params(tpd->dev, ABS_MT_TRACKING_ID, 0, (GTP_MAX_TOUCH-1), 0, 0);


input设备
tpd->dev
的申请以及定义和初始化的内容都在mtk_tpd.c这个文件中的
tpd_probe()
函数实现了。推测之所以没有一起初始化的
ABS_MT_TRACKING_ID
的内容是因为每个触控IC的原厂软件实现最大的触摸个数都不太一样,所以这里需要根据情况自己设定。

5、按键的初始化

#ifdef TPD_HAVE_BUTTON
if (FACTORY_BOOT == get_boot_mode()|| RECOVERY_BOOT == get_boot_mode())  // cty 2014-08-14
{
tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local_factory, tpd_keys_dim_local);// initialize tpd button data
}
else
{
tpd_button_setting(TPD_KEY_COUNT, tpd_keys_local, tpd_keys_dim_local);// initialize tpd button data
}
#endif


tpd_button_setting()
函数的内容非常简单,就是将数组
tpd_keys_local[TPD_KEY_COUNT]
tpd_keys_dim_local[TPD_KEY_COUNT][4]
拷贝给
tpd_keys
tpd_keys_dim
。这两个变量用于
tpd_button_init()
的初始化创建virtual keys。数组内容要根据TP的分辨率来确定按键的位置。

6、设置input设备
tpd->dev
的信息


// set vendor string
tpd->dev->id.vendor = 0x00;
tpd->dev->id.product = tpd_info.pid;
tpd->dev->id.version = tpd_info.vid;


7、设置TP类型会电容屏

tpd_type_cap = 1;


从变量字面上的意思来看是设置标记TP为电容屏,至于还有何作用还不得而知。

tpd_i2c_probe()

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: