2 * Touchscreen and battery driver for iPAQ h1910/h1915
4 * Copyright (C) 2005-2006 Pawel Kolodziejski
5 * Copyright (c) 2002,2003 SHARP Corporation
6 * Copyright (C) 2003 Joshua Wise
8 * Use consistent with the GNU GPL is permitted,
9 * provided that this copyright notice is
10 * preserved in its entirety in all copies and derived works.
14 #include <linux/module.h>
15 #include <linux/version.h>
16 #include <linux/config.h>
17 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/sched.h>
22 #include <linux/device.h>
23 #include <linux/sysctl.h>
24 #include <linux/proc_fs.h>
25 #include <linux/delay.h>
26 #include <linux/input.h>
27 #include <linux/soc/asic3_base.h>
28 #include <linux/platform_device.h>
30 #include <asm/mach/map.h>
31 #include <asm/mach-types.h>
32 #include <asm/arch/hardware.h>
34 #include <asm/mach/irq.h>
35 #include <asm/arch/pxa-regs.h>
36 #include <asm/arch/ssp.h>
37 #include <asm/arch-pxa/h1900-gpio.h>
38 #include <asm/arch-pxa/h1900-asic.h>
39 #include <asm/hardware/ipaq-asic3.h>
41 static spinlock_t h1900_ssp_lock
= SPIN_LOCK_UNLOCKED
;
42 static struct ssp_dev h1900_ssp_dev
;
43 static struct ssp_state h1900_ssp_state
;
45 unsigned long h1900_ssp_putget(ulong data
)
50 spin_lock_irqsave(&h1900_ssp_lock
, flag
);
52 ssp_write_word(&h1900_ssp_dev
, data
);
53 ssp_read_word(&h1900_ssp_dev
, &ret
);
55 spin_unlock_irqrestore(&h1900_ssp_lock
, flag
);
60 #define SAMPLE_TIMEOUT 20
62 static struct timer_list timer_pen
;
63 static struct input_dev
*idev
;
65 static int touch_pressed
;
66 static int irq_disable
;
68 static void report_touchpanel(int x
, int y
, int pressure
)
70 input_report_key(idev
, BTN_TOUCH
, pressure
!= 0);
71 input_report_abs(idev
, ABS_PRESSURE
, pressure
);
72 input_report_abs(idev
, ABS_X
, x
);
73 input_report_abs(idev
, ABS_Y
, y
);
77 #define CTRL_START 0x80
78 #define CTRL_YPOS 0x10
79 #define CTRL_Z1POS 0x30
80 #define CTRL_Z2POS 0x40
81 #define CTRL_XPOS 0x50
82 #define CTRL_TEMP0 0x04
83 #define CTRL_TEMP1 0x74
84 #define CTRL_VBAT 0x24
89 #define ADSCTRL_ADR_SH 4
91 typedef struct ts_pos_s
{
96 void read_xydata(ts_pos_t
*tp
)
98 #define abscmpmin(x,y,d) ( ((int)((x) - (y)) < (int)(d)) && ((int)((y) - (x)) < (int)(d)) )
100 unsigned int t
, x
, y
, z
[2];
101 unsigned long pressure
;
106 for (i
= j
= k
= 0, x
= y
= 0;; i
= 1) {
108 cmd
= CTRL_PD0
| CTRL_PD1
| CTRL_START
| CTRL_Z1POS
;
109 t
= h1900_ssp_putget(cmd
);
110 z
[i
] = h1900_ssp_putget(cmd
);
116 cmd
= CTRL_PD0
| CTRL_PD1
| CTRL_START
| CTRL_XPOS
;
117 x
= h1900_ssp_putget(cmd
);
118 for (j
= 0; !err
; j
++) {
120 x
= h1900_ssp_putget(cmd
);
121 if (abscmpmin(t
, x
, d
))
125 //printk("ts: x(%d,%d,%d)\n", t, x, t - x);
130 cmd
= CTRL_PD0
| CTRL_PD1
| CTRL_START
| CTRL_YPOS
;
131 y
= h1900_ssp_putget(cmd
);
132 for (k
= 0; !err
; k
++) {
134 y
= h1900_ssp_putget(cmd
);
135 if (abscmpmin(t
,y
, d
))
139 //printk("ts: y(%d,%d,%d)\n", t, y, t - y);
144 for (i
= 0; i
< 2; i
++) {
149 for (i
= 0; i
< 2; i
++){
157 cmd
&= ~(CTRL_PD0
| CTRL_PD1
);
158 t
= h1900_ssp_putget(cmd
);
160 if (err
== 0 && pressure
!= 0) {
161 //printk("ts: pxyp=%d(%d/%d,%d/%d)%d\n", z[0], x, j, y, k, z[1]);
163 //printk("pxype=%d,%d,%d,%d\n", z[0], x, y, z[1]);
170 static irqreturn_t
h1900_stylus(int irq
, void *data
, struct pt_regs
*regs
)
174 if (irq
== IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
) && irq_disable
== 0) {
177 disable_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
));
180 read_xydata(&ts_pos
);
182 if (ts_pos
.xd
== 0 || ts_pos
.yd
== 0) {
183 report_touchpanel(0, 0, 0);
184 //printk("touch released\n");
185 if (irq_disable
== 1) {
186 request_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
), h1900_stylus
, SA_SAMPLE_RANDOM
, "ads7876 stylus", NULL
);
187 set_irq_type(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
), IRQT_FALLING
);
188 enable_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
));
194 //printk("%04d %04d\n", (int)ts_pos.xd, (int)ts_pos.yd);
195 //printk("touch pressed\n");
196 report_touchpanel(ts_pos
.xd
, ts_pos
.yd
, 1);
198 mod_timer(&timer_pen
, jiffies
+ (SAMPLE_TIMEOUT
* HZ
) / 1000);
200 //printk("callback\n");
204 static void h1900_ts_timer(unsigned long nr
)
206 h1900_stylus(-1, NULL
, NULL
);
209 static int __init
h1900_ssp_probe(struct device
*dev
)
213 if (!machine_is_h1900()) {
217 ret
= ssp_init(&h1900_ssp_dev
, 1, 0);
220 printk(KERN_ERR
"Unable to register SSP handler!\n");
223 ssp_disable(&h1900_ssp_dev
);
224 ssp_config(&h1900_ssp_dev
, (SSCR0_National
| 0x0b), 0, 0, SSCR0_SerClkDiv(36));
225 ssp_enable(&h1900_ssp_dev
);
228 h1900_ssp_putget(CTRL_YPOS
| CTRL_START
);
230 h1900_ssp_putget(CTRL_Z1POS
| CTRL_START
);
232 h1900_ssp_putget(CTRL_Z2POS
| CTRL_START
);
234 h1900_ssp_putget(CTRL_XPOS
| CTRL_START
);
236 init_timer(&timer_pen
);
237 timer_pen
.function
= h1900_ts_timer
;
238 timer_pen
.data
= (unsigned long)NULL
;
240 idev
= input_allocate_device();
244 idev
->name
= "ads7876";
245 idev
->phys
= "touchscreen/ads7876";
247 set_bit(EV_ABS
, idev
->evbit
);
248 set_bit(EV_KEY
, idev
->evbit
);
249 set_bit(ABS_X
, idev
->absbit
);
250 set_bit(ABS_Y
, idev
->absbit
);
251 set_bit(ABS_PRESSURE
, idev
->absbit
);
252 set_bit(BTN_TOUCH
, idev
->keybit
);
253 idev
->absmax
[ABS_PRESSURE
] = 1;
254 idev
->absmin
[ABS_X
] = 190;
255 idev
->absmax
[ABS_X
] = 1860;
256 idev
->absmin
[ABS_Y
] = 150;
257 idev
->absmax
[ABS_Y
] = 1880;
259 input_register_device(idev
);
264 set_irq_type(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
), IRQT_FALLING
);
265 request_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
), h1900_stylus
, SA_SAMPLE_RANDOM
, "ads7876 stylus", NULL
);
271 static int h1900_ssp_suspend(struct device
*dev
, pm_message_t state
)
273 del_timer_sync(&timer_pen
);
275 disable_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
));
277 ssp_flush(&h1900_ssp_dev
);
278 ssp_save_state(&h1900_ssp_dev
, &h1900_ssp_state
);
283 static int h1900_ssp_resume(struct device
*dev
)
285 ssp_restore_state(&h1900_ssp_dev
, &h1900_ssp_state
);
286 ssp_enable(&h1900_ssp_dev
);
290 enable_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
));
295 static int h1900_ssp_remove(struct device
*dev
)
297 del_timer_sync(&timer_pen
);
299 free_irq(IRQ_GPIO(GPIO_NR_H1900_PEN_IRQ_N
), NULL
);
301 ssp_exit(&h1900_ssp_dev
);
303 input_unregister_device(idev
);
304 input_free_device(idev
);
310 static struct device_driver h1900_ssp_driver
= {
312 .bus
= &platform_bus_type
,
313 .probe
= h1900_ssp_probe
,
314 .remove
= h1900_ssp_remove
,
316 .suspend
= h1900_ssp_suspend
,
317 .resume
= h1900_ssp_resume
,
321 static int __init
h1900_ssp_init(void)
323 if (!machine_is_h1900())
326 return driver_register(&h1900_ssp_driver
);
329 static void __exit
h1900_ssp_exit(void)
331 driver_unregister(&h1900_ssp_driver
);
334 module_init(h1900_ssp_init
)
335 module_exit(h1900_ssp_exit
)
337 MODULE_AUTHOR("Joshua Wise, Pawel Kolodziejski");
338 MODULE_DESCRIPTION("SSP touchscreen support for the iPAQ h1910/h1915");
339 MODULE_LICENSE("GPL");