Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add Raspberry Pi Sense HAT joystick driver

This patch adds the driver for the Sense HAT joystick. It outputs BTN_DPAD
key events when moved in any of the four directions and the BTN_SELECT
event when depressed.

Co-developed-by: Daniel Bauman <dbauman@redhat.com>
Signed-off-by: Daniel Bauman <dbauman@redhat.com>
Co-developed-by: Mwesigwa Guma <mguma@redhat.com>
Signed-off-by: Mwesigwa Guma <mguma@redhat.com>
Co-developed-by: Joel Savitz <jsavitz@redhat.com>
Signed-off-by: Joel Savitz <jsavitz@redhat.com>
Signed-off-by: Charles Mirabile <cmirabil@redhat.com>
Link: https://lore.kernel.org/r/20220419205158.28088-3-cmirabil@redhat.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Charles Mirabile and committed by
Dmitry Torokhov
41657514 d238b8f6

+149
+11
drivers/input/joystick/Kconfig
··· 399 399 Say Y here if you want enable support for the four 400 400 built-in controller ports on the Nintendo 64 console. 401 401 402 + config JOYSTICK_SENSEHAT 403 + tristate "Raspberry Pi Sense HAT joystick" 404 + depends on INPUT && I2C 405 + select MFD_SIMPLE_MFD_I2C 406 + help 407 + Say Y here if you want to enable the driver for the 408 + the Raspberry Pi Sense HAT. 409 + 410 + To compile this driver as a module, choose M here: the 411 + module will be called sensehat_joystick. 412 + 402 413 endif
+1
drivers/input/joystick/Makefile
··· 28 28 obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o 29 29 obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o 30 30 obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o 31 + obj-$(CONFIG_JOYSTICK_SENSEHAT) += sensehat-joystick.o 31 32 obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o 32 33 obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o 33 34 obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
+137
drivers/input/joystick/sensehat-joystick.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Raspberry Pi Sense HAT joystick driver 4 + * http://raspberrypi.org 5 + * 6 + * Copyright (C) 2015 Raspberry Pi 7 + * Copyright (C) 2021 Charles Mirabile, Mwesigwa Guma, Joel Savitz 8 + * 9 + * Original Author: Serge Schneider 10 + * Revised for upstream Linux by: Charles Mirabile, Mwesigwa Guma, Joel Savitz 11 + */ 12 + 13 + #include <linux/module.h> 14 + #include <linux/input.h> 15 + #include <linux/i2c.h> 16 + #include <linux/interrupt.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/regmap.h> 19 + #include <linux/property.h> 20 + 21 + #define JOYSTICK_SMB_REG 0xf2 22 + 23 + struct sensehat_joystick { 24 + struct platform_device *pdev; 25 + struct input_dev *keys_dev; 26 + unsigned long prev_states; 27 + struct regmap *regmap; 28 + }; 29 + 30 + static const unsigned int keymap[] = { 31 + BTN_DPAD_DOWN, BTN_DPAD_RIGHT, BTN_DPAD_UP, BTN_SELECT, BTN_DPAD_LEFT, 32 + }; 33 + 34 + static irqreturn_t sensehat_joystick_report(int irq, void *cookie) 35 + { 36 + struct sensehat_joystick *sensehat_joystick = cookie; 37 + unsigned long curr_states, changes; 38 + unsigned int keys; 39 + int error; 40 + int i; 41 + 42 + error = regmap_read(sensehat_joystick->regmap, JOYSTICK_SMB_REG, &keys); 43 + if (error < 0) { 44 + dev_err(&sensehat_joystick->pdev->dev, 45 + "Failed to read joystick state: %d", error); 46 + return IRQ_NONE; 47 + } 48 + curr_states = keys; 49 + bitmap_xor(&changes, &curr_states, &sensehat_joystick->prev_states, 50 + ARRAY_SIZE(keymap)); 51 + 52 + for_each_set_bit(i, &changes, ARRAY_SIZE(keymap)) 53 + input_report_key(sensehat_joystick->keys_dev, keymap[i], 54 + curr_states & BIT(i)); 55 + 56 + input_sync(sensehat_joystick->keys_dev); 57 + sensehat_joystick->prev_states = keys; 58 + return IRQ_HANDLED; 59 + } 60 + 61 + static int sensehat_joystick_probe(struct platform_device *pdev) 62 + { 63 + struct sensehat_joystick *sensehat_joystick; 64 + int error, i, irq; 65 + 66 + sensehat_joystick = devm_kzalloc(&pdev->dev, sizeof(*sensehat_joystick), 67 + GFP_KERNEL); 68 + if (!sensehat_joystick) 69 + return -ENOMEM; 70 + 71 + sensehat_joystick->pdev = pdev; 72 + 73 + sensehat_joystick->regmap = dev_get_regmap(pdev->dev.parent, NULL); 74 + if (!sensehat_joystick->regmap) { 75 + dev_err(&pdev->dev, "unable to get sensehat regmap"); 76 + return -ENODEV; 77 + } 78 + 79 + sensehat_joystick->keys_dev = devm_input_allocate_device(&pdev->dev); 80 + if (!sensehat_joystick->keys_dev) { 81 + dev_err(&pdev->dev, "Could not allocate input device"); 82 + return -ENOMEM; 83 + } 84 + 85 + sensehat_joystick->keys_dev->name = "Raspberry Pi Sense HAT Joystick"; 86 + sensehat_joystick->keys_dev->phys = "sensehat-joystick/input0"; 87 + sensehat_joystick->keys_dev->id.bustype = BUS_I2C; 88 + 89 + __set_bit(EV_KEY, sensehat_joystick->keys_dev->evbit); 90 + __set_bit(EV_REP, sensehat_joystick->keys_dev->evbit); 91 + for (i = 0; i < ARRAY_SIZE(keymap); i++) 92 + __set_bit(keymap[i], sensehat_joystick->keys_dev->keybit); 93 + 94 + error = input_register_device(sensehat_joystick->keys_dev); 95 + if (error) { 96 + dev_err(&pdev->dev, "Could not register input device"); 97 + return error; 98 + } 99 + 100 + irq = platform_get_irq(pdev, 0); 101 + if (irq < 0) { 102 + dev_err(&pdev->dev, "Could not retrieve interrupt request"); 103 + return irq; 104 + } 105 + 106 + error = devm_request_threaded_irq(&pdev->dev, irq, 107 + NULL, sensehat_joystick_report, 108 + IRQF_ONESHOT, "keys", 109 + sensehat_joystick); 110 + if (error) { 111 + dev_err(&pdev->dev, "IRQ request failed"); 112 + return error; 113 + } 114 + 115 + return 0; 116 + } 117 + 118 + static const struct of_device_id sensehat_joystick_device_id[] = { 119 + { .compatible = "raspberrypi,sensehat-joystick" }, 120 + {}, 121 + }; 122 + MODULE_DEVICE_TABLE(of, sensehat_joystick_device_id); 123 + 124 + static struct platform_driver sensehat_joystick_driver = { 125 + .probe = sensehat_joystick_probe, 126 + .driver = { 127 + .name = "sensehat-joystick", 128 + .of_match_table = sensehat_joystick_device_id, 129 + }, 130 + }; 131 + 132 + module_platform_driver(sensehat_joystick_driver); 133 + 134 + MODULE_DESCRIPTION("Raspberry Pi Sense HAT joystick driver"); 135 + MODULE_AUTHOR("Charles Mirabile <cmirabil@redhat.com>"); 136 + MODULE_AUTHOR("Serge Schneider <serge@raspberrypi.org>"); 137 + MODULE_LICENSE("GPL");