Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  SGI Volume Button interface driver
0004  *
0005  *  Copyright (C) 2008  Thomas Bogendoerfer <tsbogend@alpha.franken.de>
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  /* msec */
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");