#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("bzli");
struct touch_screen {
struct input_dev *input;
char *name;
struct timer_list tm;
int interval;
struct clk *ts_clk;
unsigned long adccon, adctsc, adcdly,
adcdat0, adcdat1, adcupdn,
adcclrint, adcclrintpndnup;
void (*wait4down)(struct touch_screen *);
void (*wait4up)(struct touch_screen *);
void (*auto_pst)(struct touch_screen *);
irqreturn_t (*ts_handle)(int , struct touch_screen);
int (*get_x)(struct touch_screen *);
int (*get_y)(struct touch_screen *);
void (*timer_handle)(struct touch_screen *);
};
void s3c6410_ts_wait4down(struct touch_screen *t)
{
iowrite32(3 | (1 << 4) | (1 << 6) | (1 << 7),
t->adctsc);
}
void s3c6410_ts_wait4up(struct touch_screen *t)
{
iowrite32(3 | (1 << 4) | (1 << 6) | (1 << 7)
| (1 << 8), t->adctsc);
}
void s3c6410_ts_auto_pst(struct touch_screen *t)
{
iowrite32( 1 << 2, t->adctsc);
iowrite32( 1 | (17 << 6) | ( 1 << 14) | ( 1 << 16),
t->adccon);
}
irqreturn_t s3c6410_ts_handle(int irq, struct touch_screen *t)
{
if (irq == IRQ_TC) {
int temp;
temp = ioread32(t->adcupdn);
if (temp & 1) { //down
t->auto_pst(t);
iowrite32(temp & ~1, t->adcupdn);
t->tm.expires = jiffies +
t->interval;
add_timer(&t->tm);
//--------------------------
input_event(t->input,
EV_ABS, ABS_PRESSURE, 1);
} else if (temp & (1 << 1)) { //up
input_event(t->input,
EV_ABS, ABS_PRESSURE, 0);
input_event(t->input, EV_SYN, 0, 0);
//--------------------------
t->wait4down(t);
iowrite32(temp & ~(1 << 1),
t->adcupdn);
del_timer(&t->tm);
}
iowrite32(0, t->adcclrintpndnup);
} else if (irq == IRQ_ADC) {
int x, y;
x = t->get_x(t);
y = t->get_y(t);
input_event(t->input, EV_ABS, ABS_X, x);
input_event(t->input, EV_ABS, ABS_Y, y);
input_event(t->input, EV_SYN, 0, 0);
t->wait4up(t);
iowrite32(0, t->adcclrint);
}
return IRQ_HANDLED;
}
int s3c6410_ts_get_x(struct touch_screen *t)
{
return (ioread32(t->adcdat0) & 0xfff);
}
int s3c6410_ts_get_y(struct touch_screen *t)
{
return (ioread32(t->adcdat1) & 0xfff);
}
void s3c6410_ts_timer_handle(struct touch_screen *t)
{
t->auto_pst(t);
t->tm.expires = jiffies + t->interval;
add_timer(&t->tm);
}
struct touch_screen s3c6410_ts;
int init_touch_screen(struct touch_screen *t)
{
int ret = 0;
t->name = "s3c6410 touch screen";
t->adccon = ioremap(0x7E00B000, SZ_4K);
t->adctsc = t->adccon + 0x04;
t->adcdly = t->adccon + 0x08;
t->adcdat0 = t->adccon + 0x0c;
t->adcdat1 = t->adccon + 0x10;
t->adcupdn = t->adccon + 0x14;
t->adcclrint = t->adccon + 0x18;
t->adcclrintpndnup = t->adccon + 0x20;
t->wait4down = s3c6410_ts_wait4down;
t->wait4up = s3c6410_ts_wait4up;
t->auto_pst = s3c6410_ts_auto_pst;
t->ts_handle = s3c6410_ts_handle;
t->get_x = s3c6410_ts_get_x;
t->get_y = s3c6410_ts_get_y;
t->timer_handle = s3c6410_ts_timer_handle;
t->interval = (HZ >> 2);
init_timer(&t->tm);
t->tm.function = t->timer_handle;
t->tm.data = t;
t->ts_clk = clk_get(NULL, "adc");
clk_enable(t->ts_clk);
//--------------------------------------------------------
t->input = input_allocate_device();
t->input->name = t->name;
t->input->evbit[0] = BIT(EV_ABS) | BIT(EV_SYN);
input_set_abs_params(t->input, ABS_X, 0, 0xfff,
0, 0);
input_set_abs_params(t->input, ABS_Y, 0, 0xfff,
0, 0);
input_set_abs_params(t->input, ABS_PRESSURE, 0,
1, 0, 0);
//-------------------------------------------------------
request_irq(IRQ_TC, t->ts_handle, 0, t->name, t);
request_irq(IRQ_ADC, t->ts_handle, 0, t->name, t);
return ret;
}
void destroy_touch_screen(struct touch_screen *t)
{
clk_disable(t->ts_clk);
clk_put(t->ts_clk);
free_irq(IRQ_ADC, t);
free_irq(IRQ_TC, t);
iounmap(t->adccon);
input_free_device(t->input);
}
int ts_probe(struct platform_device *dev)
{
int ret = 0;
init_touch_screen(&s3c6410_ts);
input_register_device(s3c6410_ts.input);
//----------------
s3c6410_ts.wait4down(&s3c6410_ts);
return ret;
}
int ts_remove(struct platform_device *dev)
{
int ret = 0;
input_unregister_device(s3c6410_ts.input);
destroy_touch_screen(&s3c6410_ts);
return ret;
}
void ts_device_release(struct device *dev)
{
}
struct platform_device ts_device = {
.name = "6410_ts",
.dev = {
.release = ts_device_release,
},
};
struct platform_driver ts_driver = {
.probe = ts_probe,
.remove = ts_remove,
.driver = {
.name = "6410_ts",
},
};
int test_init(void)
{
int ret = 0;
platform_device_register(&ts_device);
platform_driver_register(&ts_driver);
return 0;
}
void test_exit(void)
{
platform_device_unregister(&ts_device);
platform_driver_unregister(&ts_driver);
}
module_init(test_init);
module_exit(test_exit);