都说三星的MCU对触摸屏支持不是很好,所以打算找专用的触摸屏芯片解决触摸屏不准的问题。看到linux源码有对tsc2007的支持,real210屏线也把I2C接口引出,所以现拿这个芯片下手。
对于高手来说,编写驱动,很多步骤都是顺其自然的,但是我作为新手,遇到很多问题。以下是我的步骤及中间遇到的一些问题的解决。
1.make xconfig,找到devicedriver-Input device support-Touchscreens-TSC2007 based touchscreen打钩。
执行make。按照我的理解,这样之后应该会产生一个input设备,但是查看/dev/input下并没有相应设备出现。
dmesg | grep i2c和dmesg | greptsc2007查看输出信息,发现驱动程序内的probe函数未执行。
百度了一下,probe被调用的前提是driver和device配对成功。的确,到现在为止,根本没有创建device。
一般来说,添加一个device的过程是先在板级配置文件中加入如下相似代码:
786 static structresource tsc2007_resource[]={
787 [0]={
788 .start=IRQ_EINT(20),
789 .end=IRQ_EINT(20),
790 .flags=IORESOURCE_IRQ,
791 },
792 };
793
794 static structplatform_device tsc2007_device={
795 .name="tsc2007",
796 .id=-1,
797 .num_resources=ARRAY_SIZE(tsc2007_resource),
798 .resource=tsc2007_resource,
799 };
然后调用platform_add_devices(&&tsc2007_device,1)函数加入一个device。这样驱动函数初始化过程中会通过匹配相同的名字查找device进行配对,调用probe函数。我开始就是这么做的,但发现probe函数还是没有被调用。
查了一些资料,查看I2C源代码,发现tsc2007是一个I2C的设备,所有注册操作都是按照I2C子系统的规范进行的。正确的方法应该是调用i2c_register_board_info注册一个i2c设备。
2.修改mach-smdkv210.c,加入一个i2c设备
在I2C0总线上加入一个名叫tsc2007的设备,设备名一定要和驱动程序内的.name相同。
817 static struct i2c_board_infoi2c_devs0[] __initdata = {
818 #ifdef CONFIG_SND_SOC_WM8580
819 {
820 I2C_BOARD_INFO("wm8580",0x1b),
821 },
822 #endif
823 #ifdef CONFIG_TOUCHSCREEN_TSC2007
824 {
825 I2C_BOARD_INFO("tsc2007",(0x90>>1)),
826 .irq=IRQ_EINT(20),
827 },
828 #endif
829
830 };
调用i2c_register_board_info(0,i2c_devs0, ARRAY_SIZE(i2c_devs0));注册一个i2c设备。
接着make,新内核启动后发现probe函数被调用了,ok,成功了第一步。但是提示tsc2007 platform data is required!
3.重新修改mach-smdkv210.c,加入platform_data以及硬件相关函数
tsc2007的平台相关数据的结构体structtsc2007_platform_data定义在linux/i2c/tsc2007.h,所以要先包含这个头文件。
查看这个数据结构
6 struct tsc2007_platform_data {
7 u16 model; /*2007. */
8 u16 x_plate_ohms;
9
10 int(*get_pendown_state)(void);
11 void (*clear_penirq)(void); /* If needed, clear 2nd level
12 interrupt source */
13 int (*init_platform_hw)(void);
14 void (*exit_platform_hw)(void);
15 };
函数get_pendown_state用于运行时获取笔按压状态,也就是获取tsc2007引脚PENIRQ的状态,这个引脚当触摸屏有按压的情况下输出低电平,无按压时输出高电平。
函数init_platform_hw在驱动程序的probe函数内被调用,处理一些硬件相关的初始化。这个初始化主要是针对PENIRQ相连的引脚的初始化。
函数exit_platform_hw在驱动程序exit时调用。
函数clear_penirq发生中断后清除中断
以下是我修改的硬件相关代码
787 #define TSC2007_INT_GPIO S5PV210_GPH2(4)
788 static int tsc2007_hw_init(void)
789 {
790 int err;
791 err=gpio_request(TSC2007_INT_GPIO,"tsc2007 irq");
792 if(err){
793 pr_err("tsc2007 irqgpio request err\n");
794 return err;
795 }
796
797 err=gpio_direction_input(TSC2007_INT_GPIO);
798 if(err){
799 pr_err("tsc2007 irqgpio init input err %d\n",err);
800 gpio_free(TSC2007_INT_GPIO);
801 return err;
802 }
803 s3c_gpio_cfgpin(TSC2007_INT_GPIO,S3C_GPIO_SFN(0x0f));
804 s3c_gpio_setpull(TSC2007_INT_GPIO,S3C_GPIO_PULL_NONE);
805 //writel(readl(S5PV210_GPH2CON)|(0x0f<<16),S5PV210_GPH2CON);
806 printk("tsc2007 gpio initok\n");
807 return 0;
808 }
809
810 static voidtsc2007_hw_remove(void)
811 {
812 s3c_gpio_cfgpin(TSC2007_INT_GPIO,S3C_GPIO_INPUT);
813 gpio_free(TSC2007_INT_GPIO);
814 }
815
816 static inttsc2007_get_pandown_state(void)
817 {
818 int dat;
819 //s3c_gpio_cfgpin(TSC2007_INT)
820 dat=gpio_get_value(TSC2007_INT_GPIO);
821 printk("tsc2007 intpin:%X\n",dat);
822 return (dat==0)?1:0;
823 }
824 static structtsc2007_platform_data tsc2007_data={
825 .model=2007,
826 .x_plate_ohms=180,//这个值看字面意思是x轴电阻,但找不到相关参数,就在网上随便搜了一个,按压力度计算的时候会用到。
827 .init_platform_hw=tsc2007_hw_init,
828 .exit_platform_hw=tsc2007_hw_remove,
829 .get_pendown_state=tsc2007_get_pandown_state,
830 //.clear_penirq
831 };
832
833
834 /* I2C0 */
835 static struct i2c_board_infoi2c_devs0[] __initdata = {
836 #ifdef CONFIG_SND_SOC_WM8580
837 {
838 I2C_BOARD_INFO("wm8580",0x1b),
839 },
840 #endif
841 #ifdef CONFIG_TOUCHSCREEN_TSC2007
842 {
843 I2C_BOARD_INFO("tsc2007",(0x90>>1)),
844 .irq=IRQ_EINT(20),
845 .platform_data=&tsc2007_data,
846 },
847 #endif
848
849 };
在tsc2007.c里面定义一下DEBUG,方便查看调试信息。
接着make,重启开发板。
执行命令echo8 >/proc/sys/kernel/printk修改终端信息输出级别以便可以输出调试信息。
发现按压触摸屏后并没有调用中断例程。
5.修改tsc2007.c代码
316 err = request_irq(ts->irq, tsc2007_irq,IRQF_TRIGGER_FALLING ,
317 client->dev.driver->name, ts);
中断类型原来是0,现在改为IRQF_TRIGGER_FALLING,下降沿触发,因为tsc2007中断输出管线平时输出高电平,有按压时输出低电平。
再make,重启。
这个时候操作触摸屏,终端应该就会有相应的调试信息输出来了。
Ok,成功。如果用的是tslib,那可以设置以下参数进行测试啦。
欢迎高手帮我纠错,谢谢。QQ:12430300。