summaryrefslogtreecommitdiff
path: root/packages/linux/linux-ezx/ezx_ts.patch
diff options
context:
space:
mode:
authorMichael Lauer <mickey@vanille-media.de>2006-05-11 17:23:44 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2006-05-11 17:23:44 +0000
commit844bf825c75c21864c1ba911642d58021e08e9ed (patch)
treea4fc24b7330cd955c23787749f4cf751bf35dc57 /packages/linux/linux-ezx/ezx_ts.patch
parent2222e629a6bf3ebaafce55cfd533486ec9926887 (diff)
add first stab at support for the Motorola A780 GSM phone
NOTE: for now, we use a dedicated linux-ezx kernel, but once this proves working, we will probably unify with linux-openzaurus
Diffstat (limited to 'packages/linux/linux-ezx/ezx_ts.patch')
-rw-r--r--packages/linux/linux-ezx/ezx_ts.patch1026
1 files changed, 1026 insertions, 0 deletions
diff --git a/packages/linux/linux-ezx/ezx_ts.patch b/packages/linux/linux-ezx/ezx_ts.patch
new file mode 100644
index 0000000000..41339dcf52
--- /dev/null
+++ b/packages/linux/linux-ezx/ezx_ts.patch
@@ -0,0 +1,1026 @@
+Index: linux-2.6.16.5-ezx/drivers/input/touchscreen/Kconfig
+===================================================================
+--- linux-2.6.16.5-ezx.orig/drivers/input/touchscreen/Kconfig 2006-04-12 17:27:57.000000000 -0300
++++ linux-2.6.16.5-ezx/drivers/input/touchscreen/Kconfig 2006-04-24 22:40:00.000000000 -0300
+@@ -108,4 +108,16 @@
+ To compile this driver as a module, choose M here: the
+ module will be called hp680_ts_input.
+
++config TOUCHSCREEN_EZX
++ tristate "Motorola EZX (via PCAP2) touchscreen"
++ depends on EZX
++ help
++ Say Y here if you have a Motorola EZX (E680, A780) telephone
++ and want to support the built-in touchscreen.
++
++ If unsure, say N.
++
++ To compile this driver as a module, choose M here: the
++ module will be called hp680_ts_input.
++
+ endif
+Index: linux-2.6.16.5-ezx/drivers/input/touchscreen/Makefile
+===================================================================
+--- linux-2.6.16.5-ezx.orig/drivers/input/touchscreen/Makefile 2006-04-12 17:27:57.000000000 -0300
++++ linux-2.6.16.5-ezx/drivers/input/touchscreen/Makefile 2006-04-24 22:40:15.000000000 -0300
+@@ -12,3 +12,4 @@
+ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
+ obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
++obj-$(CONFIG_TOUCHSCREEN_EZX) += ezx.o
+Index: linux-2.6.16.5-ezx/drivers/input/touchscreen/ezx.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.16.5-ezx/drivers/input/touchscreen/ezx.c 2006-04-24 22:52:20.000000000 -0300
+@@ -0,0 +1,991 @@
++/*
++ * linux/drivers/char/ezx-ts.c
++ *
++ * Copyright (C) 2002 Lili Jiang, All Rights Reserved.
++ *
++ *
++ * June, 2002 Lili Jiang, create
++ */
++
++#if 0
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++#include <linux/smp.h>
++#include <linux/smp_lock.h>
++#include <linux/sched.h>
++#include <linux/completion.h>
++#include <linux/string.h>
++#include <linux/pm.h>
++#include <linux/config.h>
++#include <linux/fb.h>
++
++#include <asm/semaphore.h>
++#include <asm/hardware.h>
++#include <asm/arch/irqs.h>
++#include <linux/timex.h>
++#include <linux/interrupt.h>
++
++#include <asm/arch/pxa-regs.h>
++
++#include "ezx-ts.h"
++#include "ssp_pcap.h"
++
++#define DEBUG 0 /*change it when formal release*/
++#if DEBUG
++# define TS_DPRINTK(s...) printk(s)
++#else
++# define TS_DPRINTK(s...)
++#endif
++
++/*
++ * This structure is nonsense - millisecs is not very useful
++ * since the field size is too small. Also, we SHOULD NOT
++ * be exposing jiffies to user space directly.
++ */
++struct ts_event {
++ u16 pressure;
++ u16 x;
++ u16 y;
++ u16 pad;
++// struct timeval stamp;
++};
++
++static struct timer_list ezx_ts_penup_timer;
++
++static struct irqaction ezx_ts_custom_timer_irq = {
++ name: "ezx_ts_custom_timer",
++};
++
++static u8 bSetPenupTimer = 0;
++static u8 bFirstPen = 0;
++//static unsigned long penCurJiffies = 0;
++static unsigned int penSampleCount = 0;
++static u32 tspenSampleCount = 0;
++static u32 tsDiscardDataCount = 0;
++
++typedef enum
++{
++ PRESSURE,
++ COORDINATE
++}EZX_TS_READ_STATE;
++
++EZX_TS_READ_STATE ezx_ts_read_state = PRESSURE;
++
++#define TS_NR_EVENTS 128
++/*250 //pay attention to that haed and tail is defined as u8*/
++
++#define TS_EDGE_MIN_LIMIT (0) /* 10 */
++#define TS_EDGE_MAX_LIMIT (1023)
++
++/* jiffies : 10ms, pen shake 50ms????? */
++//#define EZX_TS_READ_MIN_SPACE 10 /*100//5*/
++//#define EZX_TS_PENUP_TIMEOUT_MS 8
++
++#define EZX_TS_PENSAMPLE_TIMEOUT_MS 2
++ //8,6
++//#define EZX_TS_HWR_TIMEOUT_MS 2
++
++#define QT_ONEPEN_SAMPLES_NUM 1
++ //3,5
++//#define HWR_ONEPEN_SAMPLES_NUM 1
++
++#define CUSTOM_ONEPEN_SAMPLES_NUM 1
++#define EZX_TS_CUSTOM_TIMEOUT_MS 12
++ //15ms
++#define X_DIFF 85
++#define Y_DIFF 75
++#define MIN_X_HOLD 5
++#define MIN_Y_HOLD 4
++#define SAMPLE_COUNT_NOT_JUMPER 20
++
++typedef enum
++{
++ EZX_PEN_NORMAL,
++ EZX_PEN_CUSTOM
++}EZX_TS_PEN_STYLE;
++
++static EZX_TS_PEN_STYLE gPenStyle = EZX_PEN_NORMAL;
++static u8 gPenSamplesNum = QT_ONEPEN_SAMPLES_NUM;
++//static u32 gHwrTimer = EZX_TS_HWR_TIMEOUT_MS;
++static u32 gCustomTimer = EZX_TS_CUSTOM_TIMEOUT_MS;
++static u8 getPenUp = 0;
++
++struct ezx_ts_info {
++ /*struct ucb1x00 *ucb;*/
++ struct fasync_struct *fasync;
++ wait_queue_head_t read_wait;
++
++ /*
++ struct semaphore irq_wait;
++ struct semaphore sem;
++ struct completion init_exit;
++ struct task_struct *rtask;
++ */
++ u16 x_cur; /*store the current pen value read from ADC*/
++ u16 y_cur; /*store the current pen value read from ADC */
++ u16 cur_pressure;
++ u16 x_pre;
++ u16 y_pre;
++ u8 evt_head;
++ u8 evt_tail;
++ struct ts_event events[TS_NR_EVENTS]; /* buffer for store pen data*/
++/*
++ int restart:1;
++ int adcsync:1;
++
++#ifdef CONFIG_PM
++ struct pm_dev *pmdev;
++#endif
++*/
++};
++
++static struct ezx_ts_info ezxts;
++
++#define EZX_TS_SHAKE_SAMPLES 3
++static u8 ezx_ts_shake_samples_count = 0;
++static struct ts_event ezx_ts_shake_samples[EZX_TS_SHAKE_SAMPLES];
++
++static int ezx_ts_init(void);
++static void ezx_ts_exit(void);
++static int ezx_ts_open(struct inode *inode, struct file * filp);
++static int ezx_ts_release(struct inode *inode, struct file *filp);
++static ssize_t ezx_ts_read(struct file* filp, char* buffer, size_t count, loff_t *ppos);
++static unsigned int ezx_ts_poll(struct file* filp, struct poll_table_struct * wait);
++static int ezx_ts_fasync(int fd, struct file* filp, int mode);
++
++/* internal function */
++static void ezx_ts_init_penEvent(void);
++static void ezx_ts_pen_touch_handler(void);
++static void ezx_ts_penup_timeout(unsigned long data);
++static void ezx_ts_set_timer(struct timer_list *timer, void (*timer_timeout)(unsigned long), signed long timeout);
++static void ezx_ts_check_pen_samples(void);
++static void ezx_ts_evt_add(u16 pressure, u16 x, u16 y);
++static struct ts_event ezx_ts_get_onedata(void);
++
++/* for setup ezx ts self timer,begin */
++static void ezx_ts_custom_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ TS_DPRINTK("ezx_ts_custom_timer_interrupt entered.jiffies: %d\n@@@\n", jiffies);
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++
++ /* clear this timer */
++ OIER &= ~OIER_E3;
++ OSSR = OSSR_M3; /* Clear match on timer 2 */
++}
++
++static void ezx_ts_custom_setup_timer()
++{
++ ezx_ts_custom_timer_irq.handler = ezx_ts_custom_timer_interrupt;
++ setup_irq(IRQ_OST3, &ezx_ts_custom_timer_irq);
++}
++
++
++static void ezx_ts_custom_timer_start(void)
++{
++ OIER |= OIER_E3;
++ //OSMR2 = OSCR + sleep_limit * LATCH; //OSCR: 0x40A00010
++ OSMR3 = OSCR + (gCustomTimer * HZ * LATCH) /1000;
++}
++
++static void ezx_ts_custom_timer_stop(void)
++{
++ OIER &= ~OIER_E3;
++ OSSR = OSSR_M3; /* Clear match on timer 2 */
++}
++
++/* for setup ezx ts self timer, end */
++
++
++static void ezx_ts_init_penEvent(void)
++{
++ int i;
++
++ ezxts.x_cur = 0;
++ ezxts.y_cur = 0;
++ ezxts.x_pre = 0;
++ ezxts.y_pre = 0;
++ ezxts.cur_pressure = PEN_UP;
++
++ for (i = 0; i < TS_NR_EVENTS; i++)
++ {
++ ezxts.events[i].pressure=(u16)0;
++ ezxts.events[i].x=(u16)0;
++ ezxts.events[i].y=(u16)0;
++ ezxts.events[i].pad=(u16)0;
++ }
++ ezxts.evt_head = 0;
++ ezxts.evt_tail = 0;
++
++ gPenStyle = EZX_PEN_NORMAL;
++ gPenSamplesNum = QT_ONEPEN_SAMPLES_NUM;
++ //gHwrTimer = EZX_TS_HWR_TIMEOUT_MS;
++ gCustomTimer = EZX_TS_CUSTOM_TIMEOUT_MS;
++}
++
++
++static void ezx_ts_pen_touch_handler(void)
++{
++ SSP_PCAP_TSI_mode_set(PCAP_TS_PRESSURE_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ ezx_ts_read_state = PRESSURE;
++ ezxts.x_pre = 0;
++ ezxts.y_pre = 0;
++
++ TS_DPRINTK("ezx_ts pen touch handler done.\n");
++}
++
++static void ezx_ts_penup_timeout(unsigned long data)
++{
++ TS_DPRINTK("@@@\nIn pen drag! jiffies: %d\n@@@\n", jiffies);
++ bSetPenupTimer = 0;
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++}
++
++static void ezx_ts_check_pen_samples(void)
++{
++ if ( (ezx_ts_read_state == COORDINATE) && (penSampleCount != 0 ) )
++ {
++ int k;
++ if (penSampleCount < gPenSamplesNum)
++ {
++ for ( k = 0; k < (gPenSamplesNum - penSampleCount); k++)
++ {
++ ezx_ts_evt_add(PEN_DOWN, ezxts.x_cur, ezxts.y_cur);
++ TS_DPRINTK("ezx_ts_add_additional_samples: %d\n", k);
++ }
++ }
++ TS_DPRINTK("ezx_ts_evt_add: PEN_UP\n");
++ //ezx_ts_evt_add(PEN_UP, 0, 0);
++ }
++
++ if (bSetPenupTimer)
++ {
++ del_timer(&ezx_ts_penup_timer);
++ bSetPenupTimer = 0;
++ TS_DPRINTK("^^^^Delete penup timer1.\n");
++ }
++ penSampleCount = 0;
++}
++
++static void ezx_ts_set_timer(struct timer_list *timer, void (*timer_timeout)(unsigned long),
++ signed long timeout)
++{
++ init_timer(timer);
++ timer->expires = timeout + jiffies;
++ timer->data = (unsigned long) current;
++ timer->function = timer_timeout;
++
++ add_timer(timer);
++ //TS_DPRINTK("ezx_ts set timer done.\n");
++}
++
++static void ezx_ts_evt_add(u16 pressure, u16 x, u16 y)
++{
++ int next_head;
++ int last_head;
++ /* if pen_up, then copy pressure=0, last_evt.x y to current evt*/
++
++ next_head = ezxts.evt_head + 1;
++ if (next_head == TS_NR_EVENTS)
++ {
++ next_head = 0;
++ }
++
++ last_head = ezxts.evt_head - 1;
++ if (last_head == -1)
++ {
++ last_head = TS_NR_EVENTS - 1;
++ }
++
++/* if (next_head != ezxts.evt_tail)*/
++ //{
++ if ( pressure == PEN_DOWN)
++ {
++/* if ( (penSampleCount >1) && ((penCurJiffies + EZX_TS_READ_MIN_SPACE) < jiffies))
++ {
++ // see two ~ four data or just ignore the data except the first one????
++ return;
++ }
++ else*/
++ //{
++ ezxts.events[ezxts.evt_head].pressure = pressure;
++ ezxts.events[ezxts.evt_head].x = x;
++ ezxts.events[ezxts.evt_head].y = y;
++ TS_DPRINTK("ezx_store: x: %d, y :%d, pressure: 0x%x\n", x, y, pressure);
++ //}
++ }
++ else
++ {
++ ezxts.events[ezxts.evt_head].pressure = pressure;
++ ezxts.events[ezxts.evt_head].x = ezxts.events[last_head].x;
++ ezxts.events[ezxts.evt_head].y = ezxts.events[last_head].y;
++ TS_DPRINTK("ezx_store: PEN_UP\n");
++ }
++ //}
++// do_gettimeofday(&(ezxts.events[ezxts.evt_head].stamp));
++ ezxts.evt_head = next_head;
++
++ if (ezxts.evt_head == ezxts.evt_tail)
++ {
++ if ( ++ezxts.evt_tail == TS_NR_EVENTS )
++ ezxts.evt_tail = 0;
++ }
++
++ if (ezxts.fasync)
++ kill_fasync(&ezxts.fasync, SIGIO, POLL_IN);
++ wake_up_interruptible(&ezxts.read_wait);
++}
++
++static struct ts_event ezx_ts_get_onedata(void)
++{
++ int cur = ezxts.evt_tail;
++
++ if (++ezxts.evt_tail == TS_NR_EVENTS)
++ ezxts.evt_tail = 0;
++
++ return ezxts.events[cur];
++}
++
++/*****************************************************************************
++ * FUNCTION NAME : ezx_ts_open()
++ *
++ * INPUTS:
++ *
++ * OUTPUTS: pen info from ts event structure
++ *
++ * VALUE RETURNED: none
++ *
++ * DESCRIPTION:
++ * i) Increase this device module used count.
++ * ii) Initialize a buffer for store data read from touch screen interface.
++ * iii) Initialize touch screen interface hardware.
++ * iv) Setup touch screen wait queue.
++*****************************************************************************
++ */
++static int ezx_ts_open(struct inode *inode, struct file * filp)
++{
++ struct ezx_ts_info *ts = &ezxts;
++
++/* ssp_pcap_init(); // change to _start_kernel
++ ssp_pcap_open(); */
++ ssp_pcap_open(SSP_PCAP_TS_OPEN);
++ SSP_PCAP_bit_clean( SSP_PCAP_ADJ_BIT_MSR_TSM);
++
++ ezx_ts_init_penEvent();
++ filp->private_data = ts;
++
++
++ TS_DPRINTK("ezx touch screen driver opened\n");
++ return 0;
++}
++
++/* Decrease this device module used count. */
++static int ezx_ts_release(struct inode *inode, struct file *filp)
++{
++ ezx_ts_init_penEvent();
++ ezx_ts_fasync(-1, filp, 0);
++
++ TS_DPRINTK("ezx touch screen driver closed\n");
++ return 0;
++}
++
++/*****************************************************************************
++ * FUNCTION NAME : ezx_ts_read
++ *
++ * INPUTS:
++ *
++ * OUTPUTS: pen info from ts event structure
++ *
++ * VALUE RETURNED: none
++ *
++ * DESCRIPTION:
++ * This is used for UI app to call.
++ * If device is opened by nonblock mode then copy available data from the ts event buffer
++ * to user buffer and return the actual read data count, if device is opened by block mode
++ * and no data available then sleep until the required data count be read completed.
++ *
++ * CAUTIONS:
++ *
++ *
++ *****************************************************************************
++ */
++static ssize_t ezx_ts_read(struct file* filp, char* buffer, size_t count, loff_t *ppos)
++{
++ DECLARE_WAITQUEUE(wait, current);
++
++ struct ezx_ts_info *ts = filp->private_data;
++ char *ptr = buffer;
++ int err = 0;
++ struct ts_event evt;
++
++ add_wait_queue(&ts->read_wait, &wait);
++ while (count >= sizeof(struct ts_event))
++ {
++ err = -ERESTARTSYS;
++ if (signal_pending(current))
++ break;
++ if ((ts)->evt_head != (ts)->evt_tail)
++ {
++ evt = ezx_ts_get_onedata(); /*evt_tail pos changed in this func*/
++ err = copy_to_user(ptr, &evt, sizeof(struct ts_event));
++
++ if (err)
++ break;
++ //printk("ezx_ts_read: x:%d, y:%d, pressure:0x%x\n", evt.x, evt.y, evt.pressure);
++ ptr += sizeof(struct ts_event);
++ count -= sizeof(struct ts_event);
++ continue;
++ }
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ err = -EAGAIN;
++ if (filp->f_flags & O_NONBLOCK)
++ break;
++ schedule();
++ }
++ current->state = TASK_RUNNING;
++ remove_wait_queue(&(ts->read_wait), &wait);
++
++ return ptr == buffer ? err : ptr - buffer;
++
++}
++
++/*
++This function is used in nonblock mode to determine whether it can read data from touch screen
++device without blocking.
++Call poll_wait to wait until read operation status changed then return POLLIN (flag of device can be
++read without blocking) | POLLRDNORM (flag of data is available) bit mask if there is readable data
++now.
++*/
++
++static unsigned int ezx_ts_poll(struct file* filp, struct poll_table_struct * wait)
++{
++ struct ezx_ts_info *ts = filp->private_data;
++ int ret = 0;
++
++ if ( ts != NULL)
++ {
++ TS_DPRINTK("ezx_ts_poll.\n");
++ poll_wait(filp, &ts->read_wait, wait);
++ if (ts->evt_head != ts->evt_tail)
++ {
++ TS_DPRINTK("ezx_ts_poll: ts->evt_head != ts->evt_tail\n");
++ ret = POLLIN | POLLRDNORM;
++ }
++ }
++
++ return ret;
++}
++
++/* Setup fasync queue for touch screen device. */
++
++static int ezx_ts_fasync(int fd, struct file* filp, int mode)
++{
++ struct ezx_ts_info *ts = filp->private_data;
++
++ if ( ts != NULL)
++ {
++ TS_DPRINTK("ezx_ts_fasync.\n");
++ return fasync_helper(fd, filp, mode, &ts->fasync);
++ }
++ else return 0;
++}
++
++static int
++ezx_ts_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
++{
++ int res = 0;
++
++ TS_DPRINTK("ezx_ts_ioctl: arg is %d\n", arg);
++ switch (cmd) {
++/*
++ case SETTONORMAL:
++ TS_DPRINTK("ezx_ts_ioctl_test: This is SETTONORMAL.\n");
++ gPenStyle = EZX_PEN_NORMAL;
++ gPenSamplesNum = QT_ONEPEN_SAMPLES_NUM;
++ //gHwrTimer = EZX_TS_HWR_TIMEOUT_MS;
++ gCustomTimer = EZX_TS_CUSTOM_TIMEOUT_MS;
++ break;
++
++ case SETTOHWR:
++ TS_DPRINTK("ezx_ts_ioctl_test: This is SETTOHWR.\n");
++ gPenStyle = EZX_PEN_HWR;
++ gPenSamplesNum = HWR_ONEPEN_SAMPLES_NUM;
++ if ( (arg > 0 ) && (arg < 100) )
++ {
++ gHwrTimer = arg;
++ TS_DPRINTK("ezx_ts_ioctl_test: gHwrTimer is %d.\n", gHwrTimer);
++ }
++ break;
++
++ case SETTOCUSTOM:
++ TS_DPRINTK("ezx_ts_ioctl_test: This is SETTOCUSTOM.\n");
++ gPenStyle = EZX_PEN_CUSTOM;
++ gPenSamplesNum = CUSTOM_ONEPEN_SAMPLES_NUM;
++ if ( (arg > 0 ) && (arg < 100) )
++ {
++ gCustomTimer = arg;
++ TS_DPRINTK("ezx_ts_ioctl_test: gCustomTimer is %d.\n", gCustomTimer);
++ }
++ break;
++ case GETPENSTYLE:
++ TS_DPRINTK("ezx_ts_ioctl_test: This is GETPENSTYLE.\n");
++ put_user(gPenStyle, (u32*)arg);
++ break;
++ default:
++ res = -EINVAL;
++*/
++ }
++
++ return res;
++}
++
++/*****************************************************************************
++ * FUNCTION NAME : ezx_ts_touch_interrupt
++ *
++ * INPUTS:
++ *
++ *
++ * OUTPUTS:
++ *
++ *
++ * VALUE RETURNED:
++ *
++ *
++ * DESCRIPTION:
++ * This is touch screen touch interrupt service routine called by PCAP module when touch screen
++ * interrupt happened. First eliminate shake signal to get stable touch screen press information.
++ * Then write instruction to PCAP register to read ADC conversion value of pressed spot x,y coordinate
++ * and return.
++ *
++ * CAUTIONS:
++ *
++ *
++ *
++ *****************************************************************************
++ */
++void ezx_ts_touch_interrupt(int irq, void* dev_id, struct pt_regs *regs)
++{
++ TS_DPRINTK("ezx_ts_touch_irq happened.\n");
++ ezx_ts_shake_samples_count = 0;
++ //TS_DPRINTK("ezx_ts_touch_irq excuted.\n");
++ ezx_ts_check_pen_samples();
++ ezx_ts_pen_touch_handler();
++
++}
++
++/*****************************************************************************
++ * FUNCTION NAME : ezx_ts_dataReadok_interrupt
++ *
++ * INPUTS: call PCAP API to read x,y
++ *
++ * OUTPUTS: Store the pen info to ts event structure
++ *
++ * VALUE RETURNED: none
++ *
++ * DESCRIPTION:
++ * This is called by PCAP module to deal with the touch screen press raw information read from ADC
++ * when ADC data conversion finished. It performs write the data to ts event buffer for user to
++ * read out.
++ *
++ * CAUTIONS: Consider pen shake
++ *
++ *
++ *****************************************************************************
++ */
++void ezx_ts_dataReadok_interrupt(int irq, void* dev_id, struct pt_regs *regs)
++{
++ static u16 pressure;
++ u16 x;
++ u16 y;
++ U16 tempx,tempy;
++
++ if (SSP_PCAP_TSI_get_XY_value(&x, &y) != SSP_PCAP_SUCCESS)
++ {
++ return;
++ }
++ /* convert x,y???? */
++ // TS_DPRINTK( "ezx_ts_get_XY_value: x:%d, y:%d\n",x, y);
++ /* TS_DPRINTK( "\nezx_ts before convert: x:%d, y:%d\n",x, y);*/
++
++ if ( ezx_ts_read_state == PRESSURE)
++ {
++ if (( y >= TS_EDGE_MAX_LIMIT ) || (y <= TS_EDGE_MIN_LIMIT))
++ {
++ TS_DPRINTK("ezx_ts_datareadok_irq: PEN_UP.\n");
++ pressure = PEN_UP;
++ ezxts.cur_pressure = PEN_UP;
++
++ /*ezx_ts_check_pen_samples();*/
++ if ( getPenUp == 0 )
++ {
++ ezx_ts_evt_add( pressure, 0, 0);
++ }
++ SSP_PCAP_bit_clean( SSP_PCAP_ADJ_BIT_MSR_TSM);
++ return;
++ }
++ else
++ {
++ TS_DPRINTK("ezx_ts_datareadok_irq: PEN_DOWN.\n");
++ getPenUp = 0;
++ pressure = PEN_DOWN;
++ ezxts.cur_pressure = PEN_DOWN;
++ tspenSampleCount = 0;
++ ezxts.x_pre = 0;
++ ezxts.y_pre = 0;
++ bFirstPen = 1 ;
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ ezx_ts_read_state = COORDINATE;
++
++ //TS_DPRINTK("ezx_ts_datareadok_irq: Begin read XY.\n");
++ return;
++ }
++ }
++ else if ( ezx_ts_read_state == COORDINATE)
++ {/*
++ u8 count;
++
++ count = 0;
++ while ( (( x <= TS_EDGE_MIN_LIMIT)||( x >= TS_EDGE_MAX_LIMIT) ||
++ ( y <= TS_EDGE_MIN_LIMIT)||( y >= TS_EDGE_MAX_LIMIT))
++ && (count++ < 15) )
++ {
++ SSP_PCAP_bit_clean( SSP_PCAP_ADJ_BIT_MSR_TSM);
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ }
++ */
++ if ( ( x <= TS_EDGE_MIN_LIMIT)||( x >= TS_EDGE_MAX_LIMIT) ||
++ ( y <= TS_EDGE_MIN_LIMIT)||( y >= TS_EDGE_MAX_LIMIT) )
++ { /* regard it as PEN_UP */
++ pressure = PEN_UP;
++ ezxts.cur_pressure = PEN_UP;
++ x = 0;
++ y = 0;
++ tspenSampleCount = 0;
++ SSP_PCAP_bit_clean( SSP_PCAP_ADJ_BIT_MSR_TSM);
++ /*del_timer(&ezx_ts_read_timer);*/
++ ezx_ts_check_pen_samples();
++ ezx_ts_evt_add( pressure, 0, 0);
++ /* SSP_PCAP_bit_clean( SSP_PCAP_ADJ_BIT_MSR_TSM);*/
++ ezx_ts_read_state = PRESSURE;
++ getPenUp = 1;
++ TS_DPRINTK( "ezx_ts Invalid x,y position: PEN_UP?\n");
++ return;
++ }
++ getPenUp = 0;
++ penSampleCount++;
++ //TS_DPRINTK("ezx_ts_datareadok_irq: Begin store XY %d.\n", penSampleCount);
++
++ if ( gPenStyle == EZX_PEN_CUSTOM )
++ {
++ if ( ((ezxts.x_pre == 0) && (ezxts.y_pre == 0))
++ || ( (ezxts.x_pre != 0) && (ezxts.y_pre != 0)
++ &&(!((abs(ezxts.x_pre - x) > X_DIFF) || (abs(ezxts.y_pre - y) > Y_DIFF))) )
++ )
++ {
++ //TS_DPRINTK("ezx_ts_datareadok_irq: diff <= XY_DIFF.\n");
++
++ ezxts.x_pre = x;
++ ezxts.y_pre = y;
++
++ TS_DPRINTK("ezx_ts_datareadok_irq:x_pre=%d,y_pre=%d\n", ezxts.x_pre, ezxts.y_pre);
++ ezxts.x_cur = x;
++ ezxts.y_cur = y;
++ ezx_ts_evt_add(pressure, ezxts.x_cur, ezxts.y_cur);
++ //printk("ezx_ts_datareadok_irq_custom add pressure0x%x,x_cur%d,y_cur%d\n",pressure,ezxts.x_cur,ezxts.y_cur);
++ ezx_ts_custom_timer_start();
++ }
++ else
++ {
++ //TS_DPRINTK("ezx_ts_datareadok_irq: DIFF > XY_DIFF\n");
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ TS_DPRINTK("ezx_ts_datareadok_irq:x_pre=%d,y_pre=%d, x=%d,y=%d\n", ezxts.x_pre, ezxts.y_pre,x,y);
++ }
++
++
++ /*
++ if ( ezx_ts_shake_samples_count < EZX_TS_SHAKE_SAMPLES )
++ {
++ ezx_ts_shake_samples[ezx_ts_shake_samples_count].x = x;
++ ezx_ts_shake_samples[ezx_ts_shake_samples_count].y = y;
++ ezx_ts_shake_samples[ezx_ts_shake_samples_count++].pressure = PEN_DOWN;
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ TS_DPRINTK("ezx_ts_read_shake_samples%d:x=%d,y=%d\n", ezx_ts_shake_samples_count,x,y);
++ }
++ if (ezx_ts_shake_samples_count >= EZX_TS_SHAKE_SAMPLES)
++ {
++ if ( (abs(ezx_ts_shake_samples[0].x - ezx_ts_shake_samples[1].x) > X_DIFF) ||
++ (abs(ezx_ts_shake_samples[0].y - ezx_ts_shake_samples[1].y) > Y_DIFF) ||
++ (abs(ezx_ts_shake_samples[1].x - ezx_ts_shake_samples[2].x) > X_DIFF) ||
++ (abs(ezx_ts_shake_samples[1].y - ezx_ts_shake_samples[2].y) > Y_DIFF)
++ )
++ {
++ // throw these data and re-read
++ ezx_ts_shake_samples_count = 0;
++ }
++ else //save to ts_event queue
++ {
++ ezxts.x_pre = ezxts.x_cur;
++ ezxts.y_pre = ezxts.y_cur;
++ TS_DPRINTK("ezx_ts_datareadok_irq:x_pre=%d,y_pre=%d\n", ezxts.x_pre, ezxts.y_pre);
++ ezxts.x_cur = (ezx_ts_shake_samples[0].x + ezx_ts_shake_samples[1].x + ezx_ts_shake_samples[2].x) / 3;
++ ezxts.y_cur = (ezx_ts_shake_samples[0].y + ezx_ts_shake_samples[1].y + ezx_ts_shake_samples[2].y) / 3;;
++ ezx_ts_shake_samples_count = 0;
++ ezx_ts_evt_add(pressure, ezxts.x_cur, ezxts.y_cur);
++ }
++ ezx_ts_custom_timer_start();
++ }
++ */
++ }
++ else
++ {
++ /* ezxts.x_pre and ezxts.y_pre store the last position */
++ tspenSampleCount ++;
++ if(1 == tspenSampleCount)
++ {
++ ezxts.x_cur = x;
++ ezxts.y_cur = y;
++ if( 0 == bSetPenupTimer )
++ {
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ }
++ }
++ else if (2 == tspenSampleCount)
++ {
++ tspenSampleCount = 0;
++
++ tempx = (ezxts.x_cur > x? ezxts.x_cur - x:x - ezxts.x_cur);
++ tempy = (ezxts.y_cur > y? ezxts.y_cur - y:y - ezxts.y_cur);
++ if(tempx <= X_DIFF && tempy <= Y_DIFF )
++ {
++ x = (x+ezxts.x_cur)/2;
++ y = (y+ezxts.y_cur)/2;
++ if( 1 == bFirstPen)
++ {
++ bFirstPen = 0;
++ ezxts.x_pre = x;
++ ezxts.y_pre = y;
++ }
++ tempx = ( ezxts.x_pre > x? ezxts.x_pre -x:x - ezxts.x_pre);
++ tempy = ( ezxts.y_pre > y? ezxts.y_pre -y:y - ezxts.y_pre);
++ if(tempx <= X_DIFF && tempy <= Y_DIFF )
++ {
++ tsDiscardDataCount = 0;
++ if(tempx > MIN_X_HOLD || tempy > MIN_Y_HOLD)
++ {
++ ezxts.x_pre = x;
++ ezxts.y_pre = y;
++ }
++ ezx_ts_evt_add(pressure, ezxts.x_pre, ezxts.y_pre);
++ if ( bSetPenupTimer == 0 )
++ {
++ ezx_ts_set_timer(&ezx_ts_penup_timer, ezx_ts_penup_timeout,
++ EZX_TS_PENSAMPLE_TIMEOUT_MS);
++ TS_DPRINTK("ezx_ts_datareadok_irq: set timer pen sample\n");
++ bSetPenupTimer = 1;
++ }
++ }
++ else
++ {
++
++ tsDiscardDataCount ++;
++ if(tsDiscardDataCount > SAMPLE_COUNT_NOT_JUMPER)
++ {
++ tsDiscardDataCount = 0;
++ ezxts.x_pre = x;
++ ezxts.y_pre = y;
++ ezx_ts_evt_add(pressure, ezxts.x_pre, ezxts.y_pre);
++ if ( bSetPenupTimer == 0 )
++ {
++ ezx_ts_set_timer(&ezx_ts_penup_timer, ezx_ts_penup_timeout,
++ EZX_TS_PENSAMPLE_TIMEOUT_MS);
++ TS_DPRINTK("ezx_ts_datareadok_irq: set timer pen sample\n");
++ bSetPenupTimer = 1;
++ }
++ }
++ else if( 0 == bSetPenupTimer )
++ {
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ }
++ }
++ }
++ else
++ {
++ if( 0 == bSetPenupTimer )
++ {
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ }
++ }
++ }
++ else /* discard the case */
++ {
++ tspenSampleCount = 0;
++ if( 0 == bSetPenupTimer )
++ {
++ SSP_PCAP_TSI_mode_set(PCAP_TS_POSITION_XY_MEASUREMENT);
++ SSP_PCAP_TSI_start_XY_read();
++ }
++ }
++ }
++ /*if (penSampleCount >= gPenSamplesNum)
++ {
++ penSampleCount = 0;
++ }*/
++ //TS_DPRINTK("ezx_ts_datareadok_irq: read XY finished.\n");
++ }
++
++}
++
++
++static struct file_operations ezx_ts_fops = {
++ .owner = THIS_MODULE,
++ .read = ezx_ts_read,
++ .poll = ezx_ts_poll,
++ .open = ezx_ts_open,
++ .release = ezx_ts_release,
++ .fasync = ezx_ts_fasync,
++ .ioctl = ezx_ts_ioctl,
++};
++
++/*
++ * miscdevice structure for misc driver registration.
++ */
++static struct miscdevice ezx_ts_dev =
++{
++ .minor = EZX_TS_MINOR_ID,
++ .name = "ezx_ts",
++ .fops = &ezx_ts_fops,
++};
++
++
++/*Register touch screen device in misc devices.*/
++static int ezx_ts_init(void)
++{
++ int ret;
++
++ init_waitqueue_head(&ezxts.read_wait);
++ ret = misc_register(&ezx_ts_dev);
++
++ if (ret<0)
++ {
++ printk("ezx_ts_dev: failed to registering the device\n");
++ }
++ ezx_ts_custom_setup_timer();
++
++ TS_DPRINTK("ezx_ts_init done.\n");
++ return ret;
++}
++
++/*Unregister touch screen device.*/
++static void ezx_ts_exit(void)
++{
++
++ if (bSetPenupTimer)
++ {
++ del_timer(&ezx_ts_penup_timer);
++ bSetPenupTimer = 0;
++ }
++
++ ezx_ts_custom_timer_stop();
++
++ misc_deregister(&ezx_ts_dev);
++
++ TS_DPRINTK("ezx touch screen driver removed\n");
++}
++
++module_init(ezx_ts_init);
++module_exit(ezx_ts_exit);
++
++MODULE_DESCRIPTION("ezx touchscreen driver");
++MODULE_LICENSE("GPL");
++
++#endif
++
++static int __init ezxts_probe(struct platform_device *pdev)
++{
++ struct ezx_ts *ezx_ts;
++ struct input_dev *input_dev;
++ int err = -ENOMEM;
++
++ ezx_ts = kzalloc(sizeof(struct ezx_ts), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!ezx_ts || !input_dev)
++ goto fail;
++
++ platform_set_drvdata(pdev, ezx_ts);
++
++ ...;
++
++ input_dev->name = "EZX PCAP2 Touchscreen";
++ input_dev->phys = "ezxts/input0";
++ input_dev->id.bustype = BUS_HOST;
++ input_dev->id.vendor = 0x0001;
++ input_dev->id.product = 0x0002;
++ input_dev->id.version = 0x0100;
++ input_dev->cdev.dev = &pdev->dev;
++ input_dev->private = ezx_ts;
++
++ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
++ input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0,);
++ input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0,);
++
++ ...;
++
++ input_register_device(ezx_ts->input);
++
++ return 0;
++
++fail:
++ input_free_device(input_dev);
++ kfree(ezx_ts);
++
++ return err;
++}
++
++static int ezxts_remove(struct platform_device *pdev)
++{
++ struct ezx_ts *ezx_ts = platform_get_drvdata(pdev);
++
++ input_unregister_device(ezx_ts->input);
++ kfree(ezx_ts);
++
++ return 0;
++}
++
++static struct platform_driver ezxts_driver = {
++ .probe = ezxts_probe,
++ .remove = ezxts_remove,
++ .suspend = ezxts_suspend,
++ .resume = ezxts_resume,
++ .driver = {
++ .name = "ezx-ts",
++ },
++};
++
++static int __devinit ezxts_init(void)
++{
++ return platform_driver_register(&ezxts_driver);
++}
++
++static void __exit ezxts_exit(void)
++{
++ platform_driver_unregister(&ezxts_driver);
++}
++
++MODULE_DESCRIPTION("Motorola EZX / PCAP2 touchscreen driver");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Harald Welte <laforge@open-ezx.org>");