xref: /openbmc/linux/drivers/input/mouse/amimouse.c (revision d2912cb1)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  Amiga mouse driver for Linux/m68k
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (c) 2000-2002 Vojtech Pavlik
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  Based on the work of:
81da177e4SLinus Torvalds  *	Michael Rausch		James Banks
91da177e4SLinus Torvalds  *	Matther Dillon		David Giller
101da177e4SLinus Torvalds  *	Nathan Laredo		Linus Torvalds
111da177e4SLinus Torvalds  *	Johan Myreen		Jes Sorensen
121da177e4SLinus Torvalds  *	Russell King
131da177e4SLinus Torvalds  */
141da177e4SLinus Torvalds 
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/init.h>
181da177e4SLinus Torvalds #include <linux/input.h>
191da177e4SLinus Torvalds #include <linux/interrupt.h>
20314c926fSGeert Uytterhoeven #include <linux/platform_device.h>
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds #include <asm/irq.h>
231da177e4SLinus Torvalds #include <asm/setup.h>
247c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
251da177e4SLinus Torvalds #include <asm/amigahw.h>
261da177e4SLinus Torvalds #include <asm/amigaints.h>
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
291da177e4SLinus Torvalds MODULE_DESCRIPTION("Amiga mouse driver");
301da177e4SLinus Torvalds MODULE_LICENSE("GPL");
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds static int amimouse_lastx, amimouse_lasty;
331da177e4SLinus Torvalds 
amimouse_interrupt(int irq,void * data)34314c926fSGeert Uytterhoeven static irqreturn_t amimouse_interrupt(int irq, void *data)
351da177e4SLinus Torvalds {
36314c926fSGeert Uytterhoeven 	struct input_dev *dev = data;
371da177e4SLinus Torvalds 	unsigned short joy0dat, potgor;
381da177e4SLinus Torvalds 	int nx, ny, dx, dy;
391da177e4SLinus Torvalds 
40b4290a23SAl Viro 	joy0dat = amiga_custom.joy0dat;
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds 	nx = joy0dat & 0xff;
431da177e4SLinus Torvalds 	ny = joy0dat >> 8;
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds 	dx = nx - amimouse_lastx;
461da177e4SLinus Torvalds 	dy = ny - amimouse_lasty;
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds 	if (dx < -127) dx = (256 + nx) - amimouse_lastx;
491da177e4SLinus Torvalds 	if (dx >  127) dx = (nx - 256) - amimouse_lastx;
501da177e4SLinus Torvalds 	if (dy < -127) dy = (256 + ny) - amimouse_lasty;
511da177e4SLinus Torvalds 	if (dy >  127) dy = (ny - 256) - amimouse_lasty;
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds 	amimouse_lastx = nx;
541da177e4SLinus Torvalds 	amimouse_lasty = ny;
551da177e4SLinus Torvalds 
56b4290a23SAl Viro 	potgor = amiga_custom.potgor;
571da177e4SLinus Torvalds 
58314c926fSGeert Uytterhoeven 	input_report_rel(dev, REL_X, dx);
59314c926fSGeert Uytterhoeven 	input_report_rel(dev, REL_Y, dy);
601da177e4SLinus Torvalds 
61314c926fSGeert Uytterhoeven 	input_report_key(dev, BTN_LEFT,   ciaa.pra & 0x40);
62314c926fSGeert Uytterhoeven 	input_report_key(dev, BTN_MIDDLE, potgor & 0x0100);
63314c926fSGeert Uytterhoeven 	input_report_key(dev, BTN_RIGHT,  potgor & 0x0400);
641da177e4SLinus Torvalds 
65314c926fSGeert Uytterhoeven 	input_sync(dev);
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds 	return IRQ_HANDLED;
681da177e4SLinus Torvalds }
691da177e4SLinus Torvalds 
amimouse_open(struct input_dev * dev)701da177e4SLinus Torvalds static int amimouse_open(struct input_dev *dev)
711da177e4SLinus Torvalds {
721da177e4SLinus Torvalds 	unsigned short joy0dat;
73314c926fSGeert Uytterhoeven 	int error;
741da177e4SLinus Torvalds 
75b4290a23SAl Viro 	joy0dat = amiga_custom.joy0dat;
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds 	amimouse_lastx = joy0dat & 0xff;
781da177e4SLinus Torvalds 	amimouse_lasty = joy0dat >> 8;
791da177e4SLinus Torvalds 
80314c926fSGeert Uytterhoeven 	error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse",
81314c926fSGeert Uytterhoeven 			    dev);
82314c926fSGeert Uytterhoeven 	if (error)
83314c926fSGeert Uytterhoeven 		dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
841da177e4SLinus Torvalds 
85314c926fSGeert Uytterhoeven 	return error;
861da177e4SLinus Torvalds }
871da177e4SLinus Torvalds 
amimouse_close(struct input_dev * dev)881da177e4SLinus Torvalds static void amimouse_close(struct input_dev *dev)
891da177e4SLinus Torvalds {
90314c926fSGeert Uytterhoeven 	free_irq(IRQ_AMIGA_VERTB, dev);
911da177e4SLinus Torvalds }
921da177e4SLinus Torvalds 
amimouse_probe(struct platform_device * pdev)93314c926fSGeert Uytterhoeven static int __init amimouse_probe(struct platform_device *pdev)
941da177e4SLinus Torvalds {
9572155615SDmitry Torokhov 	int err;
96314c926fSGeert Uytterhoeven 	struct input_dev *dev;
9772155615SDmitry Torokhov 
98314c926fSGeert Uytterhoeven 	dev = input_allocate_device();
99314c926fSGeert Uytterhoeven 	if (!dev)
1002e5b636bSDmitry Torokhov 		return -ENOMEM;
1011da177e4SLinus Torvalds 
102314c926fSGeert Uytterhoeven 	dev->name = pdev->name;
103314c926fSGeert Uytterhoeven 	dev->phys = "amimouse/input0";
104314c926fSGeert Uytterhoeven 	dev->id.bustype = BUS_AMIGA;
105314c926fSGeert Uytterhoeven 	dev->id.vendor = 0x0001;
106314c926fSGeert Uytterhoeven 	dev->id.product = 0x0002;
107314c926fSGeert Uytterhoeven 	dev->id.version = 0x0100;
1081da177e4SLinus Torvalds 
109314c926fSGeert Uytterhoeven 	dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
110314c926fSGeert Uytterhoeven 	dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
111314c926fSGeert Uytterhoeven 	dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
1127b19ada2SJiri Slaby 		BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
113314c926fSGeert Uytterhoeven 	dev->open = amimouse_open;
114314c926fSGeert Uytterhoeven 	dev->close = amimouse_close;
115314c926fSGeert Uytterhoeven 	dev->dev.parent = &pdev->dev;
1161da177e4SLinus Torvalds 
117314c926fSGeert Uytterhoeven 	err = input_register_device(dev);
11872155615SDmitry Torokhov 	if (err) {
119314c926fSGeert Uytterhoeven 		input_free_device(dev);
12072155615SDmitry Torokhov 		return err;
12172155615SDmitry Torokhov 	}
1222e5b636bSDmitry Torokhov 
123314c926fSGeert Uytterhoeven 	platform_set_drvdata(pdev, dev);
124314c926fSGeert Uytterhoeven 
1251da177e4SLinus Torvalds 	return 0;
1261da177e4SLinus Torvalds }
1271da177e4SLinus Torvalds 
amimouse_remove(struct platform_device * pdev)128314c926fSGeert Uytterhoeven static int __exit amimouse_remove(struct platform_device *pdev)
1291da177e4SLinus Torvalds {
130314c926fSGeert Uytterhoeven 	struct input_dev *dev = platform_get_drvdata(pdev);
131314c926fSGeert Uytterhoeven 
132314c926fSGeert Uytterhoeven 	input_unregister_device(dev);
133314c926fSGeert Uytterhoeven 	return 0;
134314c926fSGeert Uytterhoeven }
135314c926fSGeert Uytterhoeven 
136314c926fSGeert Uytterhoeven static struct platform_driver amimouse_driver = {
137314c926fSGeert Uytterhoeven 	.remove = __exit_p(amimouse_remove),
138314c926fSGeert Uytterhoeven 	.driver   = {
139314c926fSGeert Uytterhoeven 		.name	= "amiga-mouse",
140314c926fSGeert Uytterhoeven 	},
141314c926fSGeert Uytterhoeven };
142d3d25808SDmitry Torokhov 
143e492fe27SSachin Kamat module_platform_driver_probe(amimouse_driver, amimouse_probe);
144314c926fSGeert Uytterhoeven 
145314c926fSGeert Uytterhoeven MODULE_ALIAS("platform:amiga-mouse");
146