转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>
DA9034是一个集成了电源管理、音频设备、触摸屏控制器和能用A/D|D/A转换的多功能芯片。最近读了一下相关驱动程序,这里记些笔记,不成体系,作为备忘而已。有兴趣的朋友可以一起讨论。
DA9034有两个输入设备,一个开关机键和触摸屏。
开关机键设备是一个platform device,在littleton.c中定义:
static struct platform_device micco_keys_device =
{
.name = "micco-keys",
.id = -1,
};
开关机键的驱动程序在drivers/input/keyboard/micco_keys.c里:
static struct platform_driver micco_keys_driver =
{
.probe = micco_keys_probe,
.remove = __devexit_p (micco_keys_remove),
.suspend = micco_keys_suspend,
.resume = micco_keys_resume,
.driver =
{
.name = "micco-keys",
},
};
在micco_keys_probe里会创建一个输入设备。
static int __devinit micco_keys_probe (struct platform_device *pdev)
{
input_dev = input_allocate_device ();
...
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->open = micco_keys_open;
input_dev->close = micco_keys_close;
input_dev->dev.parent = &pdev->dev;
if (input_register_device (input_dev))
{
dev_err (&pdev->dev, "failed to register input device/n");
input_free_device (input_dev);
return -ENOMEM;
}
g_input_dev = input_dev;
return 0;
}
在micco_keys_open里会注册DA9034的中断处理函数:
static int micco_keys_open (struct input_dev *dev)
{
unsigned long flags;
spin_lock_irqsave (&g_use_count, flags);
if (g_use_count == 0)
{
if (pmic_callback_register (EVENT_KEYS, micco_keys_interrup) < 0)
{
spin_unlock_irqrestore (&g_use_count, flags);
return -1;
}
g_use_count ++;
}
spin_unlock_irqrestore (&g_use_count, flags);
return 0;
}
在第一篇笔记中,我们已经知道:在micco的中断处理函数中,会调用pmic_event_handle去分发中断事件,我们说过DA9034是一个多功能设备,每个设备都有自己的驱动程序,pmic_event_handle。所以只是一个总入口它只是调用各个实际驱动程序注册的回调函数:
对于开关机键的驱动程序,它注册了函数micco_keys_interrup给pmic_event_handle调用。在micco_keys_interrup函数里,会根据按键的状态上报输入事件。
if (event & PMIC_EVENT_ONKEY)
{
micco_read (MICCO_STATUS_A, &val);
input_report_key (g_input_dev, KEY_POWER, (val & MICCO_STATUS_A_ONKEY) ? 0 : 1);
}
触摸屏设备是一个platform device,在littleton.c中定义:
static struct platform_device micco_ts_device = {
.name = "micco-ts",
.id = -1,
};
触摸屏设备的驱动程序在drivers/input/touchscreen/micco_touch.c里:
static struct platform_driver micco_ts_driver = {
.driver = {
.name = "micco-ts",
},
.probe = micco_ts_probe,
.remove = micco_ts_remove,
.resume = micco_ts_resume,
.suspend = micco_ts_suspend,
};
和开关机键的probe函数一样,micco_ts_probe先注册了一个输入设备,不过还同时做了其它事件:
1. 注册了micco_ts_interrupt给pmic_event_handle调用。
2. 初始化触摸屏相关的寄存器。
3. 创建proc文件。
4. 注册笔点事件的处理函数。
static int micco_ts_probe(struct platform_device *pdev)
{
...
ret = input_register_device(micco_ts_input_dev);
...
ret = pmic_callback_register(PMIC_EVENT_TOUCH, micco_ts_interrupt);
...
micco_enable_pen_down_irq(1);
micco_tsi_poweron();
micco_ts_proc_entry = create_proc_entry("driver/micco_ts", 0, NULL);
...
ts_filter_create_chain (pdev, micco_ts_filter_apis, micco_ts_filter_configs, &micco_ts_filter, 2);
micco_ts_filter->api->clear (micco_ts_filter);
return 0;
}
在函数micco_ts_open中,创建了一个线程(micco_ts_thread)循环查询触摸屏的状态,对事件进行滤波处理后,上报给用户空间。
在中断处理函数micco_ts_interrupt里,只是唤醒事件处理线程。