rk29: modify screen.h

This commit is contained in:
hhb 2011-03-23 17:36:16 +08:00
parent c479a969c5
commit 3ea1f96dc7
12 changed files with 1590 additions and 16 deletions

View File

@ -0,0 +1 @@
obj-y += tslib.o variance.o dejitter.o

View File

@ -0,0 +1,137 @@
/*
* tslib/dejitter.c
*
* Copyright (C) 2001 Russell King.
*
* This file is placed under the LGPL. Please see the file
* COPYING for more details.
*
*
* Problem: some touchscreens read the X/Y values from ADC with a
* great level of noise in their lowest bits. This produces "jitter"
* in touchscreen output, e.g. even if we hold the stylus still,
* we get a great deal of X/Y coordinate pairs that are close enough
* but not equal. Also if we try to draw a straight line in a painter
* program, we'll get a line full of spikes.
*
* Solution: we apply a smoothing filter on the last several values
* thus excluding spikes from output. If we detect a substantial change
* in coordinates, we reset the backlog of pen positions, thus avoiding
* smoothing coordinates that are not supposed to be smoothed. This
* supposes all noise has been filtered by the lower-level filter,
* e.g. by the "variance" module.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/device.h>
//#include <asm/typedef.h>
#include <mach/iomux.h>
#include <asm/uaccess.h>
#include <asm/types.h>
#include <asm/io.h>
#include <asm/delay.h>
#include "tslib.h"
//#define DEBUG
/**
* This filter works as follows: we keep track of latest N samples,
* and average them with certain weights. The oldest samples have the
* least weight and the most recent samples have the most weight.
* This helps remove the jitter and at the same time doesn't influence
* responsivity because for each input sample we generate one output
* sample; pen movement becomes just somehow more smooth.
*/
/* To keep things simple (avoiding division) we ensure that
* SUM(weight) = power-of-two. Also we must know how to approximate
* measurements when we have less than NR_SAMPHISTLEN samples.
*/
static const unsigned char weight [NR_SAMPHISTLEN - 1][NR_SAMPHISTLEN + 1] =
{
/* The last element is pow2(SUM(0..3)) */
{ 5, 3, 0, 0, 3 }, /* When we have 2 samples ... */
{ 8, 5, 3, 0, 4 }, /* When we have 3 samples ... */
{ 6, 4, 3, 3, 4 }, /* When we have 4 samples ... */
};
static void average (struct tslib_dejitter *djt, struct ts_sample *samp)
{
const unsigned char *w;
int sn = djt->head;
int i, x = 0, y = 0;
//unsigned int p = 0;
w = weight [djt->nr - 2];
for (i = 0; i < djt->nr; i++) {
x += djt->hist [sn].x * w [i];
y += djt->hist [sn].y * w [i];
//p += djt->hist [sn].p * w [i];
sn = (sn - 1) & (NR_SAMPHISTLEN - 1);
}
samp->x = x >> w [NR_SAMPHISTLEN];
samp->y = y >> w [NR_SAMPHISTLEN];
//samp->pressure = p >> w [NR_SAMPHISTLEN];
#ifdef DEBUG
printk("DEJITTER----------------> %d %d %d\n",
samp->x, samp->y, samp->pressure);
#endif
}
int dejitter_read(struct tslib_info *info, struct ts_sample *samp, int nr)
{
struct tslib_dejitter *djt = info->djt;
struct ts_sample *s;
int count = 0, ret;
ret = variance_read(info, samp, nr);
for (s = samp; ret > 0; s++, ret--) {
if (s->pressure == 0) {
/*
* Pen was released. Reset the state and
* forget all history events.
*/
djt->nr = 0;
samp [count++] = *s;
continue;
}
/* If the pen moves too fast, reset the backlog. */
if (djt->nr) {
int prev = (djt->head - 1) & (NR_SAMPHISTLEN - 1);
if (sqr(s->x - djt->hist [prev].x) +
sqr(s->y - djt->hist [prev].y) > djt->delta) {
#ifdef DEBUG
printk("DEJITTER: pen movement exceeds threshold\n");
#endif
djt->nr = 0;
}
}
djt->hist[djt->head].x = s->x;
djt->hist[djt->head].y = s->y;
djt->hist[djt->head].p = s->pressure;
if (djt->nr < NR_SAMPHISTLEN)
djt->nr++;
/* We'll pass through the very first sample since
* we can't average it (no history yet).
*/
if (djt->nr == 1)
samp [count] = *s;
else {
average (djt, samp + count);
}
count++;
djt->head = (djt->head + 1) & (NR_SAMPHISTLEN - 1);
}
return count;
}

View File

@ -0,0 +1,71 @@
/*
* tslib/tslib.c
*
* This file is placed under the LGPL. Please see the file
* COPYING for more details.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/device.h>
//#include <asm/typedef.h>
#include <mach/iomux.h>
#include <asm/uaccess.h>
#include <asm/types.h>
#include <asm/io.h>
#include <asm/delay.h>
#include "tslib.h"
struct tslib_info *g_tslib_inf = NULL;
int sqr(int x)
{
return x * x;
}
int tslib_init(struct tslib_info *info, void *raw_read)
{
struct tslib_info *tslib_inf = info;
struct tslib_variance *var = NULL;
struct tslib_dejitter *djt = NULL;
if(raw_read == NULL)
return -1;
memset(tslib_inf, 0, sizeof(struct tslib_info));
var = kmalloc(sizeof(struct tslib_variance), GFP_KERNEL);
if (var == NULL)
goto failed1;
memset(var, 0, sizeof(struct tslib_variance));
djt = kmalloc(sizeof(struct tslib_dejitter), GFP_KERNEL);
if (djt == NULL)
goto failed2;
memset(djt, 0, sizeof(struct tslib_dejitter));
var->flags = 0;
var->delta = sqr(VARIANCE_DELTA);
djt->head = 0;
djt->delta = sqr(DEJITTER_DELTA);
tslib_inf->raw_read = raw_read;
tslib_inf->var = var;
tslib_inf->djt = djt;
g_tslib_inf = tslib_inf;
return 0;
failed2:
kfree(var);
failed1:
return -1;
}

View File

@ -0,0 +1,62 @@
#ifndef _TSLIB_H_
#define _TSLIB_H_
/*
* tslib/tslib.h
*
* Copyright (C) 2001 Russell King.
*
* This file is placed under the LGPL.
*
*
* Touch screen library interface definitions.
*/
#define NR_SAMPHISTLEN 4
#define VARIANCE_DELTA 10
#define DEJITTER_DELTA 100
struct ts_sample {
int x;
int y;
unsigned int pressure;
};
struct tslib_variance {
int delta;
struct ts_sample last;
struct ts_sample noise;
unsigned int flags;
};
struct ts_hist {
int x;
int y;
unsigned int p;
};
struct tslib_dejitter {
int delta;
int x;
int y;
int down;
int nr;
int head;
struct ts_hist hist[NR_SAMPHISTLEN];
};
struct tslib_info {
int (*raw_read)(struct tslib_info *info, struct ts_sample *samp, int nr);
struct tslib_variance *var;
struct tslib_dejitter *djt;
};
int sqr(int x);
int tslib_init(struct tslib_info *info, void *raw_read);
void variance_clear(struct tslib_info *info);
int variance_read(struct tslib_info *info, struct ts_sample *samp, int nr);
int dejitter_read(struct tslib_info *info, struct ts_sample *samp, int nr);
#endif /* _TSLIB_H_ */

View File

@ -0,0 +1,138 @@
/*
* tslib/variance.c
*
* Copyright (C) 2001 Russell King.
*
* This file is placed under the LGPL. Please see the file
* COPYING for more details.
*
*
* Variance filter for touchscreen values.
*
* Problem: some touchscreens are sampled very roughly, thus even if
* you hold the pen still, the samples can differ, sometimes substantially.
* The worst happens when electric noise during sampling causes the result
* to be substantially different from the real pen position; this causes
* the mouse cursor to suddenly "jump" and then return back.
*
* Solution: delay sampled data by one timeslot. If we see that the last
* sample read differs too much, we mark it as "suspicious". If next sample
* read is close to the sample before the "suspicious", the suspicious sample
* is dropped, otherwise we consider that a quick pen movement is in progress
* and pass through both the "suspicious" sample and the sample after it.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/device.h>
//#include <asm/typedef.h>
#include <mach/iomux.h>
#include <asm/uaccess.h>
#include <asm/types.h>
#include <asm/io.h>
#include <asm/delay.h>
#include "tslib.h"
//#define DEBUG
#define VAR_PENDOWN 0x00000001
#define VAR_LASTVALID 0x00000002
#define VAR_NOISEVALID 0x00000004
#define VAR_SUBMITNOISE 0x00000008
void variance_clear(struct tslib_info *info)
{
struct ts_sample cur;
struct tslib_variance *var = info->var;
cur.pressure = 0;
/* Flush the queue immediately when the pen is just
* released, otherwise the previous layer will
* get the pen up notification too late. This
* will happen if info->next->ops->read() blocks.
*/
if (var->flags & VAR_PENDOWN) {
var->flags |= VAR_SUBMITNOISE;
var->noise = cur;
}
/* Reset the state machine on pen up events. */
var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
var->noise = cur;
var->last = cur;
return;
}
int variance_read(struct tslib_info *info, struct ts_sample *samp, int nr)
{
struct tslib_variance *var = info->var;
struct ts_sample cur;
int count = 0, dist;
while (count < nr) {
if (var->flags & VAR_SUBMITNOISE) {
cur = var->noise;
var->flags &= ~VAR_SUBMITNOISE;
} else {
if (info->raw_read(info, &cur, 1) < 1)
return count;
}
if (cur.pressure == 0) {
/* Flush the queue immediately when the pen is just
* released, otherwise the previous layer will
* get the pen up notification too late. This
* will happen if info->next->ops->read() blocks.
*/
if (var->flags & VAR_PENDOWN) {
var->flags |= VAR_SUBMITNOISE;
var->noise = cur;
}
/* Reset the state machine on pen up events. */
var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID);
goto acceptsample;
} else
var->flags |= VAR_PENDOWN;
if (!(var->flags & VAR_LASTVALID)) {
var->last = cur;
var->flags |= VAR_LASTVALID;
continue;
}
if (var->flags & VAR_PENDOWN) {
/* Compute the distance between last sample and current */
dist = sqr(cur.x - var->last.x) +
sqr(cur.y - var->last.y);
if (dist > var->delta) {
/* Do we suspect the previous sample was a noise? */
if (var->flags & VAR_NOISEVALID) {
/* Two "noises": it's just a quick pen movement */
samp [count++] = var->last = var->noise;
var->flags = (var->flags & ~VAR_NOISEVALID) |
VAR_SUBMITNOISE;
} else
var->flags |= VAR_NOISEVALID;
/* The pen jumped too far, maybe it's a noise ... */
var->noise = cur;
continue;
} else
var->flags &= ~VAR_NOISEVALID;
}
acceptsample:
#ifdef DEBUG
printk("VARIANCE----------------> %d %d %d\n",
var->last.x, var->last.y, var->last.pressure);
#endif
samp [count++] = var->last;
var->last = cur;
}
return count;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,66 @@
/*
* drivers/input/touchscreen/xpt2046_ts.h
*
* Copyright (C) 2010 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __DRIVERS_TOUCHSCREEN_XPT2046_TS_H
#define __DRIVERS_TOUCHSCREEN_XPT2046_TS_H
#define IOMUX_NAME_SIZE 20
enum xpt2046_filter {
XPT2046_FILTER_OK,
XPT2046_FILTER_REPEAT,
XPT2046_FILTER_IGNORE,
};
struct xpt2046_platform_data {
u16 model; /* 2046. */
bool keep_vref_on; /* set to keep vref on for differential
* measurements as well */
bool swap_xy; /* swap x and y axes */
/* If set to non-zero, after samples are taken this delay is applied
* and penirq is rechecked, to help avoid false events. This value
* is affected by the material used to build the touch layer.
*/
u16 penirq_recheck_delay_usecs;
u16 x_min, x_max;
u16 y_min, y_max;
u16 debounce_max; /* max number of additional readings
* per sample */
u16 debounce_tol; /* tolerance used for filtering */
u16 debounce_rep; /* additional consecutive good readings
* required after the first two */
int gpio_pendown; /* the GPIO used to decide the pendown
* state if get_pendown_state == NULL
*/
char pendown_iomux_name[IOMUX_NAME_SIZE];
int pendown_iomux_mode;
int touch_ad_top;
int touch_ad_bottom;
int touch_ad_left;
int touch_ad_right;
int touch_virtualkey_length;
int (*get_pendown_state)(void);
int (*filter_init) (struct xpt2046_platform_data *pdata,
void **filter_data);
int (*filter) (void *filter_data, int data_idx, int *val);
void (*filter_cleanup)(void *filter_data);
void (*wait_for_sync)(void);
int (* io_init)(void);
int (* io_deinit)(void);
};
#endif

View File

@ -107,7 +107,7 @@ int lcd_init(void)
/* set lcd to sleep mode or not */
int lcd_standby(u32 enable)
int lcd_standby(u8 enable)
{
mcu_ioctl(MCU_SETBYPASS, 1);
@ -124,7 +124,7 @@ int lcd_standby(u32 enable)
/* set lcd to write memory mode, so the lcdc of RK29xx can send the fb content to the lcd internal ram in hold mode*/
int lcd_refresh(u32 arg)
int lcd_refresh(u8 arg)
{
mcu_ioctl(MCU_SETBYPASS, 1);
@ -162,7 +162,7 @@ int lcd_refresh(u32 arg)
/* not used */
int lcd_scandir(u32 dir)
int lcd_scandir(u16 dir)
{
mcu_ioctl(MCU_SETBYPASS, 1);
@ -175,7 +175,7 @@ int lcd_scandir(u32 dir)
/* not used */
int lcd_disparea(u32 area)
int lcd_disparea(u8 area)
{
mcu_ioctl(MCU_SETBYPASS, 1);
mcu_ioctl(MCU_SETBYPASS, 0);

View File

@ -50,7 +50,7 @@
static struct rk29lcd_info *gLcd_info = NULL;
int lcd_init(void);
int lcd_standby(u32 enable);
int lcd_standby(u8 enable);
/*
#define RXD_PORT RK2818_PIN_PB7
#define TXD_PORT RK2818_PIN_PB6 //gLcd_info->txd_pin
@ -319,7 +319,7 @@ int lcd_init(void)
return 0;
}
int lcd_standby(u32 enable) //***enable =1 means suspend, 0 means resume
int lcd_standby(u8 enable) //***enable =1 means suspend, 0 means resume
{
if(gLcd_info)

View File

@ -422,7 +422,7 @@ int lcd_init(void)
/* set lcd to sleep mode or not */
int lcd_standby(u32 enable)
int lcd_standby(u8 enable)
{
mcu_ioctl(MCU_SETBYPASS, 1);
@ -441,7 +441,7 @@ int lcd_standby(u32 enable)
/* set lcd to write memory mode, so the lcdc of RK29xx can send the fb content to the lcd internal ram in hold mode*/
int lcd_refresh(u32 arg)
int lcd_refresh(u8 arg)
{
mcu_ioctl(MCU_SETBYPASS, 1);
@ -479,7 +479,7 @@ int lcd_refresh(u32 arg)
/* not used */
int lcd_scandir(u32 dir)
int lcd_scandir(u16 dir)
{
mcu_ioctl(MCU_SETBYPASS, 1);
@ -492,7 +492,7 @@ int lcd_scandir(u32 dir)
/* not used */
int lcd_disparea(u32 area)
int lcd_disparea(u8 area)
{
mcu_ioctl(MCU_SETBYPASS, 1);
mcu_ioctl(MCU_SETBYPASS, 0);

View File

@ -114,7 +114,7 @@
static struct rk29lcd_info *gLcd_info = NULL;
int lcd_init(void);
int lcd_standby(u32 enable);
int lcd_standby(u8 enable);
/* spi write a data frame,type mean command or data */
@ -475,7 +475,7 @@ int lcd_init(void)
return 0;
}
int lcd_standby(u32 enable)
int lcd_standby(u8 enable)
{
if(gLcd_info)
gLcd_info->io_init();

View File

@ -77,10 +77,10 @@ struct rk29fb_screen {
/* Operation function*/
int (*init)(void);
int (*standby)(u32 enable);
int (*refresh)(u32 arg);
int (*scandir)(u32 dir);
int (*disparea)(u32 area);
int (*standby)(u8 enable);
int (*refresh)(u8 arg);
int (*scandir)(u16 dir);
int (*disparea)(u8 area);
};