#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhanglong");
struct touchscreen {
unsigned long adccon,
adctsc,
adcdly,
adcdat0,
adcdat1,
adcupdn;
struct clk *ts_clk;
int down;
void (*wait4irq)(struct touchscreen *, int); //set ts in wait-for-irq mode
int (*isdown)(struct touchscreen *); //check stylus down or not
struct input_dev dev;
};
unsigned long ts_virt;
struct touchscreen s3c2440_ts;
void s3c2440_ts_wait4irq(struct touchscreen *ts, int down)
{
if (down) {
iowrite32( 0x3 | ( 1 << 4) | ( 1 << 6) | (1 << 7) , ts->adctsc);
} else {
iowrite32( 0x3 | ( 1 << 4) | ( 1 << 6) | (1 << 7) | (1 << 8) , ts->adctsc);
}
}
int s3c2440_ts_isdown(struct touchscreen *ts)
{
int down;
down = ioread32(ts->adcupdn);
iowrite32(0, ts->adcupdn);
return (down & 1);
}
irqreturn_t s3c2440_tstc_handle(int irq, struct touchscreen *ts)
{
if(IRQ_TC == irq)
{
if(ts->isdown(ts))
{ //stylus down
ts->wait4irq(ts, 0);
input_report_abs(&ts->dev, ABS_PRESSURE, 1);
s3c2410_gpio_setpin(S3C2410_GPF4, 0); //LED on
}
else
{ //stylus up
ts->wait4irq(ts, 1);
input_report_abs(&ts->dev, ABS_PRESSURE, 0);
input_sync(&ts->dev);
s3c2410_gpio_setpin(S3C2410_GPF4, 1); //LED off
}
}
return IRQ_HANDLED;
}
int test_init(void)
{
int ret;
ret = request_mem_region(0x58000000, 0x1000, "s3c2440-ts");
if(NULL == ret)
{
printk("request_mem_region failed .\n");
ret = -EBUSY;
goto err0;
}
ts_virt = ioremap(0x58000000, 0x1000);
s3c2440_ts.down = 0;
s3c2440_ts.adccon = ts_virt;
s3c2440_ts.adctsc = ts_virt + 0x04;
s3c2440_ts.adcdly = ts_virt + 0x08;
s3c2440_ts.adcdat0 = ts_virt + 0x0c;
s3c2440_ts.adcdat1 = ts_virt + 0x10;
s3c2440_ts.adcupdn = ts_virt + 0x14;
//---
s3c2440_ts.wait4irq = s3c2440_ts_wait4irq;
s3c2440_ts.isdown = s3c2440_ts_isdown;
ret = request_irq(IRQ_TC, s3c2440_tstc_handle, 0, "s3c2440-ts", &s3c2440_ts);
if(0 != ret)
{
printk("request irq[1] failed .\n");
ret = -EBUSY;
goto err1;
}
s3c2440_ts.ts_clk = clk_get(NULL, "adc");
clk_use(s3c2440_ts.ts_clk);
clk_enable(s3c2440_ts.ts_clk);
s3c2440_ts.wait4irq(&s3c2440_ts, 1);
s3c2440_ts.dev.evbit[0] = BIT(EV_ABS) | BIT(EV_SYN);
input_set_abs_params(&s3c2440_ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
input_register_device(&s3c2440_ts.dev);
return 0;
err1:
iounmap(ts_virt);
release_mem_region(0x58000000, 0x1000);
err0:
return ret;
}
void test_exit(void)
{
input_unregister_device(&s3c2440_ts.dev);
free_irq(IRQ_TC, &s3c2440_ts);
clk_disable(s3c2440_ts.ts_clk);
clk_unuse(s3c2440_ts.ts_clk);
clk_put(s3c2440_ts.ts_clk);
iounmap(ts_virt);
release_mem_region(0x58000000, 0x1000);
}
module_init(test_init);
module_exit(test_exit);
|