Path: blob/master/drivers/input/touchscreen/hp680_ts_input.c
15109 views
#include <linux/input.h>1#include <linux/module.h>2#include <linux/init.h>3#include <linux/interrupt.h>4#include <asm/io.h>5#include <asm/delay.h>6#include <asm/adc.h>7#include <mach/hp6xx.h>89#define MODNAME "hp680_ts_input"1011#define HP680_TS_ABS_X_MIN 4012#define HP680_TS_ABS_X_MAX 95013#define HP680_TS_ABS_Y_MIN 8014#define HP680_TS_ABS_Y_MAX 9101516#define PHDR 0xa400012e17#define SCPDR 0xa40001361819static void do_softint(struct work_struct *work);2021static struct input_dev *hp680_ts_dev;22static DECLARE_DELAYED_WORK(work, do_softint);2324static void do_softint(struct work_struct *work)25{26int absx = 0, absy = 0;27u8 scpdr;28int touched = 0;2930if (__raw_readb(PHDR) & PHDR_TS_PEN_DOWN) {31scpdr = __raw_readb(SCPDR);32scpdr |= SCPDR_TS_SCAN_ENABLE;33scpdr &= ~SCPDR_TS_SCAN_Y;34__raw_writeb(scpdr, SCPDR);35udelay(30);3637absy = adc_single(ADC_CHANNEL_TS_Y);3839scpdr = __raw_readb(SCPDR);40scpdr |= SCPDR_TS_SCAN_Y;41scpdr &= ~SCPDR_TS_SCAN_X;42__raw_writeb(scpdr, SCPDR);43udelay(30);4445absx = adc_single(ADC_CHANNEL_TS_X);4647scpdr = __raw_readb(SCPDR);48scpdr |= SCPDR_TS_SCAN_X;49scpdr &= ~SCPDR_TS_SCAN_ENABLE;50__raw_writeb(scpdr, SCPDR);51udelay(100);52touched = __raw_readb(PHDR) & PHDR_TS_PEN_DOWN;53}5455if (touched) {56input_report_key(hp680_ts_dev, BTN_TOUCH, 1);57input_report_abs(hp680_ts_dev, ABS_X, absx);58input_report_abs(hp680_ts_dev, ABS_Y, absy);59} else {60input_report_key(hp680_ts_dev, BTN_TOUCH, 0);61}6263input_sync(hp680_ts_dev);64enable_irq(HP680_TS_IRQ);65}6667static irqreturn_t hp680_ts_interrupt(int irq, void *dev)68{69disable_irq_nosync(irq);70schedule_delayed_work(&work, HZ / 20);7172return IRQ_HANDLED;73}7475static int __init hp680_ts_init(void)76{77int err;7879hp680_ts_dev = input_allocate_device();80if (!hp680_ts_dev)81return -ENOMEM;8283hp680_ts_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);84hp680_ts_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);8586input_set_abs_params(hp680_ts_dev, ABS_X,87HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);88input_set_abs_params(hp680_ts_dev, ABS_Y,89HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0);9091hp680_ts_dev->name = "HP Jornada touchscreen";92hp680_ts_dev->phys = "hp680_ts/input0";9394if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,95IRQF_DISABLED, MODNAME, 0) < 0) {96printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",97HP680_TS_IRQ);98err = -EBUSY;99goto fail1;100}101102err = input_register_device(hp680_ts_dev);103if (err)104goto fail2;105106return 0;107108fail2: free_irq(HP680_TS_IRQ, NULL);109cancel_delayed_work_sync(&work);110fail1: input_free_device(hp680_ts_dev);111return err;112}113114static void __exit hp680_ts_exit(void)115{116free_irq(HP680_TS_IRQ, NULL);117cancel_delayed_work_sync(&work);118input_unregister_device(hp680_ts_dev);119}120121module_init(hp680_ts_init);122module_exit(hp680_ts_exit);123124MODULE_AUTHOR("Andriy Skulysh, [email protected]");125MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");126MODULE_LICENSE("GPL");127128129