平台

开发板: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. PHP中冒号、endif、endwhile、endfor使用介绍

    我们经常在wordpress一类博客程序的模板里面看到很多奇怪的PHP语法,比如: 复制代码代码如下: <?php if(empty($GET_['a'])): ?> <font c ...

  2. 001_软件waf

    一.优秀的软件waf开源软件 <1>openwaf介绍  http://www.oschina.net/p/openwaf http://git.oschina.net/miracleqi ...

  3. jquery easyui:tab自动加载第一个tab内容

    $('#resourceTabs').tabs('unselect', 0);$('#resourceTabs').tabs('select', 0);

  4. iOS 中 h5 页面 iframe 调用高度自扩展问题及解决

    开发需求需要在 h5 中用 iframe 中调用一个其他公司开发的 html 页面. 简单的插入 <iframe /> 并设置宽高后,发现在 Android 手机浏览器上打开可以正常运行, ...

  5. NodeJS学习:环境变量

    简介 环境变量(environment variables) 不属于 NodeJS 范畴,它是操作系统用于设定执行环境的参数.会在程序运行时传递给应用程序. NodeJS 获取环境变量,是通过 glo ...

  6. .NetCore 使用 Linq 动态拼接Expression表达式条件来实现 对EF、EF Core 扩展查询排序操作

    相信在使用EF的时候对查询条件或者排序上的处理令人心烦,下面我们就来动态拼接表达式解决这一问题 当我们在查询中使用Where的时候可以看到如下参数 下面我们就来扩展 Expression<Fun ...

  7. 自定义yum源

    1.创建rpm包的存放目录 mkdir  -p   /yum/yum-sum/package 2.准备rpm包,可以通过自带yum只下载不安装工具下载 yum install --downloadon ...

  8. JS的异步模式

    JS的异步模式:1.回调函数:2.事件监听:3.观察者模式:4.promise对象 JavaScript语言将任务的执行模式可以分成两种:同步(Synchronous)和异步(Asychronous) ...

  9. 使用Sublime Text 3的HTML-CSS-JS Prettify插件格式化代码

    很多时候,我们想要格式化HTML-CSS-JS代码,网站上有很多实现此功能的小工具,当然,我的网站首页也有.但是,如果我们的代码编辑器上面也有这样的功能,那不是更加快速便捷?So,接下来,我们看看Su ...

  10. P1508 Likecloud-吃、吃、吃 DP

    题目背景 问世间,青春期为何物? 答曰:“甲亢,甲亢,再甲亢:挨饿,挨饿,再挨饿!” 题目描述 正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中.某日上课,正当他饿得头昏 ...