···11+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/input/touchscreen/ti.tsc2007.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: Texas Instruments tsc2007 touchscreen controller88+99+maintainers:1010+ - Frank Li <Frank.Li@nxp.com>1111+1212+properties:1313+ compatible:1414+ const: ti,tsc20071515+1616+ reg:1717+ maxItems: 11818+1919+ interrupts:2020+ maxItems: 12121+2222+ ti,x-plate-ohms:2323+ description: X-plate resistance in ohms.2424+2525+ gpios: true2626+2727+ pendown-gpio: true2828+2929+ ti,max-rt:3030+ $ref: /schemas/types.yaml#/definitions/uint323131+ description: maximum pressure.3232+3333+ ti,fuzzx:3434+ $ref: /schemas/types.yaml#/definitions/uint323535+ description:3636+ specifies the absolute input fuzz x value.3737+ If set, it will permit noise in the data up to +- the value given to the fuzz3838+ parameter, that is used to filter noise from the event stream.3939+4040+ ti,fuzzy:4141+ $ref: /schemas/types.yaml#/definitions/uint324242+ description: specifies the absolute input fuzz y value.4343+4444+ ti,fuzzz:4545+ $ref: /schemas/types.yaml#/definitions/uint324646+ description: specifies the absolute input fuzz z value.4747+4848+ ti,poll-period:4949+ $ref: /schemas/types.yaml#/definitions/uint325050+ description:5151+ how much time to wait (in milliseconds) before reading again the5252+ values from the tsc2007.5353+5454+required:5555+ - compatible5656+ - reg5757+ - ti,x-plate-ohms5858+5959+additionalProperties: false6060+6161+examples:6262+ - |6363+ i2c {6464+ #address-cells = <1>;6565+ #size-cells = <0>;6666+6767+ touch@49 {6868+ compatible = "ti,tsc2007";6969+ reg = <0x49>;7070+ interrupt-parent = <&gpio4>;7171+ interrupts = <0x0 0x8>;7272+ gpios = <&gpio4 0 0>;7373+ ti,x-plate-ohms = <180>;7474+ };7575+ };
···8787 touchscreen-y-plate-ohms:8888 description: Resistance of the Y-plate in Ohms89899090+ touch-overlay:9191+ description: |9292+ List of nodes defining segments (touch areas) on the touchscreen.9393+9494+ This object can be used to describe a series of segments to restrict9595+ the region within touch events are reported or buttons with a specific9696+ functionality.9797+9898+ This is of special interest if the touchscreen is shipped with a physical9999+ overlay on top of it with a frame that hides some part of the original100100+ touchscreen area. Printed buttons on that overlay are also a typical101101+ use case.102102+103103+ A new touchscreen area is defined as a sub-node without a key code. If a104104+ key code is defined in the sub-node, it will be interpreted as a button.105105+106106+ The x-origin and y-origin properties of a touchscreen area define the107107+ offset of a new origin from where the touchscreen events are referenced.108108+ This offset is applied to the events accordingly. The x-size and y-size109109+ properties define the size of the touchscreen effective area.110110+111111+ The following example shows a new touchscreen area with the new origin112112+ (0',0') for the touch events generated by the device.113113+114114+ Touchscreen (full area)115115+ ┌────────────────────────────────────────┐116116+ │ ┌───────────────────────────────┐ │117117+ │ │ │ │118118+ │ ├ y-size │ │119119+ │ │ │ │120120+ │ │ touchscreen area │ │121121+ │ │ (no key code) │ │122122+ │ │ │ │123123+ │ │ x-size │ │124124+ │ ┌└──────────────┴────────────────┘ │125125+ │(0',0') │126126+ ┌└────────────────────────────────────────┘127127+ (0,0)128128+129129+ where (0',0') = (0+x-origin,0+y-origin)130130+131131+ Sub-nodes with key codes report the touch events on their surface as key132132+ events instead.133133+134134+ The following example shows a touchscreen with a single button on it.135135+136136+ Touchscreen (full area)137137+ ┌───────────────────────────────────┐138138+ │ │139139+ │ │140140+ │ ┌─────────┐ │141141+ │ │button 0 │ │142142+ │ │KEY_POWER│ │143143+ │ └─────────┘ │144144+ │ │145145+ │ │146146+ ┌└───────────────────────────────────┘147147+ (0,0)148148+149149+ Segments defining buttons and clipped toushcreen areas can be combined150150+ as shown in the following example.151151+ In that case only the events within the touchscreen area are reported152152+ as touch events. Events within the button areas report their associated153153+ key code. Any events outside the defined areas are ignored.154154+155155+ Touchscreen (full area)156156+ ┌─────────┬──────────────────────────────┐157157+ │ │ │158158+ │ │ ┌───────────────────────┐ │159159+ │ button 0│ │ │ │160160+ │KEY_POWER│ │ │ │161161+ │ │ │ │ │162162+ ├─────────┤ │ touchscreen area │ │163163+ │ │ │ (no key code) │ │164164+ │ │ │ │ │165165+ │ button 1│ │ │ │166166+ │ KEY_INFO│ ┌└───────────────────────┘ │167167+ │ │(0',0') │168168+ ┌└─────────┴──────────────────────────────┘169169+ (0,0)170170+171171+ type: object172172+173173+ patternProperties:174174+ '^segment-':175175+ type: object176176+ description:177177+ Each segment is represented as a sub-node.178178+ properties:179179+ x-origin:180180+ description: horizontal origin of the node area181181+ $ref: /schemas/types.yaml#/definitions/uint32182182+183183+ y-origin:184184+ description: vertical origin of the node area185185+ $ref: /schemas/types.yaml#/definitions/uint32186186+187187+ x-size:188188+ description: horizontal resolution of the node area189189+ $ref: /schemas/types.yaml#/definitions/uint32190190+191191+ y-size:192192+ description: vertical resolution of the node area193193+ $ref: /schemas/types.yaml#/definitions/uint32194194+195195+ label:196196+ description: descriptive name of the segment197197+ $ref: /schemas/types.yaml#/definitions/string198198+199199+ linux,code: true200200+201201+ required:202202+ - x-origin203203+ - y-origin204204+ - x-size205205+ - y-size206206+207207+ unevaluatedProperties: false208208+90209dependencies:91210 touchscreen-size-x: [ touchscreen-size-y ]92211 touchscreen-size-y: [ touchscreen-size-x ]
···11-* Texas Instruments tsc2007 touchscreen controller22-33-Required properties:44-- compatible: must be "ti,tsc2007".55-- reg: I2C address of the chip.66-- ti,x-plate-ohms: X-plate resistance in ohms.77-88-Optional properties:99-- gpios: the interrupt gpio the chip is connected to (through the penirq pin).1010- The penirq pin goes to low when the panel is touched.1111- (see GPIO binding[1] for more details).1212-- interrupts: (gpio) interrupt to which the chip is connected1313- (see interrupt binding[0]).1414-- ti,max-rt: maximum pressure.1515-- ti,fuzzx: specifies the absolute input fuzz x value.1616- If set, it will permit noise in the data up to +- the value given to the fuzz1717- parameter, that is used to filter noise from the event stream.1818-- ti,fuzzy: specifies the absolute input fuzz y value.1919-- ti,fuzzz: specifies the absolute input fuzz z value.2020-- ti,poll-period: how much time to wait (in milliseconds) before reading again the2121- values from the tsc2007.2222-2323-[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt2424-[1]: Documentation/devicetree/bindings/gpio/gpio.txt2525-2626-Example:2727- &i2c1 {2828- /* ... */2929- tsc2007@49 {3030- compatible = "ti,tsc2007";3131- reg = <0x49>;3232- interrupt-parent = <&gpio4>;3333- interrupts = <0x0 0x8>;3434- gpios = <&gpio4 0 0>;3535- ti,x-plate-ohms = <180>;3636- };3737-3838- /* ... */3939- };
+19-2
Documentation/input/devices/edt-ft5x06.rst
···292930303131For debugging purposes the driver provides a few files in the debug3232-filesystem (if available in the kernel). In /sys/kernel/debug/edt_ft5x063333-you'll find the following files:3232+filesystem (if available in the kernel). They are located in:3333+3434+ /sys/kernel/debug/i2c/<i2c-bus>/<i2c-device>/3535+3636+If you don't know the bus and device numbers, you can look them up with this3737+command:3838+3939+ $ ls -l /sys/bus/i2c/drivers/edt_ft5x064040+4141+The dereference of the symlink will contain the needed information. You will4242+need the last two elements of its path:4343+4444+ 0-0038 -> ../../../../devices/platform/soc/fcfee800.i2c/i2c-0/0-00384545+4646+So in this case, the location for the debug files is:4747+4848+ /sys/kernel/debug/i2c/i2c-0/0-0038/4949+5050+There, you'll find the following files:34513552num_x, num_y:3653 (readonly) contains the number of sensor fields in X- and
+16-3
Documentation/input/gamepad.rst
···190190191191 Rumble is advertised as FF_RUMBLE.192192193193+- Grip buttons:194194+195195+ Many pads include buttons on the rear, usually referred to as either grip or196196+ rear buttons, or paddles. These are often reprogrammable by the firmware to197197+ appear as "normal" buttons, but are sometimes exposed to software too. Some198198+ notable examples of this are the Steam Deck, which has R4, R5, L4, and L5 on199199+ the back; the Xbox Elite pads, which have P1-P4; and the Switch 2 Pro200200+ Controller, which has GL and GR.201201+202202+ For these controllers, BTN_GRIPR and BTN_GRIPR2 should be used for the top203203+ and bottom (if present) right grip button(s), and BTN_GRIPL and BTN_GRIPL2204204+ should be used for the top and bottom (if present) left grip button(s).205205+193206- Profile:194207195195- Some pads provide a multi-value profile selection switch. An example is the196196- XBox Adaptive and the XBox Elite 2 controllers. When the active profile is197197- switched, its newly selected value is emitted as an ABS_PROFILE event.208208+ Some pads provide a multi-value profile selection switch. Examples include209209+ the Xbox Adaptive and the Xbox Elite 2 controllers. When the active profile210210+ is switched, its newly selected value is emitted as an ABS_PROFILE event.
···449449xbox-dvd (RC_PROTO_XBOX_DVD)450450----------------------------451451452452-This protocol is used by XBox DVD Remote, which was made for the original453453-XBox. There is no in-kernel decoder or encoder for this protocol. The usb452452+This protocol is used by Xbox DVD Remote, which was made for the original453453+Xbox. There is no in-kernel decoder or encoder for this protocol. The usb454454device decodes the protocol. There is a BPF decoder available in v4l-utils.
+7
MAINTAINERS
···2545925459S: Maintained2546025460F: drivers/platform/x86/toshiba-wmi.c25461254612546225462+TOUCH OVERLAY2546325463+M: Javier Carrasco <javier.carrasco@wolfvision.net>2546425464+L: linux-input@vger.kernel.org2546525465+S: Maintained2546625466+F: drivers/input/touch-overlay.c2546725467+F: include/linux/input/touch-overlay.h2546825468+2546225469TPM DEVICE DRIVER2546325470M: Peter Huewe <peterhuewe@gmx.de>2546425471M: Jarkko Sakkinen <jarkko@kernel.org>
···584584 To compile this driver as a module, choose M here. The module will585585 be called palmas_pwrbutton.586586587587-config INPUT_PCF50633_PMU588588- tristate "PCF50633 PMU events"589589- depends on MFD_PCF50633590590- help591591- Say Y to include support for delivering PMU events via input592592- layer on NXP PCF50633.593593-594587config INPUT_PCF8574595588 tristate "PCF8574 Keypad input device"596589 depends on I2C
···68686969static int max77693_haptic_set_duty_cycle(struct max77693_haptic *haptic)7070{7171- struct pwm_args pargs;7272- int delta;7171+ struct pwm_state state;7372 int error;74737575- pwm_get_args(haptic->pwm_dev, &pargs);7676- delta = (pargs.period + haptic->pwm_duty) / 2;7777- error = pwm_config(haptic->pwm_dev, delta, pargs.period);7474+ pwm_init_state(haptic->pwm_dev, &state);7575+ state.duty_cycle = (state.period + haptic->pwm_duty) / 2;7676+7777+ error = pwm_apply_might_sleep(haptic->pwm_dev, &state);7878 if (error) {7979- dev_err(haptic->dev, "failed to configure pwm: %d\n", error);7979+ dev_err(haptic->dev,8080+ "failed to set pwm duty cycle: %d\n", error);8081 return error;8182 }8283···167166168167static void max77693_haptic_enable(struct max77693_haptic *haptic)169168{169169+ struct pwm_state state;170170 int error;171171172172 if (haptic->enabled)173173 return;174174175175- error = pwm_enable(haptic->pwm_dev);175175+ pwm_init_state(haptic->pwm_dev, &state);176176+ state.duty_cycle = (state.period + haptic->pwm_duty) / 2;177177+ state.enabled = true;178178+179179+ error = pwm_apply_might_sleep(haptic->pwm_dev, &state);176180 if (error) {177181 dev_err(haptic->dev,178182 "failed to enable haptic pwm device: %d\n", error);···230224{231225 struct max77693_haptic *haptic =232226 container_of(work, struct max77693_haptic, work);233233- int error;234227235235- error = max77693_haptic_set_duty_cycle(haptic);236236- if (error) {237237- dev_err(haptic->dev, "failed to set duty cycle: %d\n", error);238238- return;239239- }240240-241241- if (haptic->magnitude)242242- max77693_haptic_enable(haptic);243243- else228228+ if (!haptic->magnitude)244229 max77693_haptic_disable(haptic);230230+ else if (haptic->enabled)231231+ max77693_haptic_set_duty_cycle(haptic);232232+ else233233+ max77693_haptic_enable(haptic);245234}246235247236static int max77693_haptic_play_effect(struct input_dev *dev, void *data,···340339 dev_err(&pdev->dev, "failed to get pwm device\n");341340 return PTR_ERR(haptic->pwm_dev);342341 }343343-344344- /*345345- * FIXME: pwm_apply_args() should be removed when switching to the346346- * atomic PWM API.347347- */348348- pwm_apply_args(haptic->pwm_dev);349342350343 haptic->motor_reg = devm_regulator_get(&pdev->dev, "haptic");351344 if (IS_ERR(haptic->motor_reg)) {
+48-50
drivers/input/misc/max8997_haptic.c
···5353 unsigned int pattern_signal_period;5454};55555656-static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)5656+static void max8997_haptic_set_internal_duty_cycle(struct max8997_haptic *chip)5757{5858- int ret = 0;5858+ u8 duty_index = DIV_ROUND_UP(chip->level * 64, 100);59596060- if (chip->mode == MAX8997_EXTERNAL_MODE) {6161- unsigned int duty = chip->pwm_period * chip->level / 100;6262- ret = pwm_config(chip->pwm, duty, chip->pwm_period);6363- } else {6464- u8 duty_index = 0;6565-6666- duty_index = DIV_ROUND_UP(chip->level * 64, 100);6767-6868- switch (chip->internal_mode_pattern) {6969- case 0:7070- max8997_write_reg(chip->client,7171- MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);7272- break;7373- case 1:7474- max8997_write_reg(chip->client,7575- MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);7676- break;7777- case 2:7878- max8997_write_reg(chip->client,7979- MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);8080- break;8181- case 3:8282- max8997_write_reg(chip->client,8383- MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);8484- break;8585- default:8686- break;8787- }6060+ switch (chip->internal_mode_pattern) {6161+ case 0:6262+ max8997_write_reg(chip->client,6363+ MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);6464+ break;6565+ case 1:6666+ max8997_write_reg(chip->client,6767+ MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);6868+ break;6969+ case 2:7070+ max8997_write_reg(chip->client,7171+ MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);7272+ break;7373+ case 3:7474+ max8997_write_reg(chip->client,7575+ MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);7676+ break;7777+ default:7878+ break;8879 }8989- return ret;9080}91819282static void max8997_haptic_configure(struct max8997_haptic *chip)···145155146156 guard(mutex)(&chip->mutex);147157148148- error = max8997_haptic_set_duty_cycle(chip);149149- if (error) {150150- dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error);151151- return;152152- }158158+ if (chip->mode != MAX8997_EXTERNAL_MODE)159159+ max8997_haptic_set_internal_duty_cycle(chip);153160154161 if (!chip->enabled) {155162 error = regulator_enable(chip->regulator);···155168 return;156169 }157170 max8997_haptic_configure(chip);158158- if (chip->mode == MAX8997_EXTERNAL_MODE) {159159- error = pwm_enable(chip->pwm);160160- if (error) {161161- dev_err(chip->dev, "Failed to enable PWM\n");162162- regulator_disable(chip->regulator);163163- return;164164- }165165- }166166- chip->enabled = true;167171 }172172+173173+ /*174174+ * It would be more straight forward to configure the external PWM175175+ * earlier i.e. when the internal duty_cycle is setup in internal mode.176176+ * But historically this is done only after the regulator was enabled177177+ * and max8997_haptic_configure() set the enable bit in178178+ * MAX8997_HAPTIC_REG_CONF2. So better keep it this way.179179+ */180180+ if (chip->mode == MAX8997_EXTERNAL_MODE) {181181+ struct pwm_state state;182182+183183+ pwm_init_state(chip->pwm, &state);184184+ state.period = chip->pwm_period;185185+ state.duty_cycle = chip->pwm_period * chip->level / 100;186186+ state.enabled = true;187187+188188+ error = pwm_apply_might_sleep(chip->pwm, &state);189189+ if (error) {190190+ dev_err(chip->dev, "Failed to enable PWM\n");191191+ regulator_disable(chip->regulator);192192+ return;193193+ }194194+ }195195+196196+ chip->enabled = true;168197}169198170199static void max8997_haptic_disable(struct max8997_haptic *chip)···285282 goto err_free_mem;286283 }287284288288- /*289289- * FIXME: pwm_apply_args() should be removed when switching to290290- * the atomic PWM API.291291- */292292- pwm_apply_args(chip->pwm);293285 break;294286295287 default:
-113
drivers/input/misc/pcf50633-input.c
···11-// SPDX-License-Identifier: GPL-2.0-or-later22-/* NXP PCF50633 Input Driver33- *44- * (C) 2006-2008 by Openmoko, Inc.55- * Author: Balaji Rao <balajirrao@openmoko.org>66- * All rights reserved.77- *88- * Broken down from monstrous PCF50633 driver mainly by99- * Harald Welte, Andy Green and Werner Almesberger1010- */1111-1212-#include <linux/kernel.h>1313-#include <linux/module.h>1414-#include <linux/device.h>1515-#include <linux/platform_device.h>1616-#include <linux/input.h>1717-#include <linux/slab.h>1818-1919-#include <linux/mfd/pcf50633/core.h>2020-2121-#define PCF50633_OOCSTAT_ONKEY 0x012222-#define PCF50633_REG_OOCSTAT 0x122323-#define PCF50633_REG_OOCMODE 0x102424-2525-struct pcf50633_input {2626- struct pcf50633 *pcf;2727- struct input_dev *input_dev;2828-};2929-3030-static void3131-pcf50633_input_irq(int irq, void *data)3232-{3333- struct pcf50633_input *input;3434- int onkey_released;3535-3636- input = data;3737-3838- /* We report only one event depending on the key press status */3939- onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)4040- & PCF50633_OOCSTAT_ONKEY;4141-4242- if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)4343- input_report_key(input->input_dev, KEY_POWER, 1);4444- else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)4545- input_report_key(input->input_dev, KEY_POWER, 0);4646-4747- input_sync(input->input_dev);4848-}4949-5050-static int pcf50633_input_probe(struct platform_device *pdev)5151-{5252- struct pcf50633_input *input;5353- struct input_dev *input_dev;5454- int ret;5555-5656-5757- input = kzalloc(sizeof(*input), GFP_KERNEL);5858- if (!input)5959- return -ENOMEM;6060-6161- input_dev = input_allocate_device();6262- if (!input_dev) {6363- kfree(input);6464- return -ENOMEM;6565- }6666-6767- platform_set_drvdata(pdev, input);6868- input->pcf = dev_to_pcf50633(pdev->dev.parent);6969- input->input_dev = input_dev;7070-7171- input_dev->name = "PCF50633 PMU events";7272- input_dev->id.bustype = BUS_I2C;7373- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);7474- set_bit(KEY_POWER, input_dev->keybit);7575-7676- ret = input_register_device(input_dev);7777- if (ret) {7878- input_free_device(input_dev);7979- kfree(input);8080- return ret;8181- }8282- pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,8383- pcf50633_input_irq, input);8484- pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,8585- pcf50633_input_irq, input);8686-8787- return 0;8888-}8989-9090-static void pcf50633_input_remove(struct platform_device *pdev)9191-{9292- struct pcf50633_input *input = platform_get_drvdata(pdev);9393-9494- pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);9595- pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);9696-9797- input_unregister_device(input->input_dev);9898- kfree(input);9999-}100100-101101-static struct platform_driver pcf50633_input_driver = {102102- .driver = {103103- .name = "pcf50633-input",104104- },105105- .probe = pcf50633_input_probe,106106- .remove = pcf50633_input_remove,107107-};108108-module_platform_driver(pcf50633_input_driver);109109-110110-MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");111111-MODULE_DESCRIPTION("PCF50633 input driver");112112-MODULE_LICENSE("GPL");113113-MODULE_ALIAS("platform:pcf50633-input");
+15
drivers/input/rmi4/Kconfig
···8282 touchpads. For sensors that support relative pointing, F12 also8383 provides mouse input.84848585+config RMI4_F1A8686+ bool "RMI4 Function 1A (0D pointing)"8787+ help8888+ Say Y here if you want to add support for RMI4 function 1A.8989+9090+ Function 1A provides capacitive keys support for RMI4 devices.9191+9292+config RMI4_F219393+ bool "RMI4 Function 21 (PRESSURE)"9494+ help9595+ Say Y here if you want to add support for RMI4 function 21.9696+9797+ Function 21 provides buttons/pressure handling for RMI4 devices.9898+ This includes support for buttons/pressure on PressurePad.9999+85100config RMI4_F3086101 bool "RMI4 Function 30 (GPIO LED)"87102 help
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Copyright (c) 2012-2025 Synaptics Incorporated44+ */55+66+#include <linux/bits.h>77+#include <linux/dev_printk.h>88+#include <linux/kernel.h>99+#include <linux/rmi.h>1010+#include <linux/input.h>1111+#include <linux/slab.h>1212+#include "rmi_driver.h"1313+1414+#define RMI_F21_SENSOR_COUNT_MASK GENMASK(3, 0)1515+#define RMI_F21_FINGER_COUNT_PRESENT BIT(5)1616+#define RMI_F21_NEW_REPORT_FORMAT BIT(6)1717+1818+#define RMI_F21_FINGER_COUNT_MASK GENMASK(3, 0)1919+2020+#define RMI_F21_MAX_SENSORS 162121+#define RMI_F21_MAX_FINGERS 162222+#define RMI_F21_DATA_REGS_MAX_SIZE (RMI_F21_MAX_SENSORS * 2 + \2323+ RMI_F21_MAX_FINGERS * 2 + 1)2424+2525+#define RMI_F21_FORCE_CLICK_BIT BIT(0)2626+2727+#define RMI_F21_FORCEPAD_BUTTON_COUNT 12828+2929+struct f21_data {3030+ struct input_dev *input;3131+ u16 key_code;3232+3333+ unsigned int attn_data_size;3434+ unsigned int attn_data_button_offset;3535+3636+ unsigned int data_reg_size;3737+ unsigned int data_reg_button_offset;3838+ u8 data_regs[RMI_F21_DATA_REGS_MAX_SIZE];3939+};4040+4141+static irqreturn_t rmi_f21_attention(int irq, void *ctx)4242+{4343+ struct rmi_function *fn = ctx;4444+ struct f21_data *f21 = dev_get_drvdata(&fn->dev);4545+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);4646+ u8 *pdata;4747+ int error;4848+ bool pressed;4949+5050+ if (drvdata->attn_data.data) {5151+ if (drvdata->attn_data.size < f21->attn_data_size) {5252+ dev_warn(&fn->dev, "f21 interrupt, but data is missing\n");5353+ return IRQ_HANDLED;5454+ }5555+5656+ pdata = drvdata->attn_data.data + f21->attn_data_button_offset;5757+5858+ drvdata->attn_data.data += f21->attn_data_size;5959+ drvdata->attn_data.size -= f21->attn_data_size;6060+ } else {6161+ error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,6262+ f21->data_regs, f21->data_reg_size);6363+ if (error) {6464+ dev_err(&fn->dev, "failed to read f21 data registers: %d\n",6565+ error);6666+ return IRQ_RETVAL(error);6767+ }6868+6969+ pdata = f21->data_regs + f21->data_reg_button_offset;7070+ }7171+7272+ pressed = *pdata & RMI_F21_FORCE_CLICK_BIT;7373+ input_report_key(f21->input, f21->key_code, pressed);7474+7575+ return IRQ_HANDLED;7676+}7777+7878+static int rmi_f21_config(struct rmi_function *fn)7979+{8080+ struct rmi_driver *drv = fn->rmi_dev->driver;8181+8282+ drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);8383+8484+ return 0;8585+}8686+8787+static int rmi_f21_initialize(struct rmi_function *fn, struct f21_data *f21)8888+{8989+ struct input_dev *input = f21->input;9090+9191+ f21->key_code = BTN_LEFT;9292+9393+ input->keycode = &f21->key_code;9494+ input->keycodesize = sizeof(f21->key_code);9595+ input->keycodemax = RMI_F21_FORCEPAD_BUTTON_COUNT;9696+9797+ input_set_capability(input, EV_KEY, f21->key_code);9898+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);9999+100100+ return 0;101101+}102102+103103+static int rmi_f21_probe(struct rmi_function *fn)104104+{105105+ struct rmi_device *rmi_dev = fn->rmi_dev;106106+ struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);107107+ struct f21_data *f21;108108+ unsigned int sensor_count;109109+ unsigned int max_fingers;110110+ unsigned int query15_offset;111111+ u8 query15_data;112112+ int error;113113+114114+ if (!drv_data->input) {115115+ dev_info(&fn->dev, "f21: no input device found, ignoring\n");116116+ return -ENXIO;117117+ }118118+119119+ f21 = devm_kzalloc(&fn->dev, sizeof(*f21), GFP_KERNEL);120120+ if (!f21)121121+ return -ENOMEM;122122+123123+ f21->input = drv_data->input;124124+125125+ error = rmi_f21_initialize(fn, f21);126126+ if (error)127127+ return error;128128+129129+ dev_set_drvdata(&fn->dev, f21);130130+131131+ sensor_count = fn->fd.query_base_addr & RMI_F21_SENSOR_COUNT_MASK;132132+ if (fn->fd.query_base_addr & RMI_F21_FINGER_COUNT_PRESENT) {133133+ query15_offset = fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT ? 2 : 1;134134+ error = rmi_read_block(fn->rmi_dev,135135+ fn->fd.query_base_addr + query15_offset,136136+ &query15_data, sizeof(query15_data));137137+ if (error)138138+ return dev_err_probe(&fn->dev, error,139139+ "failed to read 'query15' data");140140+141141+ max_fingers = query15_data & RMI_F21_FINGER_COUNT_MASK;142142+ } else {143143+ max_fingers = 5;144144+ }145145+146146+ if (fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT) {147147+ /* Each finger uses one byte, and the button state uses one byte.*/148148+ f21->attn_data_size = max_fingers + 1;149149+ f21->attn_data_button_offset = f21->attn_data_size - 1;150150+ /*151151+ * Each sensor uses two bytes, the button state uses one byte,152152+ * and each finger uses two bytes.153153+ */154154+ f21->data_reg_size = sensor_count * 2 + 1 + max_fingers * 2;155155+ f21->data_reg_button_offset = sensor_count * 2;156156+ } else {157157+ /*158158+ * Regardless of the transport each finger uses two bytes,159159+ * and the button state uses one byte.160160+ */161161+ f21->attn_data_size = sensor_count * 2 + 1;162162+ f21->attn_data_button_offset = sensor_count * 2;163163+164164+ f21->data_reg_size = f21->attn_data_size;165165+ f21->data_reg_button_offset = f21->attn_data_button_offset;166166+ }167167+168168+ return 0;169169+}170170+171171+struct rmi_function_handler rmi_f21_handler = {172172+ .driver = {173173+ .name = "rmi4_f21",174174+ },175175+ .func = 0x21,176176+ .probe = rmi_f21_probe,177177+ .config = rmi_f21_config,178178+ .attention = rmi_f21_attention,179179+};
+277
drivers/input/touch-overlay.c
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Helper functions for overlay objects on touchscreens44+ *55+ * Copyright (c) 2023 Javier Carrasco <javier.carrasco@wolfvision.net>66+ */77+88+#include <linux/input.h>99+#include <linux/input/mt.h>1010+#include <linux/input/touch-overlay.h>1111+#include <linux/list.h>1212+#include <linux/module.h>1313+#include <linux/property.h>1414+1515+struct touch_overlay_segment {1616+ struct list_head list;1717+ u32 x_origin;1818+ u32 y_origin;1919+ u32 x_size;2020+ u32 y_size;2121+ u32 key;2222+ bool pressed;2323+ int slot;2424+};2525+2626+static int touch_overlay_get_segment(struct fwnode_handle *segment_node,2727+ struct touch_overlay_segment *segment,2828+ struct input_dev *input)2929+{3030+ int error;3131+3232+ error = fwnode_property_read_u32(segment_node, "x-origin",3333+ &segment->x_origin);3434+ if (error)3535+ return error;3636+3737+ error = fwnode_property_read_u32(segment_node, "y-origin",3838+ &segment->y_origin);3939+ if (error)4040+ return error;4141+4242+ error = fwnode_property_read_u32(segment_node, "x-size",4343+ &segment->x_size);4444+ if (error)4545+ return error;4646+4747+ error = fwnode_property_read_u32(segment_node, "y-size",4848+ &segment->y_size);4949+ if (error)5050+ return error;5151+5252+ error = fwnode_property_read_u32(segment_node, "linux,code",5353+ &segment->key);5454+ if (!error)5555+ input_set_capability(input, EV_KEY, segment->key);5656+ else if (error != -EINVAL)5757+ return error;5858+5959+ return 0;6060+}6161+6262+/**6363+ * touch_overlay_map - map overlay objects from the device tree and set6464+ * key capabilities if buttons are defined.6565+ * @list: pointer to the list that will hold the segments6666+ * @input: pointer to the already allocated input_dev6767+ *6868+ * Returns 0 on success and error number otherwise.6969+ *7070+ * If buttons are defined, key capabilities are set accordingly.7171+ */7272+int touch_overlay_map(struct list_head *list, struct input_dev *input)7373+{7474+ struct fwnode_handle *fw_segment;7575+ struct device *dev = input->dev.parent;7676+ struct touch_overlay_segment *segment;7777+ int error;7878+7979+ struct fwnode_handle *overlay __free(fwnode_handle) =8080+ device_get_named_child_node(dev, "touch-overlay");8181+ if (!overlay)8282+ return 0;8383+8484+ fwnode_for_each_available_child_node(overlay, fw_segment) {8585+ segment = devm_kzalloc(dev, sizeof(*segment), GFP_KERNEL);8686+ if (!segment) {8787+ fwnode_handle_put(fw_segment);8888+ return -ENOMEM;8989+ }9090+ error = touch_overlay_get_segment(fw_segment, segment, input);9191+ if (error) {9292+ fwnode_handle_put(fw_segment);9393+ return error;9494+ }9595+ list_add_tail(&segment->list, list);9696+ }9797+9898+ return 0;9999+}100100+EXPORT_SYMBOL(touch_overlay_map);101101+102102+/**103103+ * touch_overlay_get_touchscreen_abs - get abs size from the touchscreen area.104104+ * @list: pointer to the list that holds the segments105105+ * @x: horizontal abs106106+ * @y: vertical abs107107+ */108108+void touch_overlay_get_touchscreen_abs(struct list_head *list, u16 *x, u16 *y)109109+{110110+ struct touch_overlay_segment *segment;111111+ struct list_head *ptr;112112+113113+ list_for_each(ptr, list) {114114+ segment = list_entry(ptr, struct touch_overlay_segment, list);115115+ if (!segment->key) {116116+ *x = segment->x_size - 1;117117+ *y = segment->y_size - 1;118118+ break;119119+ }120120+ }121121+}122122+EXPORT_SYMBOL(touch_overlay_get_touchscreen_abs);123123+124124+static bool touch_overlay_segment_event(struct touch_overlay_segment *seg,125125+ struct input_mt_pos *pos)126126+{127127+ if (pos->x >= seg->x_origin && pos->x < (seg->x_origin + seg->x_size) &&128128+ pos->y >= seg->y_origin && pos->y < (seg->y_origin + seg->y_size))129129+ return true;130130+131131+ return false;132132+}133133+134134+/**135135+ * touch_overlay_mapped_touchscreen - check if a touchscreen area is mapped136136+ * @list: pointer to the list that holds the segments137137+ *138138+ * Returns true if a touchscreen area is mapped or false otherwise.139139+ */140140+bool touch_overlay_mapped_touchscreen(struct list_head *list)141141+{142142+ struct touch_overlay_segment *segment;143143+ struct list_head *ptr;144144+145145+ list_for_each(ptr, list) {146146+ segment = list_entry(ptr, struct touch_overlay_segment, list);147147+ if (!segment->key)148148+ return true;149149+ }150150+151151+ return false;152152+}153153+EXPORT_SYMBOL(touch_overlay_mapped_touchscreen);154154+155155+static bool touch_overlay_event_on_ts(struct list_head *list,156156+ struct input_mt_pos *pos)157157+{158158+ struct touch_overlay_segment *segment;159159+ struct list_head *ptr;160160+161161+ list_for_each(ptr, list) {162162+ segment = list_entry(ptr, struct touch_overlay_segment, list);163163+ if (segment->key)164164+ continue;165165+166166+ if (touch_overlay_segment_event(segment, pos)) {167167+ pos->x -= segment->x_origin;168168+ pos->y -= segment->y_origin;169169+ return true;170170+ }171171+ /* ignore touch events outside the defined area */172172+ return false;173173+ }174174+175175+ return true;176176+}177177+178178+static bool touch_overlay_button_event(struct input_dev *input,179179+ struct touch_overlay_segment *segment,180180+ struct input_mt_pos *pos, int slot)181181+{182182+ struct input_mt *mt = input->mt;183183+ struct input_mt_slot *s = &mt->slots[slot];184184+ bool button_contact = touch_overlay_segment_event(segment, pos);185185+186186+ if (segment->slot == slot && segment->pressed) {187187+ /* sliding out of the button releases it */188188+ if (!button_contact) {189189+ input_report_key(input, segment->key, false);190190+ segment->pressed = false;191191+ /* keep available for a possible touch event */192192+ return false;193193+ }194194+ /* ignore sliding on the button while pressed */195195+ s->frame = mt->frame;196196+ return true;197197+ } else if (button_contact) {198198+ input_report_key(input, segment->key, true);199199+ s->frame = mt->frame;200200+ segment->slot = slot;201201+ segment->pressed = true;202202+ return true;203203+ }204204+205205+ return false;206206+}207207+208208+/**209209+ * touch_overlay_sync_frame - update the status of the segments and report210210+ * buttons whose tracked slot is unused.211211+ * @list: pointer to the list that holds the segments212212+ * @input: pointer to the input device associated to the contact213213+ */214214+void touch_overlay_sync_frame(struct list_head *list, struct input_dev *input)215215+{216216+ struct touch_overlay_segment *segment;217217+ struct input_mt *mt = input->mt;218218+ struct input_mt_slot *s;219219+ struct list_head *ptr;220220+221221+ list_for_each(ptr, list) {222222+ segment = list_entry(ptr, struct touch_overlay_segment, list);223223+ if (!segment->key)224224+ continue;225225+226226+ s = &mt->slots[segment->slot];227227+ if (!input_mt_is_used(mt, s) && segment->pressed) {228228+ input_report_key(input, segment->key, false);229229+ segment->pressed = false;230230+ }231231+ }232232+}233233+EXPORT_SYMBOL(touch_overlay_sync_frame);234234+235235+/**236236+ * touch_overlay_process_contact - process contacts according to the overlay237237+ * mapping. This function acts as a filter to release the calling driver238238+ * from the contacts that are either related to overlay buttons or out of the239239+ * overlay touchscreen area, if defined.240240+ * @list: pointer to the list that holds the segments241241+ * @input: pointer to the input device associated to the contact242242+ * @pos: pointer to the contact position243243+ * @slot: slot associated to the contact (0 if multitouch is not supported)244244+ *245245+ * Returns true if the contact was processed (reported for valid key events246246+ * and dropped for contacts outside the overlay touchscreen area) or false247247+ * if the contact must be processed by the caller. In that case this function248248+ * shifts the (x,y) coordinates to the overlay touchscreen axis if required.249249+ */250250+bool touch_overlay_process_contact(struct list_head *list,251251+ struct input_dev *input,252252+ struct input_mt_pos *pos, int slot)253253+{254254+ struct touch_overlay_segment *segment;255255+ struct list_head *ptr;256256+257257+ /*258258+ * buttons must be prioritized over overlay touchscreens to account for259259+ * overlappings e.g. a button inside the touchscreen area.260260+ */261261+ list_for_each(ptr, list) {262262+ segment = list_entry(ptr, struct touch_overlay_segment, list);263263+ if (segment->key &&264264+ touch_overlay_button_event(input, segment, pos, slot))265265+ return true;266266+ }267267+268268+ /*269269+ * valid contacts on the overlay touchscreen are left for the client270270+ * to be processed/reported according to its (possibly) unique features.271271+ */272272+ return !touch_overlay_event_on_ts(list, pos);273273+}274274+EXPORT_SYMBOL(touch_overlay_process_contact);275275+276276+MODULE_LICENSE("GPL");277277+MODULE_DESCRIPTION("Helper functions for overlay objects on touch devices");
+7-4
drivers/input/touchscreen/ad7879.c
···444444 return !!(val & AD7879_GPIO_DATA);445445}446446447447-static void ad7879_gpio_set_value(struct gpio_chip *chip,448448- unsigned gpio, int value)447447+static int ad7879_gpio_set_value(struct gpio_chip *chip, unsigned int gpio,448448+ int value)449449{450450 struct ad7879 *ts = gpiochip_get_data(chip);451451+ int ret;451452452453 mutex_lock(&ts->mutex);453454 if (value)···456455 else457456 ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;458457459459- ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);458458+ ret = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);460459 mutex_unlock(&ts->mutex);460460+461461+ return ret;461462}462463463464static int ad7879_gpio_add(struct ad7879 *ts)···475472 ts->gc.direction_input = ad7879_gpio_direction_input;476473 ts->gc.direction_output = ad7879_gpio_direction_output;477474 ts->gc.get = ad7879_gpio_get_value;478478- ts->gc.set = ad7879_gpio_set_value;475475+ ts->gc.set_rv = ad7879_gpio_set_value;479476 ts->gc.can_sleep = 1;480477 ts->gc.base = -1;481478 ts->gc.ngpio = 1;