平台

开发板: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. 纯js遍历json获取值动态为select添加option

    遍历json数组 并动态为select添加option 直接上代码,重要部分有注解 <!DOCTYPE html> <html lang="en"> < ...

  2. Coursera台大机器学习技法课程笔记13-Deep Learning

    深度学习面临的问题和现在解决的办法: 简要来说,分两步使用DL:初始化时一层一层的选择权重,而后再进行训练: 那么怎么做pre-training,即怎么选择权重呢?好的权重能够不改变原有资料的信息,即 ...

  3. .NET Core 项目经验总结:项目结构介绍 (一)

    原文地址(个人博客):http://www.gitblogs.com/Blogs/Details?id=384b4249-15e4-41bf-9cf7-44a3e1e51885 作为一个.NET We ...

  4. android:怎么实现一个控件与另一个指定控件左对齐

    https://segmentfault.com/q/1010000003905460?_ea=425861 针对你这种情况,最简单的一种办法是,设置两个TextView的宽度为固定值,且相等. Li ...

  5. 【AtCoder】AGC030

    A - Poisonous Cookies 有毒还吃,有毒吧 #include <bits/stdc++.h> #define fi first #define se second #de ...

  6. java 报错英文

    —————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流! —————————— 第一章:JDK(Java Development Kit) java开发工具包 J ...

  7. 阿里云 rds python sdk不支持python3处理

    阿里云文档中心的python版本aliyun-python-sdk-rds不支持python3处理 问题:默认情况下文档中心的python版本只支持python2,不兼容python3版本 需要稍微修 ...

  8. Redis高可用之主从复制实践(四)

    0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...

  9. Android-Start方式和Bind方式混合开启Service

    Android-Start方式和Bind方式混合开启Service 需求如下 需要开发一个音乐APP,需要满足以下的需求: 当退出所有的Activity后仍然能够播放音乐 能够控制音乐的播放比如说,暂 ...

  10. KVM源代码框架

    自己通过看代码总结的内核中包含kvm的文件夹: (1)Linux-3.17.4\Documentation\virtual\kvm\ (2)Linux-3.17.4\include\ (3)Linux ...