平台

开发板:tq2440
内核:Linux-4.9
u-boot:u-boot-2015.04
 

概述

之前移植了LCD驱动,下面继续移植触摸屏驱动,然后将tslib也移植上去。

正文

一、移植触摸屏驱动

为了简单起见我们对TQ2440自带的触摸屏驱动进行改写,改成设备树的形式。
1、设备树
触摸屏使用了两个中断,如下:
这两个中断是子中断,隶属于主中断INT_ADC:
关于寄存器,参考芯片手册的第16章,知道了上面的信息,我们就可以得到如下的设备树节点(可以参考博文基于设备树的TQ2440的中断(1)):
tq2440ts@ {
compatible = "tq2440,ts";
reg = <0x58000000 0x100>;
reg-names = "adc_ts_physical";
interrupts = < >, < >;
interrupt-names = "int_ts", "int_adc_s";
clocks = <&clocks PCLK_ADC>;
clock-names = "adc";
}; 
2、驱动
对应的触摸屏驱动是drivers/input/touchscreen/tq2440_ts.c
这部分我已经上传到github上面了,可以使用下面的命令下载:
git clone git@github.com:pengdonglin137/linux-4.9.git -b tq2440_dt 
代码如下:
 /*************************************

 NAME:tq2440_ts.c
COPYRIGHT:www.embedsky.net *************************************/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <asm/io.h>
#include <asm/irq.h> #include <plat/regs-adc.h>
#include <mach/regs-gpio.h> /* For ts.dev.id.version */
#define S3C2410TSVERSION 0x0101 #define WAIT4INT(x) (((x)<<8) | \
S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_XY_PST()) #define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST()) static char *tq2440ts_name = "TQ2440 TouchScreen"; static struct input_dev *idev;
static long xp;
static long yp;
static int count; static void __iomem *base_addr; static void touch_timer_fire(unsigned long data)
{
u32 data0;
u32 data1;
int updown; data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1); updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown) {
if (count != ) {
long tmp; tmp = xp;
xp = yp;
yp = tmp; xp >>= ;
yp >>= ; input_report_abs(idev, ABS_X, xp);
input_report_abs(idev, ABS_Y, yp); input_report_key(idev, BTN_TOUCH, );
input_report_abs(idev, ABS_PRESSURE, );
input_sync(idev);
} xp = ;
yp = ;
count = ; writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
count = ; input_report_key(idev, BTN_TOUCH, );
input_report_abs(idev, ABS_PRESSURE, );
input_sync(idev); writel(WAIT4INT(), base_addr+S3C2410_ADCTSC);
}
} static struct timer_list touch_timer =
TIMER_INITIALIZER(touch_timer_fire, , ); static irqreturn_t stylus_updown(int irq, void *dev_id)
{
u32 data0;
u32 data1;
int updown; data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1); updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); if (updown)
touch_timer_fire(); return IRQ_HANDLED;
} static irqreturn_t stylus_action(int irq, void *dev_id)
{
u32 data0;
u32 data1; data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1); xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
count++; if (count < (<<)) {
writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
mod_timer(&touch_timer, jiffies+);
writel(WAIT4INT(), base_addr+S3C2410_ADCTSC);
} return IRQ_HANDLED;
} static int tq2440ts_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct clk *adc_clock;
struct resource *tsmem, *irq;
struct input_dev *input_dev;
int ret; if (!node) {
dev_dbg(dev, "of_node is NULL\n");
return -EINVAL;
} adc_clock = devm_clk_get(dev, "adc");
dev_dbg(dev, "adc_clock: %p\n", adc_clock);
if (IS_ERR(adc_clock)) {
dev_err(dev, "cannot get clock\n");
return -ENOENT;
}
clk_prepare(adc_clock);
clk_enable(adc_clock); dev_dbg(dev, "get mem\n");
tsmem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "adc_ts_physical");
if (!tsmem) {
dev_dbg(dev, "get mem resource failed.\n");
ret = -EINVAL;
goto err;
} base_addr = devm_ioremap_resource(dev, tsmem);
if (IS_ERR(base_addr)) {
dev_dbg(dev, "ioremap failed.\n");
ret = PTR_ERR(base_addr);
goto err;
} writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);
writel(0xffff, base_addr+S3C2410_ADCDLY);
writel(WAIT4INT(), base_addr+S3C2410_ADCTSC); input_dev = devm_input_allocate_device(dev);
if (!input_dev) {
dev_dbg(dev, "ioremap failed.\n");
ret = -ENOMEM;
goto err;
} idev = input_dev;
idev->evbit[] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); __set_bit(EV_SYN, idev->evbit);
__set_bit(EV_KEY, idev->evbit);
__set_bit(EV_ABS, idev->evbit);
__set_bit(BTN_TOUCH, idev->keybit); input_set_abs_params(idev, ABS_X, , 0x3FF, , );
input_set_abs_params(idev, ABS_Y, , 0x3FF, , );
input_set_abs_params(idev, ABS_PRESSURE, , , , ); idev->name = tq2440ts_name;
idev->id.bustype = BUS_RS232;
idev->id.vendor = 0xDEAD;
idev->id.product = 0xBEEF;
idev->id.version = S3C2410TSVERSION; irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "int_ts");
if (!irq) {
dev_err(dev, "get irq resource int_ts failed.\n");
ret = -EINVAL;
goto err;
}
ret = devm_request_irq(dev, irq->start, stylus_updown, IRQF_ONESHOT, "int_ts", NULL);
if (ret < ){
dev_err(dev, "request irq tsirq %d failed.\n", irq->start);
goto err;
} irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "int_adc_s");
if (!irq) {
dev_err(dev, "get irq resource int_adc_s failed.\n");
ret = -EINVAL;
goto err;
}
ret = devm_request_irq(dev, irq->start, stylus_action, IRQF_ONESHOT, "int_adc_s", NULL);
if (ret < ) {
dev_err(dev, "request irq adcirq %d failed.\n", irq->start);
goto err;
} dev_info(dev, "%s successfully loaded\n", tq2440ts_name);
input_register_device(idev); return ;
err:
clk_disable(adc_clock);
return ret;
} static const struct of_device_id tq2440ts_match[] = {
{ .compatible = "tq2440,ts", .data = (void *) },
{},
}; static struct platform_driver tq2440ts_driver = {
.probe = tq2440ts_probe,
.driver = {
.name = "tq2440ts",
.of_match_table = of_match_ptr(tq2440ts_match),
},
}; static int __init tq2440ts_init(void)
{
return platform_driver_register(&tq2440ts_driver);
} static void __exit tq2440ts_exit(void)
{
platform_driver_unregister(&tq2440ts_driver);
} module_init(tq2440ts_init);
module_exit(tq2440ts_exit); MODULE_LICENSE("GPL");
3、测试
查看中断信息:
[root@tq2440 ]# cat /proc/interrupts
CPU0
: s3c-eint Edge eth0
: s3c Edge s3c2410-rtc tick
: s3c Edge samsung_time_irq
: s3c Edge 4d000000.fb
: s3c Edge ohci_hcd:usb1
: s3c Edge .i2c
: s3c Edge s3c2410-rtc alarm
: s3c-level Level .serial
: s3c-level Level .serial
: s3c-level Edge int_ts
: s3c-level Edge int_adc_s
: s3c-level Edge .watchdog
Err:

使用hexdump /dev/input/event0:

[root@tq2440 ]# hexdump /dev/input/event0
cb74 386e bc0b 000b
cb74 386e bc0b 000b 01e4
cb74 386e bc0b 000b 014a
cb74 386e bc0b 000b
cb74 386e bc0b 000b
cb74 386e 0a4e 000c 01dc
cb74 386e 0a4e 000c 01fa
cb74 386e 0a4e 000c
cb74 386e 585a 000c 014a
cb74 386e 585a 000c

二、移植tslib

参考:
登陆http://www.tslib.org/下载最新的版本:
https://github.com/kergoth/tslib/releases/download/1.10/tslib-1.10.tar.xz
编译安装:
#!/bin/bash

./autogen.sh

mkdir install

./configure  \
--prefix="`pwd`/install" \
--host=arm-linux \
ac_cv_func_malloc_0_nonnull=yes make
make install

安装完成后,可以看到:

$ls install
bin/ etc/ include/ lib/ share/
将这些文件拷贝到开发板上面,然后修改板子上面的/etc/profile文件,添加如下内容:
echo "Set Env for Tslib"
export TSLIB_ROOT=/
export TSLIB_TSDEVICE=/dev/input/event0
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib

修改完成后,重新启动开发板。

三、测试

运行ts_calibrate生成校准数据
[root@tq2440 ]# ts_calibrate
xres = , yres =
Took samples...
Top left : X = Y =
Took samples...
Top right : X = Y =
Took samples...
Bot right : X = Y =
Took samples...
Bot left : X = Y =
Took samples...
Center : X = Y =
582.617065 -0.602301 -0.108929
-72.806641 0.023253 0.396149
Calibration constants: - - -
运行ts_test测试:
[root@tq2440 ]# ts_test
946785862.424089:
946785862.444036:
946785865.264038:
946785865.284058:
946785865.519036:
946785865.539107:
946785865.559054:
946785865.829038:
完。

基于设备树的TQ2440触摸屏驱动移植的更多相关文章

  1. 基于设备树的TQ2440的中断(2)

    下面以按键中断为例看看基于设备数的中断的用法: 设备树: tq2440_key { compatible = "tq2440,key"; interrupt-parent = &l ...

  2. 基于设备树的TQ2440的中断(1)

    作者 姓名:彭东林 E-mail:pengdonglin137@163.com QQ:405728433 平台 板子:TQ2440 内核:Linux-4.9 u-boot: 2015.04 工具链: ...

  3. 基于设备树的TQ2440 DMA学习(3)—— DMA控制器驱动

    作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.9 概述 上一篇直接操作DMA控制器实现了一个mem2mem的DMA传输,但是这样不符合linux driv ...

  4. 基于设备树的TQ2440 DMA学习(4)—— client驱动

    作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.9 概述 前面分析了DMA控制器驱动,下面我们调用DMAENGINE的API写一个MEM2MEM的驱动 正文 ...

  5. 基于设备树的TQ2440 DMA学习(1)—— 芯片手册

    作者 彭东林pengdonglin137@163.com 平台 TQ2440内核Linux4.9 概述 一直想抽时间学习一下DMA驱动,今天就以S3C2440为例,这款芯片的DMA控制器足够简单,也比 ...

  6. 基于设备树的TQ2440 DMA学习(2)—— 简单的DMA传输

    作者 彭东林 pengdonglin137@163.com   平台 TQ2440 Linux-4.9   概述 上一篇博客分析了DMA控制器的寄存器,循序渐进,下面我们直接操作DMA控制器的寄存器实 ...

  7. 基于设备树的controller学习(2)

    作者 彭东林 pengdonglin137@163.com 平台 TQ2440 Linux-4.10.17 概述 上一篇大概介绍了一下demo-controller的结构,下面结合驱动分析.   正文 ...

  8. 基于设备树的controller学习(1)

    作者 彭东林pengdonglin137@163.com 平台 TQ2440Linux-4.10.17 概述 在设备树中我们经常见到诸如"#clock-cells"."# ...

  9. 基于设备树的led驱动程序

    #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include ...

随机推荐

  1. windows下nodejs服务器的安装与配置

    1下载安装 download from the link: https://nodejs.org/en/ windows下的安装直接运行exe,略过-- 注:由于用户权限的问题,最好将nodejs安装 ...

  2. 解决“tar:Exiting with failure status due to previous errors”【转】

    问题: 当我想试着用tar命令来创建一个压缩文件时,总在执行过程中失败,并且抛出一个错误说明"tar:由于前一个错误导致于失败状态中退出"("Exiting with f ...

  3. HTML5 drawImage性能问题

    最近做游戏发现,为了节省HTTP请求,把很多组动画放到了一张图片上,也就是传说中的雪碧图,但是用drawImage从图片上截取一部分绘制在canvas上时会非常慢. 我的图片尺寸为5000*7000 ...

  4. sonarLint--强大的代码审查工具(插件)

    idea也有的一个插件 贴上一个eclipse的sonarlint用法 http://blog.csdn.net/limm33/article/details/51166840 不过听说从2015年1 ...

  5. 5 个 Laravel Eloquent 小技巧

    1. 快速生成 Model & Migration 这并不是一个很多人知道的小技巧,为文章生成 Model 和 Migration. $ php artisan make:migration ...

  6. 标签流 VS 脚本流

    搞过点前端,玩过几个框架之后,基本都会发现框架在设计上的一些套路和流派,今天给大家扒一扒其中的两个书写流派“标签流”和“脚本流” 我们以一个button按钮为例: 这样裸写HTML标签的方式基本没法儿 ...

  7. Grinder搭建小记与Nduja(这次不待续了)

    Grinder是比较有名的浏览器FUZZ框架,采用ruby语言编写,主要是作为测试框架来使用,在<白帽子讲浏览器安全>一书中作者使用了Nduja生成测试样本来配合Grinder使用.根据网 ...

  8. ps -aux与ps -ef

    ps -aux与ps -ef这两个命令显示的结果是差不多的. 不同之处就是显示风格不同,前者是BSD风格,后者SYSTEM V(其实我不太明白这尼玛风格是什么跟什么,我看起来都差不多啊) 然后重要的不 ...

  9. P2651 添加括号III

    P2651 添加括号III无论怎么添加,a2一定是分母,其他的可以是分子,所以最后看看,(a1*a3*..*an)%a2==0即可 #include<iostream> #include& ...

  10. jQuery选择器(转)

    原文:http://www.cnblogs.com/qinwang913/p/3444135.html 一.基本分类 jQuery选择器大致可以分为两类,基本选择器和过滤选择器,总体结构体系如下:   ...