1 /* Touch screen driver for the TI something-or-other
3 * Copyright © 2005 SDG Systems, LLC
5 * Based on code that was based on the SAMCOP driver.
6 * Copyright © 2003, 2004 Compaq Computer Corporation.
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.
12 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
13 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
14 * FITNESS FOR ANY PARTICULAR PURPOSE.
16 * Author: Keith Packard <keith.packard@hp.com>
21 * 2004-02-11 Michael Opdenacker Renamed names from samcop to shamcop,
22 * Goal:support HAMCOP and SAMCOP.
23 * 2004-02-14 Michael Opdenacker Temporary fix for device id handling
25 * 2005-02-18 Aric Blumer Converted basic structure to support hx4700
27 * 2005-06-07 Aric Blumer Added tssim device handling so we can
28 * hook in the fbvncserver.
31 #include <linux/module.h>
32 #include <linux/version.h>
34 #include <linux/init.h>
36 #include <linux/cdev.h>
37 #include <linux/interrupt.h>
38 #include <linux/sched.h>
40 #include <linux/delay.h>
41 #include <linux/input.h>
42 #include <linux/input_pda.h>
43 #include <linux/platform_device.h>
44 #include <linux/battery.h>
46 #include <asm/arch/hardware.h>
48 #include <asm/mach/irq.h>
50 #include <asm/semaphore.h>
52 #include <asm/arch/pxa-regs.h>
53 #include <asm/arch/hx4700-gpio.h>
54 #include <asm/arch/hx4700-asic.h>
56 #include <asm/hardware/ipaq-asic3.h>
57 #include <linux/soc/asic3_base.h>
59 extern struct platform_device hx4700_asic3
;
61 enum touchscreen_state
{
62 STATE_WAIT_FOR_TOUCH
, /* Waiting for a PEN interrupt */
63 STATE_SAMPLING
/* Actively sampling ADC */
66 struct touchscreen_data
{
67 enum touchscreen_state state
;
68 struct timer_list timer
;
70 struct input_dev
*input
;
81 static unsigned long poll_sample_time
= 10; /* Sample every 10 milliseconds */
83 static struct touchscreen_data
*ts_data
;
87 module_param(poll_sample_time
, ulong
, 0644);
88 MODULE_PARM_DESC(poll_sample_time
, "Poll sample time");
91 report_touchpanel(struct touchscreen_data
*ts
, int pressure
, int x
, int y
)
93 input_report_abs(ts
->input
, ABS_PRESSURE
, pressure
);
94 input_report_abs(ts
->input
, ABS_X
, x
);
95 input_report_abs(ts
->input
, ABS_Y
, y
);
96 input_sync(ts
->input
);
99 static struct work_struct serial_work
;
102 pen_isr(int irq
, void *irq_desc
)
104 /* struct touchscreen_data *ts = dev_id->data; */
105 struct touchscreen_data
*ts
= ts_data
;
108 if(irq
== HX4700_IRQ(TOUCHPANEL_IRQ_N
)) {
110 if (ts
->state
== STATE_WAIT_FOR_TOUCH
) {
112 * There is ground bounce or noise or something going on here:
113 * when you write to the SSP port to get the X and Y values, it
114 * causes a TOUCHPANEL_IRQ_N interrupt to occur. So if that
115 * happens, we can check to make sure the pen is actually down and
116 * disregard the interrupt if it's not.
118 if(GET_HX4700_GPIO(TOUCHPANEL_IRQ_N
) == 0) {
120 * Disable the pen interrupt. It's reenabled when the user lifts the
123 disable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N
));
125 ts
->state
= STATE_SAMPLING
;
126 schedule_work(&serial_work
);
129 /* Shouldn't happen */
130 printk(KERN_ERR
"Unexpected ts interrupt\n");
138 key_isr(int irq
, void *dev_id
)
140 struct key_data
*key
= dev_id
;
144 * alternate between rising and falling, based on pin status
146 statusd
= asic3_get_gpio_status_d( &hx4700_asic3
.dev
);
147 key
->rising
= (statusd
& key
->gpiod_bit
) == 0;
148 set_irq_type( irq
, key
->rising
? IRQT_RISING
: IRQT_FALLING
);
149 input_report_key( ts_data
->input
, key
->key
, key
->rising
);
150 input_sync( ts_data
->input
);
158 pxa_set_cken(CKEN3_SSP2
, 1);
160 /* *** Set up the SPI Registers *** */
162 (1 << 20) /* Extended Data Size Select */
163 | (6 << 8) /* Serial Clock Rate */
164 | (0 << 7) /* Synchronous Serial Enable (Disable for now) */
165 | (0 << 4) /* Motorola SPI Interface */
166 | (7 << 0) /* Data Size Select (24-bit) */
171 /* Clear the Status */
172 SSSR_P2
= SSSR_P2
& 0x00fcfffc;
176 (1 << 20) /* Extended Data Size Select */
177 | (6 << 8) /* Serial Clock Rate */
178 | (1 << 7) /* Synchronous Serial Enable */
179 | (0 << 4) /* Motorola SPI Interface */
180 | (7 << 0) /* Data Size Select (24-bit) */
182 /* enable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N)); */
185 DECLARE_MUTEX(serial_mutex
);
190 struct touchscreen_data
*touch
= in
;
191 unsigned long inc
= (poll_sample_time
* HZ
) / 1000;
196 /* Write here to the serial port.
197 * Then we have to wait for poll_sample_time before we read out the serial
198 * port. Then, when we read it out, we check to see if the pen is still
199 * down. If so, then we issue another request here.
202 for(i
= 0; i
< TS_SAMPLES
; i
++) {
203 while(!(SSSR_P2
& (1 << 2)))
205 /* It's not full. Write the command for X */
207 while(!(SSSR_P2
& (1 << 2)))
209 /* It's not full. Write the command for Y */
214 * Enable the timer. We should get an interrupt, but we want keep a timer
215 * to ensure that we can detect missing data
217 mod_timer(&touch
->timer
, jiffies
+ inc
);
221 do_delta_calc(int x1
, int y1
, int x2
, int y2
, int x3
, int y3
)
223 /* This is based on Jamey Hicks' description on IRC. */
224 int dx2_a
, dy2_a
, dx2_b
, dy2_b
;
227 dx2_a
= dx2_a
* dx2_a
; /* If dx2_a was negative, it's not now */
229 dy2_a
= dy2_a
* dy2_a
; /* If dy2_a was negative, it's not now */
232 dx2_b
= dx2_b
* dx2_b
; /* If dx2_b was negative, it's not now */
234 dy2_b
= dy2_b
* dy2_b
; /* If dy2_b was negative, it's not now */
237 /* This was described in the algorithm by Jamey, but it doesn't do much
240 if(dx2_a
+ dy2_a
< dx2_b
+ dy2_b
) return 0;
243 /* dx2_a + dy2_a is the distance squared */
245 ((dx2_a
+ dy2_a
) > 8000)
246 || ((dx2_b
+ dy2_b
) > 8000)
253 if((dx2_b
+ dy2_b
) > 5000) {
261 ts_timer_callback(unsigned long data
)
263 struct touchscreen_data
*ts
= (struct touchscreen_data
*)data
;
268 * Check here to see if there is anything in the SPI FIFO. If so,
269 * return it if there has been a change. If not, then we have a
270 * timeout. Generate an erro somehow.
273 if(ssrval
& (1 << 3)) { /* Look at Rx Not Empty bit */
274 int number_of_entries_in_fifo
;
276 /* The FIFO is not emtpy. Good! Now make sure there are at least two
279 number_of_entries_in_fifo
= ((ssrval
>> 12) & 0xf) + 1;
281 if(number_of_entries_in_fifo
< (TS_SAMPLES
* 2)) {
282 /* Not ready yet. Come back later. */
283 unsigned long inc
= (poll_sample_time
* HZ
) / 1000;
284 mod_timer(&ts
->timer
, jiffies
+ inc
);
288 if(number_of_entries_in_fifo
== TS_SAMPLES
* 2) {
290 int X
[TS_SAMPLES
], Y
[TS_SAMPLES
];
292 for(i
= 0; i
< TS_SAMPLES
; i
++) {
303 if(do_delta_calc(X
[0], Y
[0], X
[1], Y
[1], X
[2], Y
[2])) {
306 if(do_delta_calc(X
[1], Y
[1], X
[2], Y
[2], X
[3], Y
[3])) {
309 if(do_delta_calc(X
[2], Y
[2], X
[3], Y
[3], X
[4], Y
[4])) {
314 /* Take average of point 0 and point 3 */
315 X
[2] = (X
[1] + X
[3]) / 2;
316 Y
[2] = (Y
[1] + Y
[3]) / 2;
320 /* Just ignore this one */
325 /* keep this sample */
326 x
= (X
[1] + (2 * X
[2]) + X
[3]) / 4;
327 y
= (Y
[1] + (2 * Y
[2]) + Y
[3]) / 4;
331 X
[1] = (X
[0] + X
[2]) / 2;
332 Y
[1] = (Y
[0] + Y
[2]) / 2;
337 x
= (X
[0] + (4 * X
[1]) + (6 * X
[2]) + (4 * X
[3]) + X
[4]) >> 4;
338 y
= (Y
[0] + (4 * Y
[1]) + (6 * Y
[2]) + (4 * Y
[3]) + Y
[4]) >> 4;
343 if(GET_HX4700_GPIO(TOUCHPANEL_IRQ_N
) == 0) {
346 report_touchpanel(ts
, 1, x
, y
);
351 report_touchpanel(ts
, 0, 0, 0);
352 ts
->state
= STATE_WAIT_FOR_TOUCH
;
353 /* Re-enable pen down interrupt */
354 enable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N
));
358 /* We have an error! Too many entries. */
359 printk(KERN_ERR
"TS: Expected %d entries. Got %d\n", 2, number_of_entries_in_fifo
);
360 /* Try to clear the FIFO */
361 while(number_of_entries_in_fifo
--) {
365 if(GET_HX4700_GPIO(TOUCHPANEL_IRQ_N
) == 0) {
371 /* Not ready yet. Come back later. */
372 unsigned long inc
= (poll_sample_time
* HZ
) / 1000;
373 mod_timer(&ts
->timer
, jiffies
+ inc
);
379 ts_probe (struct platform_device
*pdev
)
382 struct touchscreen_data
*ts
;
386 ts
= ts_data
= kmalloc (sizeof (*ts
), GFP_KERNEL
);
388 printk( KERN_NOTICE
"hx4700_ts: unable to allocate memory\n" );
391 memset (ts
, 0, sizeof (*ts
));
394 /* *** Set up the input subsystem stuff *** */
395 // memset(ts->input, 0, sizeof(struct input_dev));
396 ts
->input
= input_allocate_device();
397 if (ts
->input
== NULL
) {
398 printk( KERN_NOTICE
"hx4700_ts: unable to allocation touchscreen input\n" );
402 ts
->input
->evbit
[0] = BIT(EV_ABS
) | BIT(EV_KEY
);
403 ts
->input
->absbit
[0] = BIT(ABS_X
) | BIT(ABS_Y
) | BIT(ABS_PRESSURE
);
404 ts
->input
->absmin
[ABS_X
] = 0;
405 ts
->input
->absmax
[ABS_X
] = 32767;
406 ts
->input
->absmin
[ABS_Y
] = 0;
407 ts
->input
->absmax
[ABS_Y
] = 32767;
408 ts
->input
->absmin
[ABS_PRESSURE
] = 0;
409 ts
->input
->absmax
[ABS_PRESSURE
] = 1;
410 ts
->input
->keybit
[LONG(_KEY_RECORD
)] |= BIT(_KEY_RECORD
); /* record */
411 ts
->input
->keybit
[LONG(_KEY_CALENDAR
)] |= BIT(_KEY_CALENDAR
); /* calendar */
412 ts
->input
->keybit
[LONG(_KEY_HOMEPAGE
)] |= BIT(_KEY_HOMEPAGE
);
414 ts
->input
->name
= "hx4700_ts";
415 ts
->input
->private = ts
;
417 input_register_device(ts
->input
);
419 ts
->timer
.function
= ts_timer_callback
;
420 ts
->timer
.data
= (unsigned long)ts
;
421 ts
->state
= STATE_WAIT_FOR_TOUCH
;
422 init_timer (&ts
->timer
);
424 INIT_WORK(&serial_work
, start_read
, ts
);
426 platform_set_drvdata(pdev
, ts
);
428 /* *** Initialize the SSP interface *** */
432 /* Make sure the device is in such a state that it can give pen
434 while(!(SSSR_P2
& (1 << 2)))
438 for(retval
= 0; retval
< 100; retval
++) {
439 if(SSSR_P2
& (1 << 3)) {
440 while(SSSR_P2
& (1 << 3)) {
450 ts
->irq
= HX4700_IRQ( TOUCHPANEL_IRQ_N
);
451 retval
= request_irq(ts
->irq
, pen_isr
, SA_INTERRUPT
, "hx4700_ts", ts
);
453 printk("Unable to get interrupt\n");
454 input_unregister_device (ts
->input
);
457 set_irq_type(ts
->irq
, IRQT_FALLING
);
459 /* *** Initialize the ASIC3 key interrupts *** */
460 /* Maybe shouldn't do this here, but take advantage of input
461 * device already configured */
462 asic3_key
[0].gpiod_val
= GPIOD_KEY_AP2_N
;
463 asic3_key
[0].gpiod_bit
= (1<<GPIOD_KEY_AP2_N
);
464 asic3_key
[0].rising
= 0;
465 asic3_key
[0].key
= _KEY_CALENDAR
;
466 irq
= asic3_irq_base( &hx4700_asic3
.dev
) + ASIC3_GPIOD_IRQ_BASE
468 err
= request_irq( irq
, key_isr
, SA_INTERRUPT
, "HX4700 AP2 Key",
469 (void *)&asic3_key
[0] );
471 printk(KERN_ERR
"GPIOD_KEY_AP2_N: can't request IRQ\n");
473 set_irq_type( irq
, IRQT_FALLING
);
474 asic3_key
[0].irq
= irq
;
477 asic3_key
[1].gpiod_val
= GPIOD_KEY_AP4_N
;
478 asic3_key
[1].gpiod_bit
= (1<<GPIOD_KEY_AP4_N
);
479 asic3_key
[1].rising
= 0;
480 asic3_key
[1].key
= _KEY_HOMEPAGE
;
481 irq
= asic3_irq_base( &hx4700_asic3
.dev
) + ASIC3_GPIOD_IRQ_BASE
483 err
= request_irq( irq
, key_isr
, SA_INTERRUPT
, "HX4700 AP4 Key",
484 (void *)&asic3_key
[1] );
486 printk(KERN_ERR
"GPIOD_KEY_AP4_N: can't request IRQ\n");
488 set_irq_type( irq
, IRQT_FALLING
);
489 asic3_key
[1].irq
= irq
;
492 asic3_key
[2].gpiod_val
= GPIOD_AUD_RECORD_N
;
493 asic3_key
[2].gpiod_bit
= (1<<GPIOD_AUD_RECORD_N
);
494 asic3_key
[2].rising
= 0;
495 asic3_key
[2].key
= _KEY_RECORD
;
496 irq
= asic3_irq_base( &hx4700_asic3
.dev
) + ASIC3_GPIOD_IRQ_BASE
497 + GPIOD_AUD_RECORD_N
;
498 err
= request_irq( irq
, key_isr
, SA_INTERRUPT
, "HX4700 Record",
499 (void *)&asic3_key
[2] );
501 printk(KERN_ERR
"GPIOD_AUD_RECORD_N: can't request IRQ\n");
503 set_irq_type( irq
, IRQT_FALLING
);
504 asic3_key
[2].irq
= irq
;
511 ts_remove (struct platform_device
*pdev
)
514 struct touchscreen_data
*ts
= platform_get_drvdata(pdev
);
516 input_unregister_device (ts
->input
);
517 del_timer_sync (&ts
->timer
);
518 free_irq (ts
->irq
, ts
);
519 for (i
=0; i
<3; i
++) {
520 if (asic3_key
[i
].irq
!= 0)
521 free_irq( asic3_key
[i
].irq
, &asic3_key
[i
] );
525 pxa_set_cken(CKEN3_SSP2
, 0);
530 ts_suspend (struct platform_device
*pdev
, pm_message_t state
)
532 disable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N
));
537 ts_resume (struct platform_device
*pdev
)
539 struct touchscreen_data
*ts
= platform_get_drvdata(pdev
);
541 ts
->state
= STATE_WAIT_FOR_TOUCH
;
543 enable_irq(HX4700_IRQ(TOUCHPANEL_IRQ_N
));
548 static struct platform_driver ts_driver
= {
551 .suspend
= ts_suspend
,
558 static int tssim_init(void);
561 ts_module_init (void)
563 printk(KERN_NOTICE
"hx4700 Touch Screen Driver\n");
565 printk(KERN_NOTICE
" TS Simulator Not Installed\n");
567 printk(KERN_NOTICE
" TS Simulator Installed\n");
569 return platform_driver_register(&ts_driver
);
572 static void tssim_exit(void);
575 ts_module_cleanup (void)
578 platform_driver_unregister (&ts_driver
);
581 /************* Code for Touch Screen Simulation for FBVNC Server **********/
583 static struct cdev
*cdev
;
585 static long a0
= -1122, a2
= 33588528, a4
= 1452, a5
= -2970720, a6
= 65536;
587 /* The input into the input subsystem is prior to correction from calibration.
588 * So we have to undo the effects of the calibration. It's actually a
589 * complicated equation where the calibrated value of X depends on the
590 * uncalibrated values of X and Y. Fortunately, at least on the hx4700, the
591 * multiplier for the Y value is zero, so I assume that here. It is a shame
592 * that the tslib does not allow multiple inputs. Then we could do another
593 * driver for this (as it was originally) that give input that does not
594 * require calibration.
597 tssim_ioctl(struct inode
*inode
, struct file
*fp
, unsigned int ioctlnum
, unsigned long parm
)
600 case 0: a0
= parm
; break;
602 case 2: a2
= parm
; break;
604 case 4: a4
= parm
; break;
605 case 5: a5
= parm
; break;
608 printk(KERN_DEBUG
"a0 = %ld, a2 = %ld, a4 = %ld, a5 = %ld, a6 = %ld\n",
611 default: return -ENOTTY
;
617 tssim_open(struct inode
*inode
, struct file
*fp
)
619 /* Nothing to do here */
624 tssim_write(struct file
*fp
, const char __user
*data
, size_t bytes
, loff_t
*offset
)
626 unsigned long pressure
;
630 x
= data
[0] | (data
[1] << 8) | (data
[2] << 16) | (data
[3] << 24); data
+= 4;
631 y
= data
[0] | (data
[1] << 8) | (data
[2] << 16) | (data
[3] << 24); data
+= 4;
632 pressure
= data
[0] | (data
[1] << 8) | (data
[2] << 16) | (data
[3] << 24); data
+= 4;
634 input_report_abs(ts_data
->input
, ABS_PRESSURE
, pressure
?1:0);
635 input_report_abs(ts_data
->input
, ABS_X
, ((x
* a6
) - a2
)/a0
);
636 input_report_abs(ts_data
->input
, ABS_Y
, ((y
* a6
) - a5
)/a4
);
637 input_sync(ts_data
->input
);
642 int tssim_close(struct inode
*inode
, struct file
*fp
)
647 struct file_operations fops
= {
649 .write
= tssim_write
,
651 .release
= tssim_close
,
652 .ioctl
= tssim_ioctl
,
655 static int battery_class
;
657 static int get_min_voltage(struct battery
*b
)
661 static int get_max_voltage(struct battery
*b
)
663 return 1400; /* mV */
665 static int get_max_charge(struct battery
*b
)
669 static int get_voltage(struct battery
*b
)
671 static int battery_sample
;
673 if(!down_interruptible(&serial_mutex
)) {
677 while(!(SSSR_P2
& (1 << 2)))
680 while(!(SSSR_P2
& (1 << 2)))
683 while(!(SSSR_P2
& (1 << 2)))
685 SSDR_P2
= 0xd00000; /* Dummy command to allow pen interrupts again */
687 for(i
= 0; i
< 10; i
++) {
689 if(ssrval
& (1 << 3)) { /* Look at Rx Not Empty bit */
690 int number_of_entries_in_fifo
;
692 number_of_entries_in_fifo
= ((ssrval
>> 12) & 0xf) + 1;
693 if(number_of_entries_in_fifo
== 3) {
702 battery_sample
= SSDR_P2
& 0xfff;
705 /* Make sure the FIFO is empty */
706 while(SSSR_P2
& (1 << 3)) {
714 return battery_sample
;
716 static int get_charge(struct battery
*b
)
720 static int get_status(struct battery
*b
)
725 static struct battery hx4700_power
= {
726 .name
= "hx4700_backup",
728 .get_min_voltage
= get_min_voltage
,
729 .get_min_current
= 0,
731 .get_max_voltage
= get_max_voltage
,
732 .get_max_current
= 0,
733 .get_max_charge
= get_max_charge
,
735 .get_voltage
= get_voltage
,
737 .get_charge
= get_charge
,
738 .get_status
= get_status
,
742 battery_class_uevent(struct class_device
*dev
, char **envp
, int num_envp
,
743 char *buffer
, int buffer_size
)
749 battery_class_release(struct class_device
*dev
)
754 battery_class_class_release(struct class *class)
763 retval
= alloc_chrdev_region(&dev
, 0, 1, "tssim");
765 printk(KERN_ERR
"TSSIM Unable to allocate device numbers\n");
770 cdev
->owner
= THIS_MODULE
;
772 retval
= cdev_add(cdev
, dev
, 1);
774 printk(KERN_ERR
"Unable to add cdev\n");
775 unregister_chrdev_region(dev
, 1);
780 if(battery_class_register(&hx4700_power
)) {
781 printk(KERN_ERR
"hx4700_ts: Could not register battery class\n");
784 hx4700_power
.class_dev
.class->uevent
= battery_class_uevent
;
785 hx4700_power
.class_dev
.class->release
= battery_class_release
;
786 hx4700_power
.class_dev
.class->class_release
= battery_class_class_release
;
796 unregister_chrdev_region(dev
, 1);
798 battery_class_unregister(&hx4700_power
);
803 module_init(ts_module_init
);
804 module_exit(ts_module_cleanup
);
806 MODULE_LICENSE("GPL");
807 MODULE_AUTHOR("Aric Blumer, SDG Systems, LLC");
808 MODULE_DESCRIPTION("hx4700 Touch Screen Driver");