~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/input/touchscreen/hp680_ts_input.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <linux/input.h>
 
2
#include <linux/module.h>
 
3
#include <linux/init.h>
 
4
#include <linux/interrupt.h>
 
5
#include <asm/io.h>
 
6
#include <asm/delay.h>
 
7
#include <asm/adc.h>
 
8
#include <mach/hp6xx.h>
 
9
 
 
10
#define MODNAME "hp680_ts_input"
 
11
 
 
12
#define HP680_TS_ABS_X_MIN      40
 
13
#define HP680_TS_ABS_X_MAX      950
 
14
#define HP680_TS_ABS_Y_MIN      80
 
15
#define HP680_TS_ABS_Y_MAX      910
 
16
 
 
17
#define PHDR    0xa400012e
 
18
#define SCPDR   0xa4000136
 
19
 
 
20
static void do_softint(struct work_struct *work);
 
21
 
 
22
static struct input_dev *hp680_ts_dev;
 
23
static DECLARE_DELAYED_WORK(work, do_softint);
 
24
 
 
25
static void do_softint(struct work_struct *work)
 
26
{
 
27
        int absx = 0, absy = 0;
 
28
        u8 scpdr;
 
29
        int touched = 0;
 
30
 
 
31
        if (__raw_readb(PHDR) & PHDR_TS_PEN_DOWN) {
 
32
                scpdr = __raw_readb(SCPDR);
 
33
                scpdr |= SCPDR_TS_SCAN_ENABLE;
 
34
                scpdr &= ~SCPDR_TS_SCAN_Y;
 
35
                __raw_writeb(scpdr, SCPDR);
 
36
                udelay(30);
 
37
 
 
38
                absy = adc_single(ADC_CHANNEL_TS_Y);
 
39
 
 
40
                scpdr = __raw_readb(SCPDR);
 
41
                scpdr |= SCPDR_TS_SCAN_Y;
 
42
                scpdr &= ~SCPDR_TS_SCAN_X;
 
43
                __raw_writeb(scpdr, SCPDR);
 
44
                udelay(30);
 
45
 
 
46
                absx = adc_single(ADC_CHANNEL_TS_X);
 
47
 
 
48
                scpdr = __raw_readb(SCPDR);
 
49
                scpdr |= SCPDR_TS_SCAN_X;
 
50
                scpdr &= ~SCPDR_TS_SCAN_ENABLE;
 
51
                __raw_writeb(scpdr, SCPDR);
 
52
                udelay(100);
 
53
                touched = __raw_readb(PHDR) & PHDR_TS_PEN_DOWN;
 
54
        }
 
55
 
 
56
        if (touched) {
 
57
                input_report_key(hp680_ts_dev, BTN_TOUCH, 1);
 
58
                input_report_abs(hp680_ts_dev, ABS_X, absx);
 
59
                input_report_abs(hp680_ts_dev, ABS_Y, absy);
 
60
        } else {
 
61
                input_report_key(hp680_ts_dev, BTN_TOUCH, 0);
 
62
        }
 
63
 
 
64
        input_sync(hp680_ts_dev);
 
65
        enable_irq(HP680_TS_IRQ);
 
66
}
 
67
 
 
68
static irqreturn_t hp680_ts_interrupt(int irq, void *dev)
 
69
{
 
70
        disable_irq_nosync(irq);
 
71
        schedule_delayed_work(&work, HZ / 20);
 
72
 
 
73
        return IRQ_HANDLED;
 
74
}
 
75
 
 
76
static int __init hp680_ts_init(void)
 
77
{
 
78
        int err;
 
79
 
 
80
        hp680_ts_dev = input_allocate_device();
 
81
        if (!hp680_ts_dev)
 
82
                return -ENOMEM;
 
83
 
 
84
        hp680_ts_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
 
85
        hp680_ts_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
86
 
 
87
        input_set_abs_params(hp680_ts_dev, ABS_X,
 
88
                HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0);
 
89
        input_set_abs_params(hp680_ts_dev, ABS_Y,
 
90
                HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0);
 
91
 
 
92
        hp680_ts_dev->name = "HP Jornada touchscreen";
 
93
        hp680_ts_dev->phys = "hp680_ts/input0";
 
94
 
 
95
        if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt,
 
96
                        0, MODNAME, 0) < 0) {
 
97
                printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n",
 
98
                       HP680_TS_IRQ);
 
99
                err = -EBUSY;
 
100
                goto fail1;
 
101
        }
 
102
 
 
103
        err = input_register_device(hp680_ts_dev);
 
104
        if (err)
 
105
                goto fail2;
 
106
 
 
107
        return 0;
 
108
 
 
109
 fail2: free_irq(HP680_TS_IRQ, NULL);
 
110
        cancel_delayed_work_sync(&work);
 
111
 fail1: input_free_device(hp680_ts_dev);
 
112
        return err;
 
113
}
 
114
 
 
115
static void __exit hp680_ts_exit(void)
 
116
{
 
117
        free_irq(HP680_TS_IRQ, NULL);
 
118
        cancel_delayed_work_sync(&work);
 
119
        input_unregister_device(hp680_ts_dev);
 
120
}
 
121
 
 
122
module_init(hp680_ts_init);
 
123
module_exit(hp680_ts_exit);
 
124
 
 
125
MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
 
126
MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");
 
127
MODULE_LICENSE("GPL");