/*
* 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 */
/*
head和tail用于指向环形缓冲区的头和尾
*/
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坐标进行测量*/