0001
0002
0003
0004
0005
0006
0007 #include <linux/input.h>
0008 #include <linux/ioport.h>
0009 #include <linux/module.h>
0010 #include <linux/platform_device.h>
0011 #include <linux/slab.h>
0012
0013 #ifdef CONFIG_SGI_IP22
0014 #include <asm/sgi/ioc.h>
0015
0016 static inline u8 button_status(void)
0017 {
0018 u8 status;
0019
0020 status = readb(&sgioc->panel) ^ 0xa0;
0021 return ((status & 0x80) >> 6) | ((status & 0x20) >> 5);
0022 }
0023 #endif
0024
0025 #ifdef CONFIG_SGI_IP32
0026 #include <asm/ip32/mace.h>
0027
0028 static inline u8 button_status(void)
0029 {
0030 u64 status;
0031
0032 status = readq(&mace->perif.audio.control);
0033 writeq(status & ~(3U << 23), &mace->perif.audio.control);
0034
0035 return (status >> 23) & 3;
0036 }
0037 #endif
0038
0039 #define BUTTONS_POLL_INTERVAL 30
0040 #define BUTTONS_COUNT_THRESHOLD 3
0041
0042 static const unsigned short sgi_map[] = {
0043 KEY_VOLUMEDOWN,
0044 KEY_VOLUMEUP
0045 };
0046
0047 struct buttons_dev {
0048 unsigned short keymap[ARRAY_SIZE(sgi_map)];
0049 int count[ARRAY_SIZE(sgi_map)];
0050 };
0051
0052 static void handle_buttons(struct input_dev *input)
0053 {
0054 struct buttons_dev *bdev = input_get_drvdata(input);
0055 u8 status;
0056 int i;
0057
0058 status = button_status();
0059
0060 for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
0061 if (status & (1U << i)) {
0062 if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
0063 input_event(input, EV_MSC, MSC_SCAN, i);
0064 input_report_key(input, bdev->keymap[i], 1);
0065 input_sync(input);
0066 }
0067 } else {
0068 if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
0069 input_event(input, EV_MSC, MSC_SCAN, i);
0070 input_report_key(input, bdev->keymap[i], 0);
0071 input_sync(input);
0072 }
0073 bdev->count[i] = 0;
0074 }
0075 }
0076 }
0077
0078 static int sgi_buttons_probe(struct platform_device *pdev)
0079 {
0080 struct buttons_dev *bdev;
0081 struct input_dev *input;
0082 int error, i;
0083
0084 bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
0085 if (!bdev)
0086 return -ENOMEM;
0087
0088 input = devm_input_allocate_device(&pdev->dev);
0089 if (!input)
0090 return -ENOMEM;
0091
0092 memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
0093
0094 input_set_drvdata(input, bdev);
0095
0096 input->name = "SGI buttons";
0097 input->phys = "sgi/input0";
0098 input->id.bustype = BUS_HOST;
0099
0100 input->keycode = bdev->keymap;
0101 input->keycodemax = ARRAY_SIZE(bdev->keymap);
0102 input->keycodesize = sizeof(unsigned short);
0103
0104 input_set_capability(input, EV_MSC, MSC_SCAN);
0105 __set_bit(EV_KEY, input->evbit);
0106 for (i = 0; i < ARRAY_SIZE(sgi_map); i++)
0107 __set_bit(bdev->keymap[i], input->keybit);
0108 __clear_bit(KEY_RESERVED, input->keybit);
0109
0110 error = input_setup_polling(input, handle_buttons);
0111 if (error)
0112 return error;
0113
0114 input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
0115
0116 error = input_register_device(input);
0117 if (error)
0118 return error;
0119
0120 return 0;
0121 }
0122
0123 static struct platform_driver sgi_buttons_driver = {
0124 .probe = sgi_buttons_probe,
0125 .driver = {
0126 .name = "sgibtns",
0127 },
0128 };
0129 module_platform_driver(sgi_buttons_driver);
0130
0131 MODULE_LICENSE("GPL");