#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/uaccess.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/wait.h> #include <linux/poll.h> #include <linux/mm.h> #include <linux/dma-mapping.h> #include <linux/device.h> #include <linux/miscdevice.h> #include <linux/platform_device.h> #include <linux/sound.h> #include <linux/delay.h> #include <linux/input.h> #include <linux/clk.h>
#include <asm/thread_info.h> #include <asm/io.h>
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); |