S3C2410触摸屏驱动代码分析1

时间:2022-08-05 12:28:06

/*

* s3c2410-ts.c

*

* touchScreen driver for SAMSUNG S3C2410

*

* Author: Janghoon Lyu <nandy@mizi.com>

* Date : $Date: 2002/06/04 07:11:00 $

*

* $Revision: 1.1.2.6 $

*

* Based on pt036001b-ts.c

*

* This file is subject to the terms and conditions of the GNU General Public

* License. See the file COPYING in the main directory of this archive

* for more details.

*

* History:

*

* 2002-05-27: Janghoon Lyu <nandy@mizi.com>

* - Add HOOK_FOR_DRAG

* - PM鍐呴潧鍟?鐢哥虎鍟?涔愬彉 绐嶇槫鐖?鎶涜兌椋?鐧荤槫 鑷肩柦婢?

*

*/

#include <linux/config.h>

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

#include <linux/miscdevice.h>

#include <linux/sched.h>

#include <linux/delay.h>

#include <linux/poll.h>

#include <linux/spinlock.h>

#include <linux/irq.h>

#include <linux/delay.h>

#include <asm/hardware.h>

#ifdef CONFIG_PM

#include <linux/pm.h>

#endif

/* debug macros */

#undef DEBUG

#ifdef DEBUG

#define DPRINTK( x... ) printk("s3c2410-ts: " ##x)

#else

#define DPRINTK( x... )

#endif

//定义触摸屏笔的状态,其中PEN_UP为笔抬起状态

// PEN_DOWN

为笔按下状态

//

PEN_FLEETING为笔滑动状态

#define PEN_UP 0

#define PEN_DOWN 1

#define PEN_FLEETING 2

/*定义环形缓冲区的大小,环形缓冲区主要用来保存

应用程序来不及处理的触摸屏动作*/

#define MAX_TS_BUF 16 /* how many do we want to buffer */

#undef USE_ASYNC 1

#define DEVICE_NAME "s3c2410-ts"

#define TSRAW_MINOR 1

typedef struct {

//定义笔的状态

unsigned int penStatus; /* PEN_UP, PEN_DOWN, PEN_SAMPLE */

TS_RET buf[MAX_TS_BUF]; /* protect against overrun */

/*定义可以保存16个事件的环形缓冲区,其每个元素类型为:

typedef struct {

//压力,这里被定义为触摸笔动作,即

//上面定义的PEN_UP/PEN_DOWN/PEN_FLEETING三种

unsigned short pressure;

//横坐标的采样值

unsigned short x;

//纵坐标的采样值

unsigned short y;

//pad是填充位,这个成员是为了保证整个结构体的大小

//4字节整数倍而使用的

unsigned short pad;

} TS_RET;

*/

unsigned int head, tail; /* head and tail for queued events */

/*

headtail用于指向环形缓冲区的头和尾

*/

wait_queue_head_t wq;

/*Linux内核的等待队列是以双循环链表为基础数据结构,与进程调度机制紧密结合,能够用于

实现核心的异步事件通知机制。在Linux2.4.21中,等待队列在源代码树include/linux/wait.h中,

这是一个通过list_head连接的典型双循环链表,如下图所示。

*/

spinlock_t lock;

/*

定义一把自旋锁。在linux内核中,锁有两种类型,一个是自旋锁,另外是读写锁自旋

锁最多只能被一个可执行线程持有。

自旋锁不会引起调用者睡眠,如果一个执行线程试图获得一个已经被持有的自旋锁,那

么线程就会一直进行忙循环,一直等待下去,在那里看是否该自旋锁的保持者已经释放了锁,

"自旋"一词就是因此而得名。 由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而

不是睡眠是非常必要的,自旋锁的效率远高于互斥锁

*/

#ifdef USE_ASYNC

struct fasync_struct *aq;

#endif

#ifdef CONFIG_PM

struct pm_dev *pm_dev;

#endif

} TS_DEV;

static TS_DEV tsdev;

/*定义触摸屏设备变量tsdev,该全局变量用于处理一触摸屏相关事务*/

#define BUF_HEAD (tsdev.buf[tsdev.head])

#define BUF_TAIL (tsdev.buf[tsdev.tail])

#define INCBUF(x,mod) ((++(x)) & ((mod) - 1))

static int tsMajor = 0;

static void (*tsEvent)(void);

#define HOOK_FOR_DRAG

#ifdef HOOK_FOR_DRAG

#define TS_TIMER_DELAY (HZ/100) /* 10 ms */

static struct timer_list ts_timer;

#endif

#define wait_down_int() { ADCTSC = DOWN_INT | XP_PULL_UP_EN | \

XP_AIN | XM_HIZ | YP_AIN | YM_GND | \

XP_PST(WAIT_INT_MODE); }

/*设置触摸屏处于等待中断模式,笔处于抬起状态,等待笔按下

*/

#define wait_up_int() { ADCTSC = UP_INT | XP_PULL_UP_EN | XP_AIN | XM_HIZ | \

YP_AIN | YM_GND | XP_PST(WAIT_INT_MODE); }

/*设置触摸屏处于等待中断模式,笔处于按下状态,等待笔抬起

*/

#define mode_x_axis() { ADCTSC = XP_EXTVLT | XM_GND | YP_AIN | YM_HIZ | \

XP_PULL_UP_DIS | XP_PST(X_AXIS_MODE); }

/*X坐标进行测量*/