0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <linux/module.h>
0035 #include <linux/kernel.h>
0036 #include <linux/init.h>
0037 #include <linux/errno.h>
0038 #include <linux/delay.h>
0039 #include <linux/ioport.h>
0040 #include <linux/interrupt.h>
0041 #include <linux/input.h>
0042 #include <asm/io.h>
0043
0044 MODULE_AUTHOR("Daniel Quinlan <quinlan@pathname.com>, Vojtech Pavlik <vojtech@suse.cz>");
0045 MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver");
0046 MODULE_LICENSE("GPL");
0047
0048 static unsigned int mk712_io = 0x260;
0049 module_param_hw_named(io, mk712_io, uint, ioport, 0);
0050 MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller");
0051
0052 static unsigned int mk712_irq = 10;
0053 module_param_hw_named(irq, mk712_irq, uint, irq, 0);
0054 MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
0055
0056
0057 #define MK712_STATUS 0
0058 #define MK712_X 2
0059 #define MK712_Y 4
0060 #define MK712_CONTROL 6
0061 #define MK712_RATE 7
0062
0063
0064 #define MK712_STATUS_TOUCH 0x10
0065 #define MK712_CONVERSION_COMPLETE 0x80
0066
0067
0068 #define MK712_ENABLE_INT 0x01
0069 #define MK712_INT_ON_CONVERSION_COMPLETE 0x02
0070 #define MK712_INT_ON_CHANGE_IN_TOUCH_STATUS 0x04
0071 #define MK712_ENABLE_PERIODIC_CONVERSIONS 0x10
0072 #define MK712_READ_ONE_POINT 0x20
0073 #define MK712_POWERUP 0x40
0074
0075 static struct input_dev *mk712_dev;
0076 static DEFINE_SPINLOCK(mk712_lock);
0077
0078 static irqreturn_t mk712_interrupt(int irq, void *dev_id)
0079 {
0080 unsigned char status;
0081 static int debounce = 1;
0082 static unsigned short last_x;
0083 static unsigned short last_y;
0084
0085 spin_lock(&mk712_lock);
0086
0087 status = inb(mk712_io + MK712_STATUS);
0088
0089 if (~status & MK712_CONVERSION_COMPLETE) {
0090 debounce = 1;
0091 goto end;
0092 }
0093
0094 if (~status & MK712_STATUS_TOUCH) {
0095 debounce = 1;
0096 input_report_key(mk712_dev, BTN_TOUCH, 0);
0097 goto end;
0098 }
0099
0100 if (debounce) {
0101 debounce = 0;
0102 goto end;
0103 }
0104
0105 input_report_key(mk712_dev, BTN_TOUCH, 1);
0106 input_report_abs(mk712_dev, ABS_X, last_x);
0107 input_report_abs(mk712_dev, ABS_Y, last_y);
0108
0109 end:
0110 last_x = inw(mk712_io + MK712_X) & 0x0fff;
0111 last_y = inw(mk712_io + MK712_Y) & 0x0fff;
0112 input_sync(mk712_dev);
0113 spin_unlock(&mk712_lock);
0114 return IRQ_HANDLED;
0115 }
0116
0117 static int mk712_open(struct input_dev *dev)
0118 {
0119 unsigned long flags;
0120
0121 spin_lock_irqsave(&mk712_lock, flags);
0122
0123 outb(0, mk712_io + MK712_CONTROL);
0124
0125 outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
0126 MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
0127 MK712_ENABLE_PERIODIC_CONVERSIONS |
0128 MK712_POWERUP, mk712_io + MK712_CONTROL);
0129
0130 outb(10, mk712_io + MK712_RATE);
0131
0132 spin_unlock_irqrestore(&mk712_lock, flags);
0133
0134 return 0;
0135 }
0136
0137 static void mk712_close(struct input_dev *dev)
0138 {
0139 unsigned long flags;
0140
0141 spin_lock_irqsave(&mk712_lock, flags);
0142
0143 outb(0, mk712_io + MK712_CONTROL);
0144
0145 spin_unlock_irqrestore(&mk712_lock, flags);
0146 }
0147
0148 static int __init mk712_init(void)
0149 {
0150 int err;
0151
0152 if (!request_region(mk712_io, 8, "mk712")) {
0153 printk(KERN_WARNING "mk712: unable to get IO region\n");
0154 return -ENODEV;
0155 }
0156
0157 outb(0, mk712_io + MK712_CONTROL);
0158
0159 if ((inw(mk712_io + MK712_X) & 0xf000) ||
0160 (inw(mk712_io + MK712_Y) & 0xf000) ||
0161 (inw(mk712_io + MK712_STATUS) & 0xf333)) {
0162 printk(KERN_WARNING "mk712: device not present\n");
0163 err = -ENODEV;
0164 goto fail1;
0165 }
0166
0167 mk712_dev = input_allocate_device();
0168 if (!mk712_dev) {
0169 printk(KERN_ERR "mk712: not enough memory\n");
0170 err = -ENOMEM;
0171 goto fail1;
0172 }
0173
0174 mk712_dev->name = "ICS MicroClock MK712 TouchScreen";
0175 mk712_dev->phys = "isa0260/input0";
0176 mk712_dev->id.bustype = BUS_ISA;
0177 mk712_dev->id.vendor = 0x0005;
0178 mk712_dev->id.product = 0x0001;
0179 mk712_dev->id.version = 0x0100;
0180
0181 mk712_dev->open = mk712_open;
0182 mk712_dev->close = mk712_close;
0183
0184 mk712_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0185 mk712_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
0186 input_set_abs_params(mk712_dev, ABS_X, 0, 0xfff, 88, 0);
0187 input_set_abs_params(mk712_dev, ABS_Y, 0, 0xfff, 88, 0);
0188
0189 if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) {
0190 printk(KERN_WARNING "mk712: unable to get IRQ\n");
0191 err = -EBUSY;
0192 goto fail1;
0193 }
0194
0195 err = input_register_device(mk712_dev);
0196 if (err)
0197 goto fail2;
0198
0199 return 0;
0200
0201 fail2: free_irq(mk712_irq, mk712_dev);
0202 fail1: input_free_device(mk712_dev);
0203 release_region(mk712_io, 8);
0204 return err;
0205 }
0206
0207 static void __exit mk712_exit(void)
0208 {
0209 input_unregister_device(mk712_dev);
0210 free_irq(mk712_irq, mk712_dev);
0211 release_region(mk712_io, 8);
0212 }
0213
0214 module_init(mk712_init);
0215 module_exit(mk712_exit);