diff options
34 files changed, 1703 insertions, 1128 deletions
| diff --git a/Documentation/devicetree/bindings/input/adc-joystick.yaml b/Documentation/devicetree/bindings/input/adc-joystick.yaml index 2ee04e03bc22..64d961458ac7 100644 --- a/Documentation/devicetree/bindings/input/adc-joystick.yaml +++ b/Documentation/devicetree/bindings/input/adc-joystick.yaml @@ -45,6 +45,7 @@ additionalProperties: false  patternProperties:    "^axis@[0-9a-f]+$":      type: object +    $ref: input.yaml#      description: >        Represents a joystick axis bound to the given ADC channel.        For each entry in the io-channels list, one axis subnode with a matching @@ -57,7 +58,6 @@ patternProperties:          description: Index of an io-channels list entry bound to this axis.        linux,code: -        $ref: /schemas/types.yaml#/definitions/uint32          description: EV_ABS specific event code generated by the axis.        abs-range: diff --git a/Documentation/devicetree/bindings/input/adc-keys.txt b/Documentation/devicetree/bindings/input/adc-keys.txt deleted file mode 100644 index 6c8be6a9ace2..000000000000 --- a/Documentation/devicetree/bindings/input/adc-keys.txt +++ /dev/null @@ -1,67 +0,0 @@ -ADC attached resistor ladder buttons ------------------------------------- - -Required properties: - - compatible: "adc-keys" - - io-channels: Phandle to an ADC channel - - io-channel-names = "buttons"; - - keyup-threshold-microvolt: Voltage above or equal to which all the keys are -			      considered up. - -Optional properties: -	- poll-interval: Poll interval time in milliseconds -	- autorepeat: Boolean, Enable auto repeat feature of Linux input -	  subsystem. - -Each button (key) is represented as a sub-node of "adc-keys": - -Required subnode-properties: -	- label: Descriptive name of the key. -	- linux,code: Keycode to emit. -	- press-threshold-microvolt: voltage above or equal to which this key is -				     considered pressed. - -No two values of press-threshold-microvolt may be the same. -All values of press-threshold-microvolt must be less than -keyup-threshold-microvolt. - -Example: - -#include <dt-bindings/input/input.h> - -	adc-keys { -		compatible = "adc-keys"; -		io-channels = <&lradc 0>; -		io-channel-names = "buttons"; -		keyup-threshold-microvolt = <2000000>; - -		button-up { -			label = "Volume Up"; -			linux,code = <KEY_VOLUMEUP>; -			press-threshold-microvolt = <1500000>; -		}; - -		button-down { -			label = "Volume Down"; -			linux,code = <KEY_VOLUMEDOWN>; -			press-threshold-microvolt = <1000000>; -		}; - -		button-enter { -			label = "Enter"; -			linux,code = <KEY_ENTER>; -			press-threshold-microvolt = <500000>; -		}; -	}; - -+--------------------------------+------------------------+ -| 2.000.000 <= value             | no key pressed         | -+--------------------------------+------------------------+ -| 1.500.000 <= value < 2.000.000 | KEY_VOLUMEUP pressed   | -+--------------------------------+------------------------+ -| 1.000.000 <= value < 1.500.000 | KEY_VOLUMEDOWN pressed | -+--------------------------------+------------------------+ -|   500.000 <= value < 1.000.000 | KEY_ENTER pressed      | -+--------------------------------+------------------------+ -|              value <   500.000 | no key pressed         | -+--------------------------------+------------------------+ diff --git a/Documentation/devicetree/bindings/input/adc-keys.yaml b/Documentation/devicetree/bindings/input/adc-keys.yaml new file mode 100644 index 000000000000..7aa078dead37 --- /dev/null +++ b/Documentation/devicetree/bindings/input/adc-keys.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/adc-keys.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ADC attached resistor ladder buttons + +maintainers: +  - Alexandre Belloni <[email protected]> + +allOf: +  - $ref: input.yaml# + +properties: +  compatible: +    const: adc-keys + +  io-channels: +    maxItems: 1 + +  io-channel-names: +    const: buttons + +  keyup-threshold-microvolt: +    description: +      Voltage above or equal to which all the keys are considered up. + +  poll-interval: true +  autorepeat: true + +patternProperties: +  '^button-': +    type: object +    $ref: input.yaml# +    additionalProperties: false +    description: +      Each button (key) is represented as a sub-node. + +    properties: +      label: true + +      linux,code: true + +      press-threshold-microvolt: +        description: +          Voltage above or equal to which this key is considered pressed. No +          two values of press-threshold-microvolt may be the same. All values +          of press-threshold-microvolt must be less than +          keyup-threshold-microvolt. + +    required: +      - linux,code +      - press-threshold-microvolt + +required: +  - compatible +  - io-channels +  - io-channel-names +  - keyup-threshold-microvolt + +additionalProperties: false + +examples: +  - | +    #include <dt-bindings/input/input.h> +    // +--------------------------------+------------------------+ +    // | 2.000.000 <= value             | no key pressed         | +    // +--------------------------------+------------------------+ +    // | 1.500.000 <= value < 2.000.000 | KEY_VOLUMEUP pressed   | +    // +--------------------------------+------------------------+ +    // | 1.000.000 <= value < 1.500.000 | KEY_VOLUMEDOWN pressed | +    // +--------------------------------+------------------------+ +    // |   500.000 <= value < 1.000.000 | KEY_ENTER pressed      | +    // +--------------------------------+------------------------+ +    // |              value <   500.000 | no key pressed         | +    // +--------------------------------+------------------------+ + +    adc-keys { +        compatible = "adc-keys"; +        io-channels = <&lradc 0>; +        io-channel-names = "buttons"; +        keyup-threshold-microvolt = <2000000>; + +        button-up { +            label = "Volume Up"; +            linux,code = <KEY_VOLUMEUP>; +            press-threshold-microvolt = <1500000>; +        }; + +        button-down { +            label = "Volume Down"; +            linux,code = <KEY_VOLUMEDOWN>; +            press-threshold-microvolt = <1000000>; +        }; + +        button-enter { +            label = "Enter"; +            linux,code = <KEY_ENTER>; +            press-threshold-microvolt = <500000>; +        }; +    }; +... diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml index 3399fc288afb..9700dc468b25 100644 --- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml +++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml @@ -44,14 +44,13 @@ properties:  patternProperties:    "^button-[0-9]+$":      type: object +    $ref: input.yaml#      properties:        label:          $ref: /schemas/types.yaml#/definitions/string          description: Descriptive name of the key -      linux,code: -        $ref: /schemas/types.yaml#/definitions/uint32 -        description: Keycode to emit +      linux,code: true        channel:          $ref: /schemas/types.yaml#/definitions/uint32 diff --git a/Documentation/devicetree/bindings/input/ariel-pwrbutton.yaml b/Documentation/devicetree/bindings/input/ariel-pwrbutton.yaml index b4ad829d7383..442f623bb294 100644 --- a/Documentation/devicetree/bindings/input/ariel-pwrbutton.yaml +++ b/Documentation/devicetree/bindings/input/ariel-pwrbutton.yaml @@ -17,6 +17,7 @@ description: |  allOf:    - $ref: input.yaml# +  - $ref: /schemas/spi/spi-peripheral-props.yaml#  properties:    compatible: diff --git a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml index a3a1e5a65306..02e605fac408 100644 --- a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml +++ b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml @@ -37,10 +37,6 @@ properties:        device is temporarily held in hardware reset prior to initialization if        this property is present. -  azoteq,rf-filt-enable: -    type: boolean -    description: Enables the device's internal RF filter. -    azoteq,max-counts:      $ref: /schemas/types.yaml#/definitions/uint32      enum: [0, 1, 2, 3] @@ -421,6 +417,7 @@ patternProperties:      patternProperties:        "^event-(prox|touch)$":          type: object +        $ref: input.yaml#          description:            Represents a proximity or touch event reported by the channel. @@ -467,14 +464,9 @@ patternProperties:                The IQS7222B does not feature channel-specific timeouts; the time-                out specified for any one channel applies to all channels. -          linux,code: -            $ref: /schemas/types.yaml#/definitions/uint32 -            description: -              Numeric key or switch code associated with the event. Specify -              KEY_RESERVED (0) to opt out of event reporting. +          linux,code: true            linux,input-type: -            $ref: /schemas/types.yaml#/definitions/uint32              enum: [1, 5]              default: 1              description: @@ -537,9 +529,8 @@ patternProperties:        azoteq,bottom-speed:          $ref: /schemas/types.yaml#/definitions/uint32 -        multipleOf: 4          minimum: 0 -        maximum: 1020 +        maximum: 255          description:            Specifies the speed of movement after which coordinate filtering is            linearly reduced. @@ -575,14 +566,13 @@ patternProperties:      patternProperties:        "^event-(press|tap|(swipe|flick)-(pos|neg))$":          type: object +        $ref: input.yaml#          description:            Represents a press or gesture (IQS7222A only) event reported by            the slider.          properties: -          linux,code: -            $ref: /schemas/types.yaml#/definitions/uint32 -            description: Numeric key code associated with the event. +          linux,code: true            azoteq,gesture-max-ms:              multipleOf: 4 @@ -616,16 +606,15 @@ patternProperties:            azoteq,gpio-select:              $ref: /schemas/types.yaml#/definitions/uint32-array              minItems: 1 -            maxItems: 1 +            maxItems: 3              items:                minimum: 0 -              maximum: 0 +              maximum: 2              description: | -              Specifies an individual GPIO mapped to a tap, swipe or flick -              gesture as follows: +              Specifies one or more GPIO mapped to the event as follows:                0: GPIO0 -              1: GPIO3 (reserved) -              2: GPIO4 (reserved) +              1: GPIO3 (IQS7222C only) +              2: GPIO4 (IQS7222C only)                Note that although multiple events can be mapped to a single                GPIO, they must all be of the same type (proximity, touch or @@ -710,6 +699,14 @@ allOf:                multipleOf: 4                maximum: 1020 +          patternProperties: +            "^event-(press|tap|(swipe|flick)-(pos|neg))$": +              properties: +                azoteq,gpio-select: +                  maxItems: 1 +                  items: +                    maximum: 0 +      else:        patternProperties:          "^channel-([0-9]|1[0-9])$": @@ -726,8 +723,6 @@ allOf:                  azoteq,gesture-dist: false -                azoteq,gpio-select: false -  required:    - compatible    - reg diff --git a/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml index 878464f128dc..5139af287d3e 100644 --- a/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml +++ b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml @@ -57,7 +57,7 @@ examples:          #address-cells = <1>;          #size-cells = <0>; -        mpr121@5a { +        touchkey@5a {              compatible = "fsl,mpr121-touchkey";              reg = <0x5a>;              interrupt-parent = <&gpio1>; @@ -77,7 +77,7 @@ examples:          #address-cells = <1>;          #size-cells = <0>; -        mpr121@5a { +        touchkey@5a {              compatible = "fsl,mpr121-touchkey";              reg = <0x5a>;              poll-interval = <20>; diff --git a/Documentation/devicetree/bindings/input/gpio-keys.yaml b/Documentation/devicetree/bindings/input/gpio-keys.yaml index 7fe1966ea28a..17ac9dff7972 100644 --- a/Documentation/devicetree/bindings/input/gpio-keys.yaml +++ b/Documentation/devicetree/bindings/input/gpio-keys.yaml @@ -15,107 +15,106 @@ properties:        - gpio-keys        - gpio-keys-polled +  autorepeat: true + +  label: +    description: Name of entire device + +  poll-interval: true +  patternProperties: -  ".*": -    if: -      type: object -    then: -      $ref: input.yaml# +  "^(button|event|key|switch|(button|event|key|switch)-[a-z0-9-]+|[a-z0-9-]+-(button|event|key|switch))$": +    $ref: input.yaml# -      properties: -        gpios: -          maxItems: 1 +    properties: +      gpios: +        maxItems: 1 + +      interrupts: +        maxItems: 1 -        interrupts: -          maxItems: 1 +      label: +        description: Descriptive name of the key. -        label: -          description: Descriptive name of the key. +      linux,code: +        description: Key / Axis code to emit. -        linux,code: -          description: Key / Axis code to emit. -          $ref: /schemas/types.yaml#/definitions/uint32 +      linux,input-type: +        default: 1  # EV_KEY -        linux,input-type: -          description: -            Specify event type this button/key generates. If not specified defaults to -            <1> == EV_KEY. -          $ref: /schemas/types.yaml#/definitions/uint32 +      linux,input-value: +        description: | +          If linux,input-type is EV_ABS or EV_REL then this +          value is sent for events this button generates when pressed. +          EV_ABS/EV_REL axis will generate an event with a value of 0 +          when all buttons with linux,input-type == type and +          linux,code == axis are released. This value is interpreted +          as a signed 32 bit value, e.g. to make a button generate a +          value of -1 use: -          default: 1 +          linux,input-value = <0xffffffff>; /* -1 */ -        linux,input-value: -          description: | -            If linux,input-type is EV_ABS or EV_REL then this -            value is sent for events this button generates when pressed. -            EV_ABS/EV_REL axis will generate an event with a value of 0 -            when all buttons with linux,input-type == type and -            linux,code == axis are released. This value is interpreted -            as a signed 32 bit value, e.g. to make a button generate a -            value of -1 use: +        $ref: /schemas/types.yaml#/definitions/uint32 -            linux,input-value = <0xffffffff>; /* -1 */ +      debounce-interval: +        description: +          Debouncing interval time in milliseconds. If not specified defaults to 5. +        $ref: /schemas/types.yaml#/definitions/uint32 -          $ref: /schemas/types.yaml#/definitions/uint32 +        default: 5 -        debounce-interval: -          description: -            Debouncing interval time in milliseconds. If not specified defaults to 5. -          $ref: /schemas/types.yaml#/definitions/uint32 +      wakeup-source: +        description: Button can wake-up the system. -          default: 5 +      wakeup-event-action: +        description: | +          Specifies whether the key should wake the system when asserted, when +          deasserted, or both. This property is only valid for keys that wake up the +          system (e.g., when the "wakeup-source" property is also provided). -        wakeup-source: -          description: Button can wake-up the system. +          Supported values are defined in linux-event-codes.h: -        wakeup-event-action: -          description: | -            Specifies whether the key should wake the system when asserted, when -            deasserted, or both. This property is only valid for keys that wake up the -            system (e.g., when the "wakeup-source" property is also provided). +            EV_ACT_ANY        - both asserted and deasserted +            EV_ACT_ASSERTED   - asserted +            EV_ACT_DEASSERTED - deasserted +        $ref: /schemas/types.yaml#/definitions/uint32 +        enum: [0, 1, 2] -            Supported values are defined in linux-event-codes.h: +      linux,can-disable: +        description: +          Indicates that button is connected to dedicated (not shared) interrupt +          which can be disabled to suppress events from the button. +        type: boolean -              EV_ACT_ANY        - both asserted and deasserted -              EV_ACT_ASSERTED   - asserted -              EV_ACT_DEASSERTED - deasserted -          $ref: /schemas/types.yaml#/definitions/uint32 -          enum: [0, 1, 2] +    required: +      - linux,code -        linux,can-disable: -          description: -            Indicates that button is connected to dedicated (not shared) interrupt -            which can be disabled to suppress events from the button. -          type: boolean +    anyOf: +      - required: +          - interrupts +      - required: +          - interrupts-extended +      - required: +          - gpios +    dependencies: +      wakeup-event-action: [ wakeup-source ] +      linux,input-value: [ gpios ] + +    unevaluatedProperties: false + +allOf: +  - $ref: input.yaml# +  - if: +      properties: +        compatible: +          const: gpio-keys-polled +    then:        required: -        - linux,code - -      anyOf: -        - required: -            - interrupts -        - required: -            - gpios - -      dependencies: -        wakeup-event-action: [ wakeup-source ] -        linux,input-value: [ gpios ] - -      unevaluatedProperties: false - -if: -  properties: -    compatible: -      const: gpio-keys-polled -then: -  properties: -    poll-interval: -      description: -        Poll interval time in milliseconds -      $ref: /schemas/types.yaml#/definitions/uint32 - -  required: -    - poll-interval +        - poll-interval +    else: +      properties: +        poll-interval: false  additionalProperties: false @@ -127,13 +126,13 @@ examples:          compatible = "gpio-keys";          autorepeat; -        up { +        key-up {              label = "GPIO Key UP";              linux,code = <103>;              gpios = <&gpio1 0 1>;          }; -        down { +        key-down {              label = "GPIO Key DOWN";              linux,code = <108>;              interrupts = <1 IRQ_TYPE_EDGE_FALLING>; diff --git a/Documentation/devicetree/bindings/input/input.yaml b/Documentation/devicetree/bindings/input/input.yaml index d41d8743aad4..17512f4347fd 100644 --- a/Documentation/devicetree/bindings/input/input.yaml +++ b/Documentation/devicetree/bindings/input/input.yaml @@ -21,7 +21,26 @@ properties:      $ref: /schemas/types.yaml#/definitions/uint32-array      items:        minimum: 0 -      maximum: 0xff +      maximum: 0x2ff + +  linux,code: +    description: +      Specifies a single numeric keycode value to be used for reporting +      button/switch events. Specify KEY_RESERVED (0) to opt out of event +      reporting. +    $ref: /schemas/types.yaml#/definitions/uint32 +    maximum: 0x2ff + +  linux,input-type: +    $ref: /schemas/types.yaml#/definitions/uint32 +    enum: +      - 1   # EV_KEY +      - 2   # EV_REL +      - 3   # EV_ABS +      - 5   # EV_SW +    description: +      Specifies whether the event is to be interpreted as a key, relative, +      absolute, or switch.    poll-interval:      description: Poll interval time in milliseconds. @@ -39,4 +58,7 @@ properties:        reset automatically. Device with key pressed reset feature can specify        this property. +dependencies: +  linux,input-type: [ "linux,code" ] +  additionalProperties: true diff --git a/Documentation/devicetree/bindings/input/iqs269a.yaml b/Documentation/devicetree/bindings/input/iqs269a.yaml index 9c154e5e1a91..3c430d38594f 100644 --- a/Documentation/devicetree/bindings/input/iqs269a.yaml +++ b/Documentation/devicetree/bindings/input/iqs269a.yaml @@ -370,6 +370,7 @@ patternProperties:      patternProperties:        "^event-prox(-alt)?$":          type: object +        $ref: input.yaml#          description:            Represents a proximity event reported by the channel in response to            a decrease in counts. Node names suffixed with '-alt' instead corre- @@ -396,14 +397,13 @@ patternProperties:              default: 10              description: Specifies the threshold for the event. -          linux,code: -            $ref: /schemas/types.yaml#/definitions/uint32 -            description: Numeric key or switch code associated with the event. +          linux,code: true          additionalProperties: false        "^event-touch(-alt)?$":          type: object +        $ref: input.yaml#          description: Represents a touch event reported by the channel.          properties: @@ -421,14 +421,13 @@ patternProperties:              default: 4              description: Specifies the hysteresis for the event. -          linux,code: -            $ref: /schemas/types.yaml#/definitions/uint32 -            description: Numeric key or switch code associated with the event. +          linux,code: true          additionalProperties: false        "^event-deep(-alt)?$":          type: object +        $ref: input.yaml#          description: Represents a deep-touch event reported by the channel.          properties: @@ -446,9 +445,7 @@ patternProperties:              default: 0              description: Specifies the hysteresis for the event. -          linux,code: -            $ref: /schemas/types.yaml#/definitions/uint32 -            description: Numeric key or switch code associated with the event. +          linux,code: true          additionalProperties: false @@ -475,7 +472,7 @@ examples:              #address-cells = <1>;              #size-cells = <0>; -            iqs269a@44 { +            touch@44 {                      #address-cells = <1>;                      #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/input/iqs626a.yaml b/Documentation/devicetree/bindings/input/iqs626a.yaml index 0cb736c541c9..7a27502095f3 100644 --- a/Documentation/devicetree/bindings/input/iqs626a.yaml +++ b/Documentation/devicetree/bindings/input/iqs626a.yaml @@ -449,6 +449,7 @@ patternProperties:      patternProperties:        "^event-(prox|touch|deep)(-alt)?$":          type: object +        $ref: input.yaml#          description:            Represents a proximity, touch or deep-touch event reported by the            channel in response to a decrease in counts. Node names suffixed with @@ -487,21 +488,15 @@ patternProperties:                Specifies the hysteresis for the event (touch and deep-touch                events only). -          linux,code: -            $ref: /schemas/types.yaml#/definitions/uint32 -            description: Numeric key or switch code associated with the event. +          linux,code: true            linux,input-type: -            $ref: /schemas/types.yaml#/definitions/uint32              enum: [1, 5]              description:                Specifies whether the event is to be interpreted as a key (1) or                a switch (5). By default, Hall-channel events are interpreted as                switches and all others are interpreted as keys. -        dependencies: -          linux,input-type: ["linux,code"] -          additionalProperties: false      dependencies: @@ -511,6 +506,7 @@ patternProperties:    "^trackpad-3x[2-3]$":      type: object +    $ref: input.yaml#      description:        Represents all channels associated with the trackpad. The channels are        collectively active if the trackpad is defined and inactive otherwise. @@ -679,7 +675,6 @@ patternProperties:            Specifies the raw count filter strength during low-power mode.        linux,keycodes: -        $ref: /schemas/types.yaml#/definitions/uint32-array          minItems: 1          maxItems: 6          description: | @@ -751,7 +746,7 @@ examples:              #address-cells = <1>;              #size-cells = <0>; -            iqs626a@44 { +            touch@44 {                      #address-cells = <1>;                      #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/input/iqs62x-keys.yaml b/Documentation/devicetree/bindings/input/iqs62x-keys.yaml index 77fe3b545b35..0aa951f0ab92 100644 --- a/Documentation/devicetree/bindings/input/iqs62x-keys.yaml +++ b/Documentation/devicetree/bindings/input/iqs62x-keys.yaml @@ -9,6 +9,9 @@ title: Azoteq IQS620A/621/622/624/625 Keys and Switches  maintainers:    - Jeff LaBundy <[email protected]> +allOf: +  - $ref: input.yaml# +  description: |    The Azoteq IQS620A, IQS621, IQS622, IQS624 and IQS625 multi-function sensors    feature a variety of self-capacitive, mutual-inductive and Hall-effect sens- @@ -30,7 +33,6 @@ properties:        - azoteq,iqs625-keys    linux,keycodes: -    $ref: /schemas/types.yaml#/definitions/uint32-array      minItems: 1      maxItems: 16      description: | @@ -89,15 +91,14 @@ properties:  patternProperties:    "^hall-switch-(north|south)$":      type: object +    $ref: input.yaml#      description:        Represents north/south-field Hall-effect sensor touch or proximity        events. Note that north/south-field orientation is reversed on the        IQS620AXzCSR device due to its flip-chip package.      properties: -      linux,code: -        $ref: /schemas/types.yaml#/definitions/uint32 -        description: Numeric switch code associated with the event. +      linux,code: true        azoteq,use-prox:          $ref: /schemas/types.yaml#/definitions/flag diff --git a/Documentation/devicetree/bindings/input/max77650-onkey.yaml b/Documentation/devicetree/bindings/input/max77650-onkey.yaml index 3a2ad6ec64db..48edc0c8c1dd 100644 --- a/Documentation/devicetree/bindings/input/max77650-onkey.yaml +++ b/Documentation/devicetree/bindings/input/max77650-onkey.yaml @@ -16,15 +16,15 @@ description: |    The onkey controller is represented as a sub-node of the PMIC node on    the device tree. +allOf: +  - $ref: input.yaml# +  properties:    compatible:      const: maxim,max77650-onkey    linux,code: -    $ref: /schemas/types.yaml#/definitions/uint32 -    description: -      The key-code to be reported when the key is pressed. Defaults -      to KEY_POWER. +    default: 116  # KEY_POWER    maxim,onkey-slide:      $ref: /schemas/types.yaml#/definitions/flag diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml index d5d6bced3148..96358b12f9b2 100644 --- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml +++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml @@ -112,7 +112,7 @@ examples:        #address-cells = <1>;        #size-cells = <0>; -      cap1188@28 { +      touch@28 {          compatible = "microchip,cap1188";          interrupt-parent = <&gpio1>;          interrupts = <0 0>; diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml index 2e8da7470513..46bc8c028fe6 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml @@ -85,6 +85,14 @@ properties:      minimum: 0      maximum: 80 +  report-rate-hz: +    description: | +                 Allows setting the scan rate in Hertz. +                  M06 supports range from 30 to 140 Hz. +                  M12 supports range from 1 to 255 Hz. +    minimum: 1 +    maximum: 255 +    touchscreen-size-x: true    touchscreen-size-y: true    touchscreen-fuzz-x: true diff --git a/drivers/input/input-core-private.h b/drivers/input/input-core-private.h new file mode 100644 index 000000000000..116834cf8868 --- /dev/null +++ b/drivers/input/input-core-private.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _INPUT_CORE_PRIVATE_H +#define _INPUT_CORE_PRIVATE_H + +/* + * Functions and definitions that are private to input core, + * should not be used by input drivers or handlers. + */ + +struct input_dev; + +void input_mt_release_slots(struct input_dev *dev); +void input_handle_event(struct input_dev *dev, +			unsigned int type, unsigned int code, int value); + +#endif /* _INPUT_CORE_PRIVATE_H */ diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 44fe6f2f063c..14b53dac1253 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -8,6 +8,7 @@  #include <linux/input/mt.h>  #include <linux/export.h>  #include <linux/slab.h> +#include "input-core-private.h"  #define TRKID_SGN	((TRKID_MAX + 1) >> 1) @@ -259,10 +260,13 @@ static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)  {  	int i; +	lockdep_assert_held(&dev->event_lock); +  	for (i = 0; i < mt->num_slots; i++) { -		if (!input_mt_is_used(mt, &mt->slots[i])) { -			input_mt_slot(dev, i); -			input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); +		if (input_mt_is_active(&mt->slots[i]) && +		    !input_mt_is_used(mt, &mt->slots[i])) { +			input_handle_event(dev, EV_ABS, ABS_MT_SLOT, i); +			input_handle_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);  		}  	}  } @@ -278,13 +282,44 @@ void input_mt_drop_unused(struct input_dev *dev)  	struct input_mt *mt = dev->mt;  	if (mt) { +		unsigned long flags; + +		spin_lock_irqsave(&dev->event_lock, flags); +  		__input_mt_drop_unused(dev, mt);  		mt->frame++; + +		spin_unlock_irqrestore(&dev->event_lock, flags);  	}  }  EXPORT_SYMBOL(input_mt_drop_unused);  /** + * input_mt_release_slots() - Deactivate all slots + * @dev: input device with allocated MT slots + * + * Lift all active slots. + */ +void input_mt_release_slots(struct input_dev *dev) +{ +	struct input_mt *mt = dev->mt; + +	lockdep_assert_held(&dev->event_lock); + +	if (mt) { +		/* This will effectively mark all slots unused. */ +		mt->frame++; + +		__input_mt_drop_unused(dev, mt); + +		if (test_bit(ABS_PRESSURE, dev->absbit)) +			input_handle_event(dev, EV_ABS, ABS_PRESSURE, 0); + +		mt->frame++; +	} +} + +/**   * input_mt_sync_frame() - synchronize mt frame   * @dev: input device with allocated MT slots   * @@ -300,8 +335,13 @@ void input_mt_sync_frame(struct input_dev *dev)  	if (!mt)  		return; -	if (mt->flags & INPUT_MT_DROP_UNUSED) +	if (mt->flags & INPUT_MT_DROP_UNUSED) { +		unsigned long flags; + +		spin_lock_irqsave(&dev->event_lock, flags);  		__input_mt_drop_unused(dev, mt); +		spin_unlock_irqrestore(&dev->event_lock, flags); +	}  	if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))  		use_count = true; diff --git a/drivers/input/input.c b/drivers/input/input.c index 1365c9dfb5f2..ebb2b7f0f8ff 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -24,6 +24,7 @@  #include <linux/mutex.h>  #include <linux/rcupdate.h>  #include "input-compat.h" +#include "input-core-private.h"  #include "input-poller.h"  MODULE_AUTHOR("Vojtech Pavlik <[email protected]>"); @@ -142,6 +143,8 @@ static void input_pass_values(struct input_dev *dev,  	struct input_handle *handle;  	struct input_value *v; +	lockdep_assert_held(&dev->event_lock); +  	if (!count)  		return; @@ -174,44 +177,6 @@ static void input_pass_values(struct input_dev *dev,  	}  } -static void input_pass_event(struct input_dev *dev, -			     unsigned int type, unsigned int code, int value) -{ -	struct input_value vals[] = { { type, code, value } }; - -	input_pass_values(dev, vals, ARRAY_SIZE(vals)); -} - -/* - * Generate software autorepeat event. Note that we take - * dev->event_lock here to avoid racing with input_event - * which may cause keys get "stuck". - */ -static void input_repeat_key(struct timer_list *t) -{ -	struct input_dev *dev = from_timer(dev, t, timer); -	unsigned long flags; - -	spin_lock_irqsave(&dev->event_lock, flags); - -	if (test_bit(dev->repeat_key, dev->key) && -	    is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { -		struct input_value vals[] =  { -			{ EV_KEY, dev->repeat_key, 2 }, -			input_value_sync -		}; - -		input_set_timestamp(dev, ktime_get()); -		input_pass_values(dev, vals, ARRAY_SIZE(vals)); - -		if (dev->rep[REP_PERIOD]) -			mod_timer(&dev->timer, jiffies + -					msecs_to_jiffies(dev->rep[REP_PERIOD])); -	} - -	spin_unlock_irqrestore(&dev->event_lock, flags); -} -  #define INPUT_IGNORE_EVENT	0  #define INPUT_PASS_TO_HANDLERS	1  #define INPUT_PASS_TO_DEVICE	2 @@ -275,6 +240,10 @@ static int input_get_disposition(struct input_dev *dev,  	int disposition = INPUT_IGNORE_EVENT;  	int value = *pval; +	/* filter-out events from inhibited devices */ +	if (dev->inhibited) +		return INPUT_IGNORE_EVENT; +  	switch (type) {  	case EV_SYN: @@ -375,19 +344,9 @@ static int input_get_disposition(struct input_dev *dev,  	return disposition;  } -static void input_handle_event(struct input_dev *dev, -			       unsigned int type, unsigned int code, int value) +static void input_event_dispose(struct input_dev *dev, int disposition, +				unsigned int type, unsigned int code, int value)  { -	int disposition; - -	/* filter-out events from inhibited devices */ -	if (dev->inhibited) -		return; - -	disposition = input_get_disposition(dev, type, code, &value); -	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) -		add_input_randomness(type, code, value); -  	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)  		dev->event(dev, type, code, value); @@ -426,7 +385,22 @@ static void input_handle_event(struct input_dev *dev,  		input_pass_values(dev, dev->vals, dev->num_vals);  		dev->num_vals = 0;  	} +} +void input_handle_event(struct input_dev *dev, +			unsigned int type, unsigned int code, int value) +{ +	int disposition; + +	lockdep_assert_held(&dev->event_lock); + +	disposition = input_get_disposition(dev, type, code, &value); +	if (disposition != INPUT_IGNORE_EVENT) { +		if (type != EV_SYN) +			add_input_randomness(type, code, value); + +		input_event_dispose(dev, disposition, type, code, value); +	}  }  /** @@ -613,7 +587,7 @@ static void __input_release_device(struct input_handle *handle)  					    lockdep_is_held(&dev->mutex));  	if (grabber == handle) {  		rcu_assign_pointer(dev->grab, NULL); -		/* Make sure input_pass_event() notices that grab is gone */ +		/* Make sure input_pass_values() notices that grab is gone */  		synchronize_rcu();  		list_for_each_entry(handle, &dev->h_list, d_node) @@ -736,7 +710,7 @@ void input_close_device(struct input_handle *handle)  	if (!--handle->open) {  		/* -		 * synchronize_rcu() makes sure that input_pass_event() +		 * synchronize_rcu() makes sure that input_pass_values()  		 * completed and that no more input events are delivered  		 * through this handle  		 */ @@ -751,22 +725,21 @@ EXPORT_SYMBOL(input_close_device);   * Simulate keyup events for all keys that are marked as pressed.   * The function must be called with dev->event_lock held.   */ -static void input_dev_release_keys(struct input_dev *dev) +static bool input_dev_release_keys(struct input_dev *dev)  {  	bool need_sync = false;  	int code; +	lockdep_assert_held(&dev->event_lock); +  	if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {  		for_each_set_bit(code, dev->key, KEY_CNT) { -			input_pass_event(dev, EV_KEY, code, 0); +			input_handle_event(dev, EV_KEY, code, 0);  			need_sync = true;  		} - -		if (need_sync) -			input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - -		memset(dev->key, 0, sizeof(dev->key));  	} + +	return need_sync;  }  /* @@ -793,7 +766,8 @@ static void input_disconnect_device(struct input_dev *dev)  	 * generate events even after we done here but they will not  	 * reach any handlers.  	 */ -	input_dev_release_keys(dev); +	if (input_dev_release_keys(dev)) +		input_handle_event(dev, EV_SYN, SYN_REPORT, 1);  	list_for_each_entry(handle, &dev->h_list, d_node)  		handle->open = 0; @@ -1004,12 +978,16 @@ int input_set_keycode(struct input_dev *dev,  	} else if (test_bit(EV_KEY, dev->evbit) &&  		   !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&  		   __test_and_clear_bit(old_keycode, dev->key)) { -		struct input_value vals[] =  { -			{ EV_KEY, old_keycode, 0 }, -			input_value_sync -		}; - -		input_pass_values(dev, vals, ARRAY_SIZE(vals)); +		/* +		 * We have to use input_event_dispose() here directly instead +		 * of input_handle_event() because the key we want to release +		 * here is considered no longer supported by the device and +		 * input_handle_event() will ignore it. +		 */ +		input_event_dispose(dev, INPUT_PASS_TO_HANDLERS, +				    EV_KEY, old_keycode, 0); +		input_event_dispose(dev, INPUT_PASS_TO_HANDLERS | INPUT_FLUSH, +				    EV_SYN, SYN_REPORT, 1);  	}   out: @@ -1784,7 +1762,8 @@ void input_reset_device(struct input_dev *dev)  	spin_lock_irqsave(&dev->event_lock, flags);  	input_dev_toggle(dev, true); -	input_dev_release_keys(dev); +	if (input_dev_release_keys(dev)) +		input_handle_event(dev, EV_SYN, SYN_REPORT, 1);  	spin_unlock_irqrestore(&dev->event_lock, flags);  	mutex_unlock(&dev->mutex); @@ -1806,7 +1785,9 @@ static int input_inhibit_device(struct input_dev *dev)  	}  	spin_lock_irq(&dev->event_lock); +	input_mt_release_slots(dev);  	input_dev_release_keys(dev); +	input_handle_event(dev, EV_SYN, SYN_REPORT, 1);  	input_dev_toggle(dev, false);  	spin_unlock_irq(&dev->event_lock); @@ -1857,7 +1838,8 @@ static int input_dev_suspend(struct device *dev)  	 * Keys that are pressed now are unlikely to be  	 * still pressed when we resume.  	 */ -	input_dev_release_keys(input_dev); +	if (input_dev_release_keys(input_dev)) +		input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1);  	/* Turn off LEDs and sounds, if any are active. */  	input_dev_toggle(input_dev, false); @@ -1891,7 +1873,8 @@ static int input_dev_freeze(struct device *dev)  	 * Keys that are pressed now are unlikely to be  	 * still pressed when we resume.  	 */ -	input_dev_release_keys(input_dev); +	if (input_dev_release_keys(input_dev)) +		input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1);  	spin_unlock_irq(&input_dev->event_lock); @@ -2259,6 +2242,34 @@ static void devm_input_device_unregister(struct device *dev, void *res)  	__input_unregister_device(input);  } +/* + * Generate software autorepeat event. Note that we take + * dev->event_lock here to avoid racing with input_event + * which may cause keys get "stuck". + */ +static void input_repeat_key(struct timer_list *t) +{ +	struct input_dev *dev = from_timer(dev, t, timer); +	unsigned long flags; + +	spin_lock_irqsave(&dev->event_lock, flags); + +	if (!dev->inhibited && +	    test_bit(dev->repeat_key, dev->key) && +	    is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { + +		input_set_timestamp(dev, ktime_get()); +		input_handle_event(dev, EV_KEY, dev->repeat_key, 2); +		input_handle_event(dev, EV_SYN, SYN_REPORT, 1); + +		if (dev->rep[REP_PERIOD]) +			mod_timer(&dev->timer, jiffies + +					msecs_to_jiffies(dev->rep[REP_PERIOD])); +	} + +	spin_unlock_irqrestore(&dev->event_lock, flags); +} +  /**   * input_enable_softrepeat - enable software autorepeat   * @dev: input device diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c index 78ebca7d400a..e0cfdc84763f 100644 --- a/drivers/input/joystick/adc-joystick.c +++ b/drivers/input/joystick/adc-joystick.c @@ -222,13 +222,6 @@ static int adc_joystick_probe(struct platform_device *pdev)  	if (error)  		return error; -	input_set_drvdata(input, joy); -	error = input_register_device(input); -	if (error) { -		dev_err(dev, "Unable to register input device\n"); -		return error; -	} -  	joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);  	if (IS_ERR(joy->buffer)) {  		dev_err(dev, "Unable to allocate callback buffer\n"); @@ -241,6 +234,14 @@ static int adc_joystick_probe(struct platform_device *pdev)  		return error;  	} +	input_set_drvdata(input, joy); + +	error = input_register_device(input); +	if (error) { +		dev_err(dev, "Unable to register input device\n"); +		return error; +	} +  	return 0;  } diff --git a/drivers/input/joystick/sensehat-joystick.c b/drivers/input/joystick/sensehat-joystick.c index 5ad1fe4ff496..a84df39d3b2f 100644 --- a/drivers/input/joystick/sensehat-joystick.c +++ b/drivers/input/joystick/sensehat-joystick.c @@ -98,10 +98,8 @@ static int sensehat_joystick_probe(struct platform_device *pdev)  	}  	irq = platform_get_irq(pdev, 0); -	if (irq < 0) { -		dev_err(&pdev->dev, "Could not retrieve interrupt request"); +	if (irq < 0)  		return irq; -	}  	error = devm_request_threaded_irq(&pdev->dev, irq,  					  NULL, sensehat_joystick_report, diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 4ea79db8f134..a20ee693b22b 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -795,7 +795,7 @@ config KEYBOARD_MT6779  config KEYBOARD_MTK_PMIC  	tristate "MediaTek PMIC keys support" -	depends on MFD_MT6397 +	depends on MFD_MT6397 || COMPILE_TEST  	help  	  Say Y here if you want to use the pmic keys (powerkey/homekey). diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 1592da4de336..1a1a05d7cd42 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -8,17 +8,19 @@   * Copyright (C) 2008-2010 Analog Devices Inc.   */ -#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/gpio/driver.h> +#include <linux/i2c.h> +#include <linux/input.h>  #include <linux/interrupt.h>  #include <linux/irq.h> -#include <linux/workqueue.h> -#include <linux/errno.h> -#include <linux/pm.h> +#include <linux/ktime.h> +#include <linux/module.h>  #include <linux/platform_device.h> -#include <linux/input.h> -#include <linux/i2c.h> -#include <linux/gpio/driver.h> +#include <linux/pm.h>  #include <linux/slab.h> +#include <linux/timekeeping.h>  #include <linux/platform_data/adp5588.h> @@ -36,18 +38,18 @@   * asserted.   */  #define WA_DELAYED_READOUT_REVID(rev)		((rev) < 4) +#define WA_DELAYED_READOUT_TIME			25  struct adp5588_kpad {  	struct i2c_client *client;  	struct input_dev *input; -	struct delayed_work work; +	ktime_t irq_time;  	unsigned long delay;  	unsigned short keycode[ADP5588_KEYMAPSIZE];  	const struct adp5588_gpi_map *gpimap;  	unsigned short gpimapsize;  #ifdef CONFIG_GPIOLIB  	unsigned char gpiomap[ADP5588_MAXGPIO]; -	bool export_gpio;  	struct gpio_chip gc;  	struct mutex gpio_lock;	/* Protect cached dir, dat_out */  	u8 dat_out[3]; @@ -179,6 +181,21 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,  	return n_unused;  } +static void adp5588_gpio_do_teardown(void *_kpad) +{ +	struct adp5588_kpad *kpad = _kpad; +	struct device *dev = &kpad->client->dev; +	const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev); +	const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; +	int error; + +	error = gpio_data->teardown(kpad->client, +				    kpad->gc.base, kpad->gc.ngpio, +				    gpio_data->context); +	if (error) +		dev_warn(&kpad->client->dev, "teardown failed %d\n", error); +} +  static int adp5588_gpio_add(struct adp5588_kpad *kpad)  {  	struct device *dev = &kpad->client->dev; @@ -195,8 +212,6 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)  		return 0;  	} -	kpad->export_gpio = true; -  	kpad->gc.direction_input = adp5588_gpio_direction_input;  	kpad->gc.direction_output = adp5588_gpio_direction_output;  	kpad->gc.get = adp5588_gpio_get_value; @@ -210,9 +225,9 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)  	mutex_init(&kpad->gpio_lock); -	error = gpiochip_add_data(&kpad->gc, kpad); +	error = devm_gpiochip_add_data(dev, &kpad->gc, kpad);  	if (error) { -		dev_err(dev, "gpiochip_add failed, err: %d\n", error); +		dev_err(dev, "gpiochip_add failed: %d\n", error);  		return error;  	} @@ -227,41 +242,24 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)  					 kpad->gc.base, kpad->gc.ngpio,  					 gpio_data->context);  		if (error) -			dev_warn(dev, "setup failed, %d\n", error); +			dev_warn(dev, "setup failed: %d\n", error);  	} -	return 0; -} - -static void adp5588_gpio_remove(struct adp5588_kpad *kpad) -{ -	struct device *dev = &kpad->client->dev; -	const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev); -	const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; -	int error; - -	if (!kpad->export_gpio) -		return; -  	if (gpio_data->teardown) { -		error = gpio_data->teardown(kpad->client, -					    kpad->gc.base, kpad->gc.ngpio, -					    gpio_data->context); +		error = devm_add_action(dev, adp5588_gpio_do_teardown, kpad);  		if (error) -			dev_warn(dev, "teardown failed %d\n", error); +			dev_warn(dev, "failed to schedule teardown: %d\n", +				 error);  	} -	gpiochip_remove(&kpad->gc); +	return 0;  } +  #else  static inline int adp5588_gpio_add(struct adp5588_kpad *kpad)  {  	return 0;  } - -static inline void adp5588_gpio_remove(struct adp5588_kpad *kpad) -{ -}  #endif  static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt) @@ -289,13 +287,36 @@ static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)  	}  } -static void adp5588_work(struct work_struct *work) +static irqreturn_t adp5588_hard_irq(int irq, void *handle)  { -	struct adp5588_kpad *kpad = container_of(work, -						struct adp5588_kpad, work.work); +	struct adp5588_kpad *kpad = handle; + +	kpad->irq_time = ktime_get(); + +	return IRQ_WAKE_THREAD; +} + +static irqreturn_t adp5588_thread_irq(int irq, void *handle) +{ +	struct adp5588_kpad *kpad = handle;  	struct i2c_client *client = kpad->client; +	ktime_t target_time, now; +	unsigned long delay;  	int status, ev_cnt; +	/* +	 * Readout needs to wait for at least 25ms after the notification +	 * for REVID < 4. +	 */ +	if (kpad->delay) { +		target_time = ktime_add_ms(kpad->irq_time, kpad->delay); +		now = ktime_get(); +		if (ktime_before(now, target_time)) { +			delay = ktime_to_us(ktime_sub(target_time, now)); +			usleep_range(delay, delay + 1000); +		} +	} +  	status = adp5588_read(client, INT_STAT);  	if (status & ADP5588_OVR_FLOW_INT)	/* Unlikely and should never happen */ @@ -308,20 +329,8 @@ static void adp5588_work(struct work_struct *work)  			input_sync(kpad->input);  		}  	} -	adp5588_write(client, INT_STAT, status); /* Status is W1C */ -} - -static irqreturn_t adp5588_irq(int irq, void *handle) -{ -	struct adp5588_kpad *kpad = handle; -	/* -	 * use keventd context to read the event fifo registers -	 * Schedule readout at least 25ms after notification for -	 * REVID < 4 -	 */ - -	schedule_delayed_work(&kpad->work, kpad->delay); +	adp5588_write(client, INT_STAT, status); /* Status is W1C */  	return IRQ_HANDLED;  } @@ -496,30 +505,27 @@ static int adp5588_probe(struct i2c_client *client,  		return -EINVAL;  	} -	kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); -	input = input_allocate_device(); -	if (!kpad || !input) { -		error = -ENOMEM; -		goto err_free_mem; -	} +	kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL); +	if (!kpad) +		return -ENOMEM; + +	input = devm_input_allocate_device(&client->dev); +	if (!input) +		return -ENOMEM;  	kpad->client = client;  	kpad->input = input; -	INIT_DELAYED_WORK(&kpad->work, adp5588_work);  	ret = adp5588_read(client, DEV_ID); -	if (ret < 0) { -		error = ret; -		goto err_free_mem; -	} +	if (ret < 0) +		return ret;  	revid = (u8) ret & ADP5588_DEVICE_ID_MASK;  	if (WA_DELAYED_READOUT_REVID(revid)) -		kpad->delay = msecs_to_jiffies(30); +		kpad->delay = msecs_to_jiffies(WA_DELAYED_READOUT_TIME);  	input->name = client->name;  	input->phys = "adp5588-keys/input0"; -	input->dev.parent = &client->dev;  	input_set_drvdata(input, kpad); @@ -556,95 +562,63 @@ static int adp5588_probe(struct i2c_client *client,  	error = input_register_device(input);  	if (error) { -		dev_err(&client->dev, "unable to register input device\n"); -		goto err_free_mem; +		dev_err(&client->dev, "unable to register input device: %d\n", +			error); +		return error;  	} -	error = request_irq(client->irq, adp5588_irq, -			    IRQF_TRIGGER_FALLING, -			    client->dev.driver->name, kpad); +	error = devm_request_threaded_irq(&client->dev, client->irq, +					  adp5588_hard_irq, adp5588_thread_irq, +					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT, +					  client->dev.driver->name, kpad);  	if (error) { -		dev_err(&client->dev, "irq %d busy?\n", client->irq); -		goto err_unreg_dev; +		dev_err(&client->dev, "failed to request irq %d: %d\n", +			client->irq, error); +		return error;  	}  	error = adp5588_setup(client);  	if (error) -		goto err_free_irq; +		return error;  	if (kpad->gpimapsize)  		adp5588_report_switch_state(kpad);  	error = adp5588_gpio_add(kpad);  	if (error) -		goto err_free_irq; - -	device_init_wakeup(&client->dev, 1); -	i2c_set_clientdata(client, kpad); +		return error;  	dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);  	return 0; - - err_free_irq: -	free_irq(client->irq, kpad); -	cancel_delayed_work_sync(&kpad->work); - err_unreg_dev: -	input_unregister_device(input); -	input = NULL; - err_free_mem: -	input_free_device(input); -	kfree(kpad); - -	return error;  }  static int adp5588_remove(struct i2c_client *client)  { -	struct adp5588_kpad *kpad = i2c_get_clientdata(client); -  	adp5588_write(client, CFG, 0); -	free_irq(client->irq, kpad); -	cancel_delayed_work_sync(&kpad->work); -	input_unregister_device(kpad->input); -	adp5588_gpio_remove(kpad); -	kfree(kpad); +	/* all resources will be freed by devm */  	return 0;  } -#ifdef CONFIG_PM -static int adp5588_suspend(struct device *dev) +static int __maybe_unused adp5588_suspend(struct device *dev)  { -	struct adp5588_kpad *kpad = dev_get_drvdata(dev); -	struct i2c_client *client = kpad->client; +	struct i2c_client *client = to_i2c_client(dev);  	disable_irq(client->irq); -	cancel_delayed_work_sync(&kpad->work); - -	if (device_may_wakeup(&client->dev)) -		enable_irq_wake(client->irq);  	return 0;  } -static int adp5588_resume(struct device *dev) +static int __maybe_unused adp5588_resume(struct device *dev)  { -	struct adp5588_kpad *kpad = dev_get_drvdata(dev); -	struct i2c_client *client = kpad->client; - -	if (device_may_wakeup(&client->dev)) -		disable_irq_wake(client->irq); +	struct i2c_client *client = to_i2c_client(dev);  	enable_irq(client->irq);  	return 0;  } -static const struct dev_pm_ops adp5588_dev_pm_ops = { -	.suspend = adp5588_suspend, -	.resume  = adp5588_resume, -}; -#endif +static SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);  static const struct i2c_device_id adp5588_id[] = {  	{ "adp5588-keys", 0 }, @@ -656,9 +630,7 @@ MODULE_DEVICE_TABLE(i2c, adp5588_id);  static struct i2c_driver adp5588_driver = {  	.driver = {  		.name = KBUILD_MODNAME, -#ifdef CONFIG_PM  		.pm   = &adp5588_dev_pm_ops, -#endif  	},  	.probe    = adp5588_probe,  	.remove   = adp5588_remove, diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index cc73a149da28..c14136b733a9 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -12,6 +12,7 @@  // expensive.  #include <linux/module.h> +#include <linux/acpi.h>  #include <linux/bitops.h>  #include <linux/i2c.h>  #include <linux/input.h> @@ -518,6 +519,50 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev,  	return 0;  } +static void cros_ec_keyb_parse_vivaldi_physmap(struct cros_ec_keyb *ckdev) +{ +	u32 *physmap = ckdev->vdata.function_row_physmap; +	unsigned int row, col, scancode; +	int n_physmap; +	int error; +	int i; + +	n_physmap = device_property_count_u32(ckdev->dev, +					      "function-row-physmap"); +	if (n_physmap <= 0) +		return; + +	if (n_physmap >= VIVALDI_MAX_FUNCTION_ROW_KEYS) { +		dev_warn(ckdev->dev, +			 "only up to %d top row keys is supported (%d specified)\n", +			 VIVALDI_MAX_FUNCTION_ROW_KEYS, n_physmap); +		n_physmap = VIVALDI_MAX_FUNCTION_ROW_KEYS; +	} + +	error = device_property_read_u32_array(ckdev->dev, +					       "function-row-physmap", +					       physmap, n_physmap); +	if (error) { +		dev_warn(ckdev->dev, +			 "failed to parse function-row-physmap property: %d\n", +			 error); +		return; +	} + +	/* +	 * Convert (in place) from row/column encoding to matrix "scancode" +	 * used by the driver. +	 */ +	for (i = 0; i < n_physmap; i++) { +		row = KEY_ROW(physmap[i]); +		col = KEY_COL(physmap[i]); +		scancode = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); +		physmap[i] = scancode; +	} + +	ckdev->vdata.num_function_row_keys = n_physmap; +} +  /**   * cros_ec_keyb_register_matrix - Register matrix keys   * @@ -534,11 +579,6 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)  	struct input_dev *idev;  	const char *phys;  	int err; -	struct property *prop; -	const __be32 *p; -	u32 *physmap; -	u32 key_pos; -	unsigned int row, col, scancode, n_physmap;  	err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols);  	if (err) @@ -573,7 +613,7 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)  	idev->id.product = 0;  	idev->dev.parent = dev; -	ckdev->ghost_filter = of_property_read_bool(dev->of_node, +	ckdev->ghost_filter = device_property_read_bool(dev,  					"google,needs-ghost-filter");  	err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols, @@ -589,22 +629,7 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)  	input_set_drvdata(idev, ckdev);  	ckdev->idev = idev;  	cros_ec_keyb_compute_valid_keys(ckdev); - -	physmap = ckdev->vdata.function_row_physmap; -	n_physmap = 0; -	of_property_for_each_u32(dev->of_node, "function-row-physmap", -				 prop, p, key_pos) { -		if (n_physmap == VIVALDI_MAX_FUNCTION_ROW_KEYS) { -			dev_warn(dev, "Only support up to %d top row keys\n", -				 VIVALDI_MAX_FUNCTION_ROW_KEYS); -			break; -		} -		row = KEY_ROW(key_pos); -		col = KEY_COL(key_pos); -		scancode = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); -		physmap[n_physmap++] = scancode; -	} -	ckdev->vdata.num_function_row_keys = n_physmap; +	cros_ec_keyb_parse_vivaldi_physmap(ckdev);  	err = input_register_device(ckdev->idev);  	if (err) { @@ -653,14 +678,19 @@ static const struct attribute_group cros_ec_keyb_attr_group = {  static int cros_ec_keyb_probe(struct platform_device *pdev)  { -	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); +	struct cros_ec_device *ec;  	struct device *dev = &pdev->dev;  	struct cros_ec_keyb *ckdev;  	bool buttons_switches_only = device_get_match_data(dev);  	int err; -	if (!dev->of_node) -		return -ENODEV; +	/* +	 * If the parent ec device has not been probed yet, defer the probe of +	 * this keyboard/button driver until later. +	 */ +	ec = dev_get_drvdata(pdev->dev.parent); +	if (!ec) +		return -EPROBE_DEFER;  	ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL);  	if (!ckdev) @@ -713,6 +743,14 @@ static int cros_ec_keyb_remove(struct platform_device *pdev)  	return 0;  } +#ifdef CONFIG_ACPI +static const struct acpi_device_id cros_ec_keyb_acpi_match[] = { +	{ "GOOG0007", true }, +	{ } +}; +MODULE_DEVICE_TABLE(acpi, cros_ec_keyb_acpi_match); +#endif +  #ifdef CONFIG_OF  static const struct of_device_id cros_ec_keyb_of_match[] = {  	{ .compatible = "google,cros-ec-keyb" }, @@ -730,6 +768,7 @@ static struct platform_driver cros_ec_keyb_driver = {  	.driver = {  		.name = "cros-ec-keyb",  		.of_match_table = of_match_ptr(cros_ec_keyb_of_match), +		.acpi_match_table = ACPI_PTR(cros_ec_keyb_acpi_match),  		.pm = &cros_ec_keyb_pm_ops,  	},  }; diff --git a/drivers/input/keyboard/mt6779-keypad.c b/drivers/input/keyboard/mt6779-keypad.c index 2e7c9187c10f..bf447bf598fb 100644 --- a/drivers/input/keyboard/mt6779-keypad.c +++ b/drivers/input/keyboard/mt6779-keypad.c @@ -17,6 +17,11 @@  #define MTK_KPD_DEBOUNCE	0x0018  #define MTK_KPD_DEBOUNCE_MASK	GENMASK(13, 0)  #define MTK_KPD_DEBOUNCE_MAX_MS	256 +#define MTK_KPD_SEL		0x0020 +#define MTK_KPD_SEL_COL	GENMASK(15, 10) +#define MTK_KPD_SEL_ROW	GENMASK(9, 4) +#define MTK_KPD_SEL_COLMASK(c)	GENMASK((c) + 9, 10) +#define MTK_KPD_SEL_ROWMASK(r)	GENMASK((r) + 3, 4)  #define MTK_KPD_NUM_MEMS	5  #define MTK_KPD_NUM_BITS	136	/* 4*32+8 MEM5 only use 8 BITS */ @@ -42,7 +47,7 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id)  	const unsigned short *keycode = keypad->input_dev->keycode;  	DECLARE_BITMAP(new_state, MTK_KPD_NUM_BITS);  	DECLARE_BITMAP(change, MTK_KPD_NUM_BITS); -	unsigned int bit_nr; +	unsigned int bit_nr, key;  	unsigned int row, col;  	unsigned int scancode;  	unsigned int row_shift = get_count_order(keypad->n_cols); @@ -61,8 +66,10 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id)  		if (bit_nr % 32 >= 16)  			continue; -		row = bit_nr / 32; -		col = bit_nr % 32; +		key = bit_nr / 32 * 16 + bit_nr % 32; +		row = key / 9; +		col = key % 9; +  		scancode = MATRIX_SCAN_CODE(row, col, row_shift);  		/* 1: not pressed, 0: pressed */  		pressed = !test_bit(bit_nr, new_state); @@ -159,6 +166,11 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev)  	regmap_write(keypad->regmap, MTK_KPD_DEBOUNCE,  		     (debounce * (1 << 5)) & MTK_KPD_DEBOUNCE_MASK); +	regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_ROW, +			   MTK_KPD_SEL_ROWMASK(keypad->n_rows)); +	regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_COL, +			   MTK_KPD_SEL_COLMASK(keypad->n_cols)); +  	keypad->clk = devm_clk_get(&pdev->dev, "kpd");  	if (IS_ERR(keypad->clk))  		return PTR_ERR(keypad->clk); diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c index c31ab4368388..6404081253ea 100644 --- a/drivers/input/keyboard/mtk-pmic-keys.c +++ b/drivers/input/keyboard/mtk-pmic-keys.c @@ -18,17 +18,9 @@  #include <linux/platform_device.h>  #include <linux/regmap.h> -#define MTK_PMIC_PWRKEY_RST_EN_MASK	0x1 -#define MTK_PMIC_PWRKEY_RST_EN_SHIFT	6 -#define MTK_PMIC_HOMEKEY_RST_EN_MASK	0x1 -#define MTK_PMIC_HOMEKEY_RST_EN_SHIFT	5 -#define MTK_PMIC_RST_DU_MASK		0x3 -#define MTK_PMIC_RST_DU_SHIFT		8 - -#define MTK_PMIC_PWRKEY_RST		\ -	(MTK_PMIC_PWRKEY_RST_EN_MASK << MTK_PMIC_PWRKEY_RST_EN_SHIFT) -#define MTK_PMIC_HOMEKEY_RST		\ -	(MTK_PMIC_HOMEKEY_RST_EN_MASK << MTK_PMIC_HOMEKEY_RST_EN_SHIFT) +#define MTK_PMIC_RST_DU_MASK	GENMASK(9, 8) +#define MTK_PMIC_PWRKEY_RST	BIT(6) +#define MTK_PMIC_HOMEKEY_RST	BIT(5)  #define MTK_PMIC_PWRKEY_INDEX	0  #define MTK_PMIC_HOMEKEY_INDEX	1 @@ -39,50 +31,58 @@ struct mtk_pmic_keys_regs {  	u32 deb_mask;  	u32 intsel_reg;  	u32 intsel_mask; +	u32 rst_en_mask;  };  #define MTK_PMIC_KEYS_REGS(_deb_reg, _deb_mask,		\ -	_intsel_reg, _intsel_mask)			\ +	_intsel_reg, _intsel_mask, _rst_mask)		\  {							\  	.deb_reg		= _deb_reg,		\  	.deb_mask		= _deb_mask,		\  	.intsel_reg		= _intsel_reg,		\  	.intsel_mask		= _intsel_mask,		\ +	.rst_en_mask		= _rst_mask,		\  }  struct mtk_pmic_regs {  	const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT];  	u32 pmic_rst_reg; +	u32 rst_lprst_mask; /* Long-press reset timeout bitmask */  };  static const struct mtk_pmic_regs mt6397_regs = {  	.keys_regs[MTK_PMIC_PWRKEY_INDEX] =  		MTK_PMIC_KEYS_REGS(MT6397_CHRSTATUS, -		0x8, MT6397_INT_RSV, 0x10), +		0x8, MT6397_INT_RSV, 0x10, MTK_PMIC_PWRKEY_RST),  	.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =  		MTK_PMIC_KEYS_REGS(MT6397_OCSTATUS2, -		0x10, MT6397_INT_RSV, 0x8), +		0x10, MT6397_INT_RSV, 0x8, MTK_PMIC_HOMEKEY_RST),  	.pmic_rst_reg = MT6397_TOP_RST_MISC, +	.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,  };  static const struct mtk_pmic_regs mt6323_regs = {  	.keys_regs[MTK_PMIC_PWRKEY_INDEX] =  		MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS, -		0x2, MT6323_INT_MISC_CON, 0x10), +		0x2, MT6323_INT_MISC_CON, 0x10, MTK_PMIC_PWRKEY_RST),  	.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =  		MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS, -		0x4, MT6323_INT_MISC_CON, 0x8), +		0x4, MT6323_INT_MISC_CON, 0x8, MTK_PMIC_HOMEKEY_RST),  	.pmic_rst_reg = MT6323_TOP_RST_MISC, +	.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,  };  static const struct mtk_pmic_regs mt6358_regs = {  	.keys_regs[MTK_PMIC_PWRKEY_INDEX] =  		MTK_PMIC_KEYS_REGS(MT6358_TOPSTATUS, -				   0x2, MT6358_PSC_TOP_INT_CON0, 0x5), +				   0x2, MT6358_PSC_TOP_INT_CON0, 0x5, +				   MTK_PMIC_PWRKEY_RST),  	.keys_regs[MTK_PMIC_HOMEKEY_INDEX] =  		MTK_PMIC_KEYS_REGS(MT6358_TOPSTATUS, -				   0x8, MT6358_PSC_TOP_INT_CON0, 0xa), +				   0x8, MT6358_PSC_TOP_INT_CON0, 0xa, +				   MTK_PMIC_HOMEKEY_RST),  	.pmic_rst_reg = MT6358_TOP_RST_MISC, +	.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,  };  struct mtk_pmic_keys_info { @@ -108,53 +108,49 @@ enum mtk_pmic_keys_lp_mode {  };  static void mtk_pmic_keys_lp_reset_setup(struct mtk_pmic_keys *keys, -		u32 pmic_rst_reg) +					 const struct mtk_pmic_regs *regs)  { -	int ret; +	const struct mtk_pmic_keys_regs *kregs_home, *kregs_pwr;  	u32 long_press_mode, long_press_debounce; +	u32 value, mask; +	int error; + +	kregs_home = keys->keys[MTK_PMIC_HOMEKEY_INDEX].regs; +	kregs_pwr = keys->keys[MTK_PMIC_PWRKEY_INDEX].regs; -	ret = of_property_read_u32(keys->dev->of_node, -		"power-off-time-sec", &long_press_debounce); -	if (ret) +	error = of_property_read_u32(keys->dev->of_node, "power-off-time-sec", +				     &long_press_debounce); +	if (error)  		long_press_debounce = 0; -	regmap_update_bits(keys->regmap, pmic_rst_reg, -			   MTK_PMIC_RST_DU_MASK << MTK_PMIC_RST_DU_SHIFT, -			   long_press_debounce << MTK_PMIC_RST_DU_SHIFT); +	mask = regs->rst_lprst_mask; +	value = long_press_debounce << (ffs(regs->rst_lprst_mask) - 1); -	ret = of_property_read_u32(keys->dev->of_node, -		"mediatek,long-press-mode", &long_press_mode); -	if (ret) +	error  = of_property_read_u32(keys->dev->of_node, +				      "mediatek,long-press-mode", +				      &long_press_mode); +	if (error)  		long_press_mode = LP_DISABLE;  	switch (long_press_mode) { -	case LP_ONEKEY: -		regmap_update_bits(keys->regmap, pmic_rst_reg, -				   MTK_PMIC_PWRKEY_RST, -				   MTK_PMIC_PWRKEY_RST); -		regmap_update_bits(keys->regmap, pmic_rst_reg, -				   MTK_PMIC_HOMEKEY_RST, -				   0); -		break;  	case LP_TWOKEY: -		regmap_update_bits(keys->regmap, pmic_rst_reg, -				   MTK_PMIC_PWRKEY_RST, -				   MTK_PMIC_PWRKEY_RST); -		regmap_update_bits(keys->regmap, pmic_rst_reg, -				   MTK_PMIC_HOMEKEY_RST, -				   MTK_PMIC_HOMEKEY_RST); -		break; +		value |= kregs_home->rst_en_mask; +		fallthrough; + +	case LP_ONEKEY: +		value |= kregs_pwr->rst_en_mask; +		fallthrough; +  	case LP_DISABLE: -		regmap_update_bits(keys->regmap, pmic_rst_reg, -				   MTK_PMIC_PWRKEY_RST, -				   0); -		regmap_update_bits(keys->regmap, pmic_rst_reg, -				   MTK_PMIC_HOMEKEY_RST, -				   0); +		mask |= kregs_home->rst_en_mask; +		mask |= kregs_pwr->rst_en_mask;  		break; +  	default:  		break;  	} + +	regmap_update_bits(keys->regmap, regs->pmic_rst_reg, mask, value);  }  static irqreturn_t mtk_pmic_keys_irq_handler_thread(int irq, void *data) @@ -358,7 +354,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)  		return error;  	} -	mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs->pmic_rst_reg); +	mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs);  	platform_set_drvdata(pdev, keys); diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 8a7ce41b8c56..ee9d04a3f0d5 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -179,11 +179,9 @@ static irqreturn_t omap4_keypad_irq_thread_fn(int irq, void *dev_id)  	int error;  	u64 keys; -	error = pm_runtime_get_sync(dev); -	if (error < 0) { -		pm_runtime_put_noidle(dev); +	error = pm_runtime_resume_and_get(dev); +	if (error)  		return IRQ_NONE; -	}  	low = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0);  	high = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32); @@ -207,11 +205,9 @@ static int omap4_keypad_open(struct input_dev *input)  	struct device *dev = input->dev.parent;  	int error; -	error = pm_runtime_get_sync(dev); -	if (error < 0) { -		pm_runtime_put_noidle(dev); +	error = pm_runtime_resume_and_get(dev); +	if (error)  		return error; -	}  	disable_irq(keypad_data->irq); @@ -254,9 +250,10 @@ static void omap4_keypad_close(struct input_dev *input)  	struct device *dev = input->dev.parent;  	int error; -	error = pm_runtime_get_sync(dev); -	if (error < 0) -		pm_runtime_put_noidle(dev); +	error = pm_runtime_resume_and_get(dev); +	if (error) +		dev_err(dev, "%s: pm_runtime_resume_and_get() failed: %d\n", +			__func__, error);  	disable_irq(keypad_data->irq);  	omap4_keypad_stop(keypad_data); @@ -392,10 +389,9 @@ static int omap4_keypad_probe(struct platform_device *pdev)  	 * Enable clocks for the keypad module so that we can read  	 * revision register.  	 */ -	error = pm_runtime_get_sync(dev); -	if (error < 0) { -		dev_err(dev, "pm_runtime_get_sync() failed\n"); -		pm_runtime_put_noidle(dev); +	error = pm_runtime_resume_and_get(dev); +	if (error) { +		dev_err(dev, "pm_runtime_resume_and_get() failed\n");  		return error;  	} diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index 6b4138771a3f..b2e8097a2e6d 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -40,7 +40,6 @@  #define IQS7222_SLDR_SETUP_2_RES_MASK		GENMASK(15, 8)  #define IQS7222_SLDR_SETUP_2_RES_SHIFT		8  #define IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK	GENMASK(7, 0) -#define IQS7222_SLDR_SETUP_3_CHAN_SEL_MASK	GENMASK(9, 0)  #define IQS7222_GPIO_SETUP_0_GPIO_EN		BIT(0) @@ -54,6 +53,9 @@  #define IQS7222_SYS_SETUP_ACK_RESET		BIT(0)  #define IQS7222_EVENT_MASK_ATI			BIT(12) +#define IQS7222_EVENT_MASK_SLDR			BIT(10) +#define IQS7222_EVENT_MASK_TOUCH		BIT(1) +#define IQS7222_EVENT_MASK_PROX			BIT(0)  #define IQS7222_COMMS_HOLD			BIT(0)  #define IQS7222_COMMS_ERROR			0xEEEE @@ -92,11 +94,11 @@ enum iqs7222_reg_key_id {  enum iqs7222_reg_grp_id {  	IQS7222_REG_GRP_STAT, +	IQS7222_REG_GRP_FILT,  	IQS7222_REG_GRP_CYCLE,  	IQS7222_REG_GRP_GLBL,  	IQS7222_REG_GRP_BTN,  	IQS7222_REG_GRP_CHAN, -	IQS7222_REG_GRP_FILT,  	IQS7222_REG_GRP_SLDR,  	IQS7222_REG_GRP_GPIO,  	IQS7222_REG_GRP_SYS, @@ -135,12 +137,12 @@ struct iqs7222_event_desc {  static const struct iqs7222_event_desc iqs7222_kp_events[] = {  	{  		.name = "event-prox", -		.enable = BIT(0), +		.enable = IQS7222_EVENT_MASK_PROX,  		.reg_key = IQS7222_REG_KEY_PROX,  	},  	{  		.name = "event-touch", -		.enable = BIT(1), +		.enable = IQS7222_EVENT_MASK_TOUCH,  		.reg_key = IQS7222_REG_KEY_TOUCH,  	},  }; @@ -556,13 +558,6 @@ static const struct iqs7222_prop_desc iqs7222_props[] = {  		.label = "current reference trim",  	},  	{ -		.name = "azoteq,rf-filt-enable", -		.reg_grp = IQS7222_REG_GRP_GLBL, -		.reg_offset = 0, -		.reg_shift = 15, -		.reg_width = 1, -	}, -	{  		.name = "azoteq,max-counts",  		.reg_grp = IQS7222_REG_GRP_GLBL,  		.reg_offset = 0, @@ -1272,9 +1267,22 @@ static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222)  	struct i2c_client *client = iqs7222->client;  	ktime_t ati_timeout;  	u16 sys_status = 0; -	u16 sys_setup = iqs7222->sys_setup[0] & ~IQS7222_SYS_SETUP_ACK_RESET; +	u16 sys_setup;  	int error, i; +	/* +	 * The reserved fields of the system setup register may have changed +	 * as a result of other registers having been written. As such, read +	 * the register's latest value to avoid unexpected behavior when the +	 * register is written in the loop that follows. +	 */ +	error = iqs7222_read_word(iqs7222, IQS7222_SYS_SETUP, &sys_setup); +	if (error) +		return error; + +	sys_setup &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK; +	sys_setup &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK; +  	for (i = 0; i < IQS7222_NUM_RETRIES; i++) {  		/*  		 * Trigger ATI from streaming and normal-power modes so that @@ -1299,12 +1307,15 @@ static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222)  			if (error)  				return error; -			if (sys_status & IQS7222_SYS_STATUS_ATI_ACTIVE) -				continue; +			if (sys_status & IQS7222_SYS_STATUS_RESET) +				return 0;  			if (sys_status & IQS7222_SYS_STATUS_ATI_ERROR)  				break; +			if (sys_status & IQS7222_SYS_STATUS_ATI_ACTIVE) +				continue; +  			/*  			 * Use stream-in-touch mode if either slider reports  			 * absolute position. @@ -1321,7 +1332,7 @@ static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222)  		dev_err(&client->dev,  			"ATI attempt %d of %d failed with status 0x%02X, %s\n",  			i + 1, IQS7222_NUM_RETRIES, (u8)sys_status, -			i < IQS7222_NUM_RETRIES ? "retrying..." : "stopping"); +			i + 1 < IQS7222_NUM_RETRIES ? "retrying" : "stopping");  	}  	return -ETIMEDOUT; @@ -1334,6 +1345,34 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir)  	int error, i, j, k;  	/* +	 * Acknowledge reset before writing any registers in case the device +	 * suffers a spurious reset during initialization. Because this step +	 * may change the reserved fields of the second filter beta register, +	 * its cache must be updated. +	 * +	 * Writing the second filter beta register, in turn, may clobber the +	 * system status register. As such, the filter beta register pair is +	 * written first to protect against this hazard. +	 */ +	if (dir == WRITE) { +		u16 reg = dev_desc->reg_grps[IQS7222_REG_GRP_FILT].base + 1; +		u16 filt_setup; + +		error = iqs7222_write_word(iqs7222, IQS7222_SYS_SETUP, +					   iqs7222->sys_setup[0] | +					   IQS7222_SYS_SETUP_ACK_RESET); +		if (error) +			return error; + +		error = iqs7222_read_word(iqs7222, reg, &filt_setup); +		if (error) +			return error; + +		iqs7222->filt_setup[1] &= GENMASK(7, 0); +		iqs7222->filt_setup[1] |= (filt_setup & ~GENMASK(7, 0)); +	} + +	/*  	 * Take advantage of the stop-bit disable function, if available, to  	 * save the trouble of having to reopen a communication window after  	 * each burst read or write. @@ -1957,8 +1996,8 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)  	int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row;  	int ext_chan = rounddown(num_chan, 10);  	int count, error, reg_offset, i; +	u16 *event_mask = &iqs7222->sys_setup[dev_desc->event_offset];  	u16 *sldr_setup = iqs7222->sldr_setup[sldr_index]; -	u16 *sys_setup = iqs7222->sys_setup;  	unsigned int chan_sel[4], val;  	error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index, @@ -2003,7 +2042,7 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)  	reg_offset = dev_desc->sldr_res < U16_MAX ? 0 : 1;  	sldr_setup[0] |= count; -	sldr_setup[3 + reg_offset] &= ~IQS7222_SLDR_SETUP_3_CHAN_SEL_MASK; +	sldr_setup[3 + reg_offset] &= ~GENMASK(ext_chan - 1, 0);  	for (i = 0; i < ARRAY_SIZE(chan_sel); i++) {  		sldr_setup[5 + reg_offset + i] = 0; @@ -2081,17 +2120,19 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)  			sldr_setup[0] |= dev_desc->wheel_enable;  	} +	/* +	 * The absence of a register offset makes it safe to assume the device +	 * supports gestures, each of which is first disabled until explicitly +	 * enabled. +	 */ +	if (!reg_offset) +		for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) +			sldr_setup[9] &= ~iqs7222_sl_events[i].enable; +  	for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) {  		const char *event_name = iqs7222_sl_events[i].name;  		struct fwnode_handle *event_node; -		/* -		 * The absence of a register offset means the remaining fields -		 * in the group represent gesture settings. -		 */ -		if (iqs7222_sl_events[i].enable && !reg_offset) -			sldr_setup[9] &= ~iqs7222_sl_events[i].enable; -  		event_node = fwnode_get_named_child_node(sldr_node, event_name);  		if (!event_node)  			continue; @@ -2104,6 +2145,22 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)  		if (error)  			return error; +		/* +		 * The press/release event does not expose a direct GPIO link, +		 * but one can be emulated by tying each of the participating +		 * channels to the same GPIO. +		 */ +		error = iqs7222_gpio_select(iqs7222, event_node, +					    i ? iqs7222_sl_events[i].enable +					      : sldr_setup[3 + reg_offset], +					    i ? 1568 + sldr_index * 30 +					      : sldr_setup[4 + reg_offset]); +		if (error) +			return error; + +		if (!reg_offset) +			sldr_setup[9] |= iqs7222_sl_events[i].enable; +  		error = fwnode_property_read_u32(event_node, "linux,code",  						 &val);  		if (error) { @@ -2115,26 +2172,20 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)  		iqs7222->sl_code[sldr_index][i] = val;  		input_set_capability(iqs7222->keypad, EV_KEY, val); -		/* -		 * The press/release event is determined based on whether the -		 * coordinate field reports 0xFFFF and has no explicit enable -		 * control. -		 */ -		if (!iqs7222_sl_events[i].enable || reg_offset) -			continue; - -		sldr_setup[9] |= iqs7222_sl_events[i].enable; - -		error = iqs7222_gpio_select(iqs7222, event_node, -					    iqs7222_sl_events[i].enable, -					    1568 + sldr_index * 30); -		if (error) -			return error; -  		if (!dev_desc->event_offset)  			continue; -		sys_setup[dev_desc->event_offset] |= BIT(10 + sldr_index); +		/* +		 * The press/release event is determined based on whether the +		 * coordinate field reports 0xFFFF and solely relies on touch +		 * or proximity interrupts to be unmasked. +		 */ +		if (i && !reg_offset) +			*event_mask |= (IQS7222_EVENT_MASK_SLDR << sldr_index); +		else if (sldr_setup[4 + reg_offset] == dev_desc->touch_link) +			*event_mask |= IQS7222_EVENT_MASK_TOUCH; +		else +			*event_mask |= IQS7222_EVENT_MASK_PROX;  	}  	/* @@ -2227,11 +2278,6 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)  			return error;  	} -	sys_setup[0] &= ~IQS7222_SYS_SETUP_INTF_MODE_MASK; -	sys_setup[0] &= ~IQS7222_SYS_SETUP_PWR_MODE_MASK; - -	sys_setup[0] |= IQS7222_SYS_SETUP_ACK_RESET; -  	return iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_SYS,  				   IQS7222_REG_KEY_NONE);  } @@ -2299,29 +2345,37 @@ static int iqs7222_report(struct iqs7222_private *iqs7222)  			input_report_abs(iqs7222->keypad, iqs7222->sl_axis[i],  					 sldr_pos); -		for (j = 0; j < ARRAY_SIZE(iqs7222_sl_events); j++) { -			u16 mask = iqs7222_sl_events[j].mask; -			u16 val = iqs7222_sl_events[j].val; +		input_report_key(iqs7222->keypad, iqs7222->sl_code[i][0], +				 sldr_pos < dev_desc->sldr_res); -			if (!iqs7222_sl_events[j].enable) { -				input_report_key(iqs7222->keypad, -						 iqs7222->sl_code[i][j], -						 sldr_pos < dev_desc->sldr_res); -				continue; -			} +		/* +		 * A maximum resolution indicates the device does not support +		 * gestures, in which case the remaining fields are ignored. +		 */ +		if (dev_desc->sldr_res == U16_MAX) +			continue; -			/* -			 * The remaining offsets represent gesture state, and -			 * are discarded in the case of IQS7222C because only -			 * absolute position is reported. -			 */ -			if (num_stat < IQS7222_MAX_COLS_STAT) -				continue; +		if (!(le16_to_cpu(status[1]) & IQS7222_EVENT_MASK_SLDR << i)) +			continue; + +		/* +		 * Skip the press/release event, as it does not have separate +		 * status fields and is handled separately. +		 */ +		for (j = 1; j < ARRAY_SIZE(iqs7222_sl_events); j++) { +			u16 mask = iqs7222_sl_events[j].mask; +			u16 val = iqs7222_sl_events[j].val;  			input_report_key(iqs7222->keypad,  					 iqs7222->sl_code[i][j],  					 (state & mask) == val);  		} + +		input_sync(iqs7222->keypad); + +		for (j = 1; j < ARRAY_SIZE(iqs7222_sl_events); j++) +			input_report_key(iqs7222->keypad, +					 iqs7222->sl_code[i][j], 0);  	}  	input_sync(iqs7222->keypad); diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c index 812edfced86e..0caaf3e64215 100644 --- a/drivers/input/mouse/cyapa_gen6.c +++ b/drivers/input/mouse/cyapa_gen6.c @@ -57,7 +57,7 @@ struct pip_app_resp_head {  	 * The value of data_status can be the first byte of data or  	 * the command status or the unsupported command code depending on the  	 * requested command code. -	*/ +	 */  	u8 data_status;  } __packed; diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 23507fce3a2b..18ccbd45004a 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -41,7 +41,7 @@ struct gpio_mouse {  /*   * Timer function which is run every scan_ms ms when the device is opened. - * The dev input variable is set to the the input_dev pointer. + * The dev input variable is set to the input_dev pointer.   */  static void gpio_mouse_scan(struct input_dev *input)  { diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 148a7c5fd0e2..4fbec7bbecca 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -67,25 +67,84 @@ static inline void i8042_write_command(int val)  #include <linux/dmi.h> -static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { +#define SERIO_QUIRK_NOKBD		BIT(0) +#define SERIO_QUIRK_NOAUX		BIT(1) +#define SERIO_QUIRK_NOMUX		BIT(2) +#define SERIO_QUIRK_FORCEMUX		BIT(3) +#define SERIO_QUIRK_UNLOCK		BIT(4) +#define SERIO_QUIRK_PROBE_DEFER		BIT(5) +#define SERIO_QUIRK_RESET_ALWAYS	BIT(6) +#define SERIO_QUIRK_RESET_NEVER		BIT(7) +#define SERIO_QUIRK_DIECT		BIT(8) +#define SERIO_QUIRK_DUMBKBD		BIT(9) +#define SERIO_QUIRK_NOLOOP		BIT(10) +#define SERIO_QUIRK_NOTIMEOUT		BIT(11) +#define SERIO_QUIRK_KBDRESET		BIT(12) +#define SERIO_QUIRK_DRITEK		BIT(13) +#define SERIO_QUIRK_NOPNP		BIT(14) + +/* Quirk table for different mainboards. Options similar or identical to i8042 + * module parameters. + * ORDERING IS IMPORTANT! The first match will be apllied and the rest ignored. + * This allows entries to overwrite vendor wide quirks on a per device basis. + * Where this is irrelevant, entries are sorted case sensitive by DMI_SYS_VENDOR + * and/or DMI_BOARD_VENDOR to make it easier to avoid dublicate entries. + */ +static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {  	{ -		/* -		 * Arima-Rioworks HDAMB - -		 * AUX LOOP command does not raise AUX IRQ -		 */  		.matches = { -			DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"), -			DMI_MATCH(DMI_BOARD_NAME, "HDAMB"), -			DMI_MATCH(DMI_BOARD_VERSION, "Rev E"), +			DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* ASUS G1S */  		.matches = { -			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), -			DMI_MATCH(DMI_BOARD_NAME, "G1S"), -			DMI_MATCH(DMI_BOARD_VERSION, "1.0"), +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +			DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP) +	}, +	{ +		/* Asus X450LCP */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_NEVER) +	}, +	{ +		/* ASUS ZenBook UX425UA */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER) +	}, +	{ +		/* ASUS ZenBook UM325UA */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER) +	}, +	/* +	 * On some Asus laptops, just running self tests cause problems. +	 */ +	{ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ +		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_NEVER) +	}, +	{ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +			DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */ +		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_NEVER)  	},  	{  		/* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */ @@ -94,585 +153,689 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {  			DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"),  			DMI_MATCH(DMI_BOARD_VERSION, "REV 2.X"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ +		/* ASUS G1S */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -			DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"), +			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), +			DMI_MATCH(DMI_BOARD_NAME, "G1S"), +			DMI_MATCH(DMI_BOARD_VERSION, "1.0"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), -			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "8500"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Acer Aspire 5710 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), -			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Dell Embedded Box PC 3000 */ +		/* Acer Aspire 7738 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* OQO Model 01 */ +		/* Acer Aspire 5536 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "OQO"), -			DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "00"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* ULI EV4873 - AUX LOOP does not work properly */ +		/* +		 * Acer Aspire 5738z +		 * Touchpad stops working in mux mode when dis- + re-enabled +		 * with the touchpad enable/disable toggle hotkey +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ULI"), -			DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Microsoft Virtual Machine */ +		/* Acer Aspire One 150 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Medion MAM 2070 */ +		/* Acer Aspire One 532h */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), -			DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "AO532h"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Medion Akoya E7225 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Medion"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Blue FB5601 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "blue"), -			DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "M606"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Gigabyte M912 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "M912"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "01"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Gigabyte M1022M netbook */  		.matches = { -			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."), -			DMI_MATCH(DMI_BOARD_NAME, "M1022E"), -			DMI_MATCH(DMI_BOARD_VERSION, "1.02"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Gigabyte Spring Peak - defines wrong chassis type */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Gigabyte T1005 - defines wrong chassis type ("Other") */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "T1005"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Gigabyte T1005M/P - defines wrong chassis type ("Other") */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	}, +	/* +	 * Some Wistron based laptops need us to explicitly enable the 'Dritek +	 * keyboard extension' to make their extra keys start generating scancodes. +	 * Originally, this was just confined to older laptops, but a few Acer laptops +	 * have turned up in 2007 that also need this again. +	 */  	{ +		/* Acer Aspire 5100 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ +		/* Acer Aspire 5610 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"), -			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ +		/* Acer Aspire 5630 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"), -			DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	}, -	{ } -}; - -/* - * Some Fujitsu notebooks are having trouble with touchpads if - * active multiplexing mode is activated. Luckily they don't have - * external PS/2 ports so we can safely disable it. - * ... apparently some Toshibas don't like MUX mode either and - * die horrible death on reboot. - */ -static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {  	{ -		/* Fujitsu Lifebook P7010/P7010D */ +		/* Acer Aspire 5650 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "P7010"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu Lifebook P7010 */ +		/* Acer Aspire 5680 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), -			DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu Lifebook P5020D */ +		/* Acer Aspire 5720 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu Lifebook S2000 */ +		/* Acer Aspire 9110 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu Lifebook S6230 */ +		/* Acer TravelMate 660 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu Lifebook T725 laptop */ +		/* Acer TravelMate 2490 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu Lifebook U745 */ +		/* Acer TravelMate 4280 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"), +			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), +			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_DRITEK)  	},  	{ -		/* Fujitsu T70H */ +		/* Amoi M636/A737 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"), +			DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), +			DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Fujitsu-Siemens Lifebook T3010 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), +			DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"), +			DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Fujitsu-Siemens Lifebook E4010 */ +		/* Compal HEL80I */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"), +			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), +			DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Fujitsu-Siemens Amilo Pro 2010 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), -			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"), +			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), +			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Fujitsu-Siemens Amilo Pro 2030 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), -			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), +			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), +			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* -		 * No data is coming from the touchscreen unless KBC -		 * is in legacy mode. -		 */ -		/* Panasonic CF-29 */ +		/* Advent 4211 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), -			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), +			DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* -		 * HP Pavilion DV4017EA - -		 * errors on MUX ports are reported without raising AUXDATA -		 * causing "spurious NAK" messages. -		 */ +		/* Dell Embedded Box PC 3000 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* -		 * HP Pavilion ZT1000 - -		 * like DV4017EA does not raise AUXERR for errors on MUX ports. -		 */ +		/* Dell XPS M1530 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* -		 * HP Pavilion DV4270ca - -		 * like DV4017EA does not raise AUXERR for errors on MUX ports. -		 */ +		/* Dell Vostro 1510 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Dell Vostro V13 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)  	},  	{ +		/* Dell Vostro 1320 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), -			DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ +		/* Dell Vostro 1520 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), -			DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ +		/* Dell Vostro 1720 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Sharp Actius MM20 */ +		/* Entroware Proteus */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), -			DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), +			DMI_MATCH(DMI_SYS_VENDOR, "Entroware"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS)  	}, +	/* +	 * Some Fujitsu notebooks are having trouble with touchpads if +	 * active multiplexing mode is activated. Luckily they don't have +	 * external PS/2 ports so we can safely disable it. +	 * ... apparently some Toshibas don't like MUX mode either and +	 * die horrible death on reboot. +	 */  	{ -		/* Sony Vaio FS-115b */ +		/* Fujitsu Lifebook P7010/P7010D */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* -		 * Sony Vaio FZ-240E - -		 * reset and GET ID commands issued via KBD port are -		 * sometimes being delivered to AUX3. -		 */ +		/* Fujitsu Lifebook P5020D */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* -		 * Most (all?) VAIOs do not have external PS/2 ports nor -		 * they implement active multiplexing properly, and -		 * MUX discovery usually messes up keyboard/touchpad. -		 */ +		/* Fujitsu Lifebook S2000 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -			DMI_MATCH(DMI_BOARD_NAME, "VAIO"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Amoi M636/A737 */ +		/* Fujitsu Lifebook S6230 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), -			DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Lenovo 3000 n100 */ +		/* Fujitsu Lifebook T725 laptop */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -			DMI_MATCH(DMI_PRODUCT_NAME, "076804U"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)  	},  	{ -		/* Lenovo XiaoXin Air 12 */ +		/* Fujitsu Lifebook U745 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -			DMI_MATCH(DMI_PRODUCT_NAME, "80UN"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Fujitsu T70H */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Acer Aspire 5710 */ +		/* Fujitsu A544 laptop */ +		/* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)  	},  	{ -		/* Acer Aspire 7738 */ +		/* Fujitsu AH544 laptop */ +		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)  	},  	{ -		/* Gericom Bellagio */ +		/* Fujitsu U574 laptop */ +		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), -			DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)  	},  	{ -		/* IBM 2656 */ +		/* Fujitsu UH554 laptop */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "IBM"), -			DMI_MATCH(DMI_PRODUCT_NAME, "2656"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)  	},  	{ -		/* Dell XPS M1530 */ +		/* Fujitsu Lifebook P7010 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), +			DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Compal HEL80I */ +		/* Fujitsu-Siemens Lifebook T3010 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), -			DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Dell Vostro 1510 */ +		/* Fujitsu-Siemens Lifebook E4010 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), +			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Acer Aspire 5536 */ +		/* Fujitsu-Siemens Amilo Pro 2010 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), +			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Dell Vostro V13 */ +		/* Fujitsu-Siemens Amilo Pro 2030 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), +			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), +			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Newer HP Pavilion dv4 models */ +		/* Gigabyte M912 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "M912"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "01"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Asus X450LCP */ +		/* Gigabyte Spring Peak - defines wrong chassis type */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Avatar AVIU-145A6 */ +		/* Gigabyte T1005 - defines wrong chassis type ("Other") */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Intel"), -			DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* TUXEDO BU1406 */ +		/* Gigabyte T1005M/P - defines wrong chassis type ("Other") */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), -			DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	}, +	/* +	 * Some laptops need keyboard reset before probing for the trackpad to get +	 * it detected, initialised & finally work. +	 */  	{ -		/* Lenovo LaVie Z */ +		/* Gigabyte P35 v2 - Elantech touchpad */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo LaVie Z"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_KBDRESET) +	}, +		{ +		/* Aorus branded Gigabyte X3 Plus - Elantech touchpad */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "X3"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)  	},  	{ -		/* -		 * Acer Aspire 5738z -		 * Touchpad stops working in mux mode when dis- + re-enabled -		 * with the touchpad enable/disable toggle hotkey -		 */ +		/* Gigabyte P34 - Elantech touchpad */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P34"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)  	},  	{ -		/* Entroware Proteus */ +		/* Gigabyte P57 - Elantech touchpad */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Entroware"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"), +			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P57"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_KBDRESET) +	}, +	{ +		/* Gericom Bellagio */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), +			DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX) +	}, +	{ +		/* Gigabyte M1022M netbook */ +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."), +			DMI_MATCH(DMI_BOARD_NAME, "M1022E"), +			DMI_MATCH(DMI_BOARD_VERSION, "1.02"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP) +	}, +	{ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	}, -	{ } -}; - -static const struct dmi_system_id i8042_dmi_forcemux_table[] __initconst = {  	{  		/* -		 * Sony Vaio VGN-CS series require MUX or the touch sensor -		 * buttons will disturb touchpad operation +		 * HP Pavilion DV4017EA - +		 * errors on MUX ports are reported without raising AUXDATA +		 * causing "spurious NAK" messages.  		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), -			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"), +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	}, -	{ } -}; - -/* - * On some Asus laptops, just running self tests cause problems. - */ -static const struct dmi_system_id i8042_dmi_noselftest_table[] = {  	{ +		/* +		 * HP Pavilion ZT1000 - +		 * like DV4017EA does not raise AUXERR for errors on MUX ports. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),  		}, -	}, { +		.driver_data = (void *)(SERIO_QUIRK_NOMUX) +	}, +	{ +		/* +		 * HP Pavilion DV4270ca - +		 * like DV4017EA does not raise AUXERR for errors on MUX ports. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -			DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */ +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	}, -	{ } -}; -static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {  	{ -		/* MSI Wind U-100 */ +		/* Newer HP Pavilion dv4 models */  		.matches = { -			DMI_MATCH(DMI_BOARD_NAME, "U-100"), -			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), +			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), +			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)  	},  	{ -		/* LG Electronics X110 */ +		/* IBM 2656 */  		.matches = { -			DMI_MATCH(DMI_BOARD_NAME, "X110"), -			DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), +			DMI_MATCH(DMI_SYS_VENDOR, "IBM"), +			DMI_MATCH(DMI_PRODUCT_NAME, "2656"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Acer Aspire One 150 */ +		/* Avatar AVIU-145A6 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), +			DMI_MATCH(DMI_SYS_VENDOR, "Intel"), +			DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Intel MBO Desktop D845PESV */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"), +			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), +			DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOPNP)  	},  	{ +		/* +		 * Intel NUC D54250WYK - does not have i8042 controller but +		 * declares PS/2 devices in DSDT. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"), +			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), +			DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOPNP)  	},  	{ +		/* Lenovo 3000 n100 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"), +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Lenovo XiaoXin Air 12 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"), +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "80UN"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Lenovo LaVie Z */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"), +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo LaVie Z"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* Lenovo Ideapad U455 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"), +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "20046"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ +		/* Lenovo ThinkPad L460 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"), +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Advent 4211 */ +		/* Lenovo ThinkPad Twist S230u */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS) +	}, +	{ +		/* LG Electronics X110 */ +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), +			DMI_MATCH(DMI_BOARD_NAME, "X110"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{  		/* Medion Akoya Mini E1210 */ @@ -680,6 +843,7 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {  			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),  			DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{  		/* Medion Akoya E1222 */ @@ -687,331 +851,434 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {  			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),  			DMI_MATCH(DMI_PRODUCT_NAME, "E122X"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	},  	{ -		/* Mivvy M310 */ +		/* MSI Wind U-100 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), -			DMI_MATCH(DMI_PRODUCT_NAME, "N10"), +			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), +			DMI_MATCH(DMI_BOARD_NAME, "U-100"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Dell Vostro 1320 */ +		/* +		 * No data is coming from the touchscreen unless KBC +		 * is in legacy mode. +		 */ +		/* Panasonic CF-29 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"), +			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), +			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Dell Vostro 1520 */ +		/* Medion Akoya E7225 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"), +			DMI_MATCH(DMI_SYS_VENDOR, "Medion"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Dell Vostro 1720 */ +		/* Microsoft Virtual Machine */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), +			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Lenovo Ideapad U455 */ +		/* Medion MAM 2070 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -			DMI_MATCH(DMI_PRODUCT_NAME, "20046"), +			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), +			DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Lenovo ThinkPad L460 */ +		/* TUXEDO BU1406 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"), +			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), +			DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */ +		/* OQO Model 01 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), -			DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"), +			DMI_MATCH(DMI_SYS_VENDOR, "OQO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "00"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Lenovo ThinkPad Twist S230u */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -			DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"), +			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"), +			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* Entroware Proteus */ +		/* Acer Aspire 5 A515 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Entroware"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"), -			DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"), +			DMI_MATCH(DMI_BOARD_VENDOR, "PK"), +			DMI_MATCH(DMI_BOARD_NAME, "Grumpy_PK"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOPNP)  	}, -	{ } -}; - -#ifdef CONFIG_PNP -static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {  	{ -		/* Intel MBO Desktop D845PESV */ +		/* ULI EV4873 - AUX LOOP does not work properly */  		.matches = { -			DMI_MATCH(DMI_BOARD_NAME, "D845PESV"), -			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), +			DMI_MATCH(DMI_SYS_VENDOR, "ULI"), +			DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{  		/* -		 * Intel NUC D54250WYK - does not have i8042 controller but -		 * declares PS/2 devices in DSDT. +		 * Arima-Rioworks HDAMB - +		 * AUX LOOP command does not raise AUX IRQ  		 */  		.matches = { -			DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"), -			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), +			DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"), +			DMI_MATCH(DMI_BOARD_NAME, "HDAMB"), +			DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	},  	{ -		/* MSI Wind U-100 */ +		/* Sharp Actius MM20 */  		.matches = { -			DMI_MATCH(DMI_BOARD_NAME, "U-100"), -			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), +			DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), +			DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ -		/* Acer Aspire 5 A515 */ +		/* +		 * Sony Vaio FZ-240E - +		 * reset and GET ID commands issued via KBD port are +		 * sometimes being delivered to AUX3. +		 */  		.matches = { -			DMI_MATCH(DMI_BOARD_NAME, "Grumpy_PK"), -			DMI_MATCH(DMI_BOARD_VENDOR, "PK"), +			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX) +	}, +	{ +		/* +		 * Most (all?) VAIOs do not have external PS/2 ports nor +		 * they implement active multiplexing properly, and +		 * MUX discovery usually messes up keyboard/touchpad. +		 */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +			DMI_MATCH(DMI_BOARD_NAME, "VAIO"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	}, -	{ } -}; - -static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = {  	{ +		/* Sony Vaio FS-115b */  		.matches = { -			DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ +			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{ +		/* +		 * Sony Vaio VGN-CS series require MUX or the touch sensor +		 * buttons will disturb touchpad operation +		 */  		.matches = { -			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ +			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), +			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_FORCEMUX)  	},  	{  		.matches = { -			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ +			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	},  	{  		.matches = { -			DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ +			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), +			DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	}, -	{ } -}; -#endif - -static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {  	{ -		/* Dell Vostro V13 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), +			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), +			DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX)  	}, +	/* +	 * A lot of modern Clevo barebones have touchpad and/or keyboard issues +	 * after suspend fixable with nomux + reset + noloop + nopnp. Luckily, +	 * none of them have an external PS/2 port so this can safely be set for +	 * all of them. These two are based on a Clevo design, but have the +	 * board_name changed. +	 */  	{ -		/* Newer HP Pavilion dv4 models */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), -			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"), +			DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"), +			DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Fujitsu A544 laptop */ -		/* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"), +			DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"), +			DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Fujitsu AH544 laptop */ -		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ +		/* Mivvy M310 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"), +			DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "N10"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)  	}, +	/* +	 * Some laptops need keyboard reset before probing for the trackpad to get +	 * it detected, initialised & finally work. +	 */  	{ -		/* Fujitsu Lifebook T725 laptop */ +		/* Schenker XMG C504 - Elantech touchpad */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"), +			DMI_MATCH(DMI_SYS_VENDOR, "XMG"), +			DMI_MATCH(DMI_PRODUCT_NAME, "C504"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)  	},  	{ -		/* Fujitsu U574 laptop */ -		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ +		/* Blue FB5601 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), +			DMI_MATCH(DMI_SYS_VENDOR, "blue"), +			DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"), +			DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)  	}, +	/* +	 * A lot of modern Clevo barebones have touchpad and/or keyboard issues +	 * after suspend fixable with nomux + reset + noloop + nopnp. Luckily, +	 * none of them have an external PS/2 port so this can safely be set for +	 * all of them. +	 * Clevo barebones come with board_vendor and/or system_vendor set to +	 * either the very generic string "Notebook" and/or a different value +	 * for each individual reseller. The only somewhat universal way to +	 * identify them is by board_name. +	 */  	{ -		/* Fujitsu UH554 laptop */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), -			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"), +			DMI_MATCH(DMI_BOARD_NAME, "LAPQC71A"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	}, -	{ } -}; - -/* - * Some Wistron based laptops need us to explicitly enable the 'Dritek - * keyboard extension' to make their extra keys start generating scancodes. - * Originally, this was just confined to older laptops, but a few Acer laptops - * have turned up in 2007 that also need this again. - */ -static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {  	{ -		/* Acer Aspire 5100 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), +			DMI_MATCH(DMI_BOARD_NAME, "LAPQC71B"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer Aspire 5610 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), +			DMI_MATCH(DMI_BOARD_NAME, "N140CU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer Aspire 5630 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), +			DMI_MATCH(DMI_BOARD_NAME, "N141CU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer Aspire 5650 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), +			DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer Aspire 5680 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), +			DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	}, +	/* +	 * At least one modern Clevo barebone has the touchpad connected both +	 * via PS/2 and i2c interface. This causes a race condition between the +	 * psmouse and i2c-hid driver. Since the full capability of the touchpad +	 * is available via the i2c interface and the device has no external +	 * PS/2 port, it is safe to just ignore all ps2 mouses here to avoid +	 * this issue. The known affected device is the +	 * TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU which comes with one of +	 * the two different dmi strings below. NS50MU is not a typo! +	 */  	{ -		/* Acer Aspire 5720 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"), +			DMI_MATCH(DMI_BOARD_NAME, "NS50MU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX | +					SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | +					SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer Aspire 9110 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), +			DMI_MATCH(DMI_BOARD_NAME, "NS50_70MU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX | +					SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | +					SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer TravelMate 660 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"), +			DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer TravelMate 2490 */ +		/* +		 * This is only a partial board_name and might be followed by +		 * another letter or number. DMI_MATCH however does do partial +		 * matching. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P65xH"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Acer TravelMate 4280 */ +		/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	}, -	{ } -}; - -/* - * Some laptops need keyboard reset before probing for the trackpad to get - * it detected, initialised & finally work. - */ -static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {  	{ -		/* Gigabyte P35 v2 - Elantech touchpad */ +		/* +		 * This is only a partial board_name and might be followed by +		 * another letter or number. DMI_MATCH however does do partial +		 * matching. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P65_P67H"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	}, -		{ -		/* Aorus branded Gigabyte X3 Plus - Elantech touchpad */ +	{ +		/* +		 * This is only a partial board_name and might be followed by +		 * another letter or number. DMI_MATCH however does do partial +		 * matching. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "X3"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P65_67RP"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Gigabyte P34 - Elantech touchpad */ +		/* +		 * This is only a partial board_name and might be followed by +		 * another letter or number. DMI_MATCH however does do partial +		 * matching. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "P34"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P65_67RS"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Gigabyte P57 - Elantech touchpad */ +		/* +		 * This is only a partial board_name and might be followed by +		 * another letter or number. DMI_MATCH however does do partial +		 * matching. +		 */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), -			DMI_MATCH(DMI_PRODUCT_NAME, "P57"), +			DMI_MATCH(DMI_PRODUCT_NAME, "P67xRP"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ -		/* Schenker XMG C504 - Elantech touchpad */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "XMG"), -			DMI_MATCH(DMI_PRODUCT_NAME, "C504"), +			DMI_MATCH(DMI_BOARD_NAME, "PB50_70DFx,DDx"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) +	}, +	{ +		.matches = { +			DMI_MATCH(DMI_BOARD_NAME, "X170SM"),  		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) +	}, +	{ +		.matches = { +			DMI_MATCH(DMI_BOARD_NAME, "X170KM-G"), +		}, +		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | +					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)  	},  	{ }  }; -static const struct dmi_system_id i8042_dmi_probe_defer_table[] __initconst = { +#ifdef CONFIG_PNP +static const struct dmi_system_id i8042_dmi_laptop_table[] __initconst = {  	{ -		/* ASUS ZenBook UX425UA */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"), +			DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */  		},  	},  	{ -		/* ASUS ZenBook UM325UA */  		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), +			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ +		}, +	}, +	{ +		.matches = { +			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ +		}, +	}, +	{ +		.matches = { +			DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */  		},  	},  	{ }  }; +#endif  #endif /* CONFIG_X86 */ @@ -1167,11 +1434,6 @@ static int __init i8042_pnp_init(void)  	bool pnp_data_busted = false;  	int err; -#ifdef CONFIG_X86 -	if (dmi_check_system(i8042_dmi_nopnp_table)) -		i8042_nopnp = true; -#endif -  	if (i8042_nopnp) {  		pr_info("PNP detection disabled\n");  		return 0; @@ -1275,6 +1537,59 @@ static inline int i8042_pnp_init(void) { return 0; }  static inline void i8042_pnp_exit(void) { }  #endif /* CONFIG_PNP */ + +#ifdef CONFIG_X86 +static void __init i8042_check_quirks(void) +{ +	const struct dmi_system_id *device_quirk_info; +	uintptr_t quirks; + +	device_quirk_info = dmi_first_match(i8042_dmi_quirk_table); +	if (!device_quirk_info) +		return; + +	quirks = (uintptr_t)device_quirk_info->driver_data; + +	if (quirks & SERIO_QUIRK_NOKBD) +		i8042_nokbd = true; +	if (quirks & SERIO_QUIRK_NOAUX) +		i8042_noaux = true; +	if (quirks & SERIO_QUIRK_NOMUX) +		i8042_nomux = true; +	if (quirks & SERIO_QUIRK_FORCEMUX) +		i8042_nomux = false; +	if (quirks & SERIO_QUIRK_UNLOCK) +		i8042_unlock = true; +	if (quirks & SERIO_QUIRK_PROBE_DEFER) +		i8042_probe_defer = true; +	/* Honor module parameter when value is not default */ +	if (i8042_reset == I8042_RESET_DEFAULT) { +		if (quirks & SERIO_QUIRK_RESET_ALWAYS) +			i8042_reset = I8042_RESET_ALWAYS; +		if (quirks & SERIO_QUIRK_RESET_NEVER) +			i8042_reset = I8042_RESET_NEVER; +	} +	if (quirks & SERIO_QUIRK_DIECT) +		i8042_direct = true; +	if (quirks & SERIO_QUIRK_DUMBKBD) +		i8042_dumbkbd = true; +	if (quirks & SERIO_QUIRK_NOLOOP) +		i8042_noloop = true; +	if (quirks & SERIO_QUIRK_NOTIMEOUT) +		i8042_notimeout = true; +	if (quirks & SERIO_QUIRK_KBDRESET) +		i8042_kbdreset = true; +	if (quirks & SERIO_QUIRK_DRITEK) +		i8042_dritek = true; +#ifdef CONFIG_PNP +	if (quirks & SERIO_QUIRK_NOPNP) +		i8042_nopnp = true; +#endif +} +#else +static inline void i8042_check_quirks(void) {} +#endif +  static int __init i8042_platform_init(void)  {  	int retval; @@ -1297,45 +1612,42 @@ static int __init i8042_platform_init(void)  	i8042_kbd_irq = I8042_MAP_IRQ(1);  	i8042_aux_irq = I8042_MAP_IRQ(12); -	retval = i8042_pnp_init(); -	if (retval) -		return retval; -  #if defined(__ia64__) -        i8042_reset = I8042_RESET_ALWAYS; +	i8042_reset = I8042_RESET_ALWAYS;  #endif +	i8042_check_quirks(); + +	pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s\n", +		i8042_nokbd ? " nokbd" : "", +		i8042_noaux ? " noaux" : "", +		i8042_nomux ? " nomux" : "", +		i8042_unlock ? " unlock" : "", +		i8042_probe_defer ? "probe_defer" : "", +		i8042_reset == I8042_RESET_DEFAULT ? +			"" : i8042_reset == I8042_RESET_ALWAYS ? +				" reset_always" : " reset_never", +		i8042_direct ? " direct" : "", +		i8042_dumbkbd ? " dumbkbd" : "", +		i8042_noloop ? " noloop" : "", +		i8042_notimeout ? " notimeout" : "", +		i8042_kbdreset ? " kbdreset" : "",  #ifdef CONFIG_X86 -	/* Honor module parameter when value is not default */ -	if (i8042_reset == I8042_RESET_DEFAULT) { -		if (dmi_check_system(i8042_dmi_reset_table)) -			i8042_reset = I8042_RESET_ALWAYS; - -		if (dmi_check_system(i8042_dmi_noselftest_table)) -			i8042_reset = I8042_RESET_NEVER; -	} - -	if (dmi_check_system(i8042_dmi_noloop_table)) -		i8042_noloop = true; - -	if (dmi_check_system(i8042_dmi_nomux_table)) -		i8042_nomux = true; - -	if (dmi_check_system(i8042_dmi_forcemux_table)) -		i8042_nomux = false; - -	if (dmi_check_system(i8042_dmi_notimeout_table)) -		i8042_notimeout = true; - -	if (dmi_check_system(i8042_dmi_dritek_table)) -		i8042_dritek = true; - -	if (dmi_check_system(i8042_dmi_kbdreset_table)) -		i8042_kbdreset = true; +		i8042_dritek ? " dritek" : "", +#else +		"", +#endif +#ifdef CONFIG_PNP +		i8042_nopnp ? " nopnp" : ""); +#else +		""); +#endif -	if (dmi_check_system(i8042_dmi_probe_defer_table)) -		i8042_probe_defer = true; +	retval = i8042_pnp_init(); +	if (retval) +		return retval; +#ifdef CONFIG_X86  	/*  	 * A20 was already enabled during early kernel init. But some buggy  	 * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index bb2e1cbffba7..82beddb28761 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -24,6 +24,7 @@  #include <linux/irq.h>  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/property.h>  #include <linux/ratelimit.h>  #include <linux/regulator/consumer.h>  #include <linux/slab.h> @@ -47,6 +48,8 @@  #define M09_REGISTER_NUM_X		0x94  #define M09_REGISTER_NUM_Y		0x95 +#define M12_REGISTER_REPORT_RATE	0x88 +  #define EV_REGISTER_THRESHOLD		0x40  #define EV_REGISTER_GAIN		0x41  #define EV_REGISTER_OFFSET_Y		0x45 @@ -127,9 +130,12 @@ struct edt_ft5x06_ts_data {  	int max_support_points;  	char name[EDT_NAME_LEN]; +	char fw_version[EDT_NAME_LEN];  	struct edt_reg_addr reg_addr;  	enum edt_ver version; +	unsigned int crc_errors; +	unsigned int header_errors;  };  struct edt_i2c_chip_data { @@ -178,6 +184,7 @@ static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,  		crc ^= buf[i];  	if (crc != buf[buflen-1]) { +		tsdata->crc_errors++;  		dev_err_ratelimited(&tsdata->client->dev,  				    "crc error: 0x%02x expected, got 0x%02x\n",  				    crc, buf[buflen-1]); @@ -235,6 +242,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)  	if (tsdata->version == EDT_M06) {  		if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||  			rdbuf[2] != datalen) { +			tsdata->header_errors++;  			dev_err_ratelimited(dev,  					"Unexpected header: %02x%02x%02x!\n",  					rdbuf[0], rdbuf[1], rdbuf[2]); @@ -523,9 +531,55 @@ static EDT_ATTR(offset_y, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,  /* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */  static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,  		M09_REGISTER_THRESHOLD, EV_REGISTER_THRESHOLD, 0, 255); -/* m06: range 3 to 14, m12: (0x64: 100Hz) */ +/* m06: range 3 to 14, m12: range 1 to 255 */  static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, -		NO_REGISTER, NO_REGISTER, 0, 255); +		M12_REGISTER_REPORT_RATE, NO_REGISTER, 0, 255); + +static ssize_t model_show(struct device *dev, struct device_attribute *attr, +			  char *buf) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + +	return sysfs_emit(buf, "%s\n", tsdata->name); +} + +static DEVICE_ATTR_RO(model); + +static ssize_t fw_version_show(struct device *dev, +			       struct device_attribute *attr, char *buf) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + +	return sysfs_emit(buf, "%s\n", tsdata->fw_version); +} + +static DEVICE_ATTR_RO(fw_version); + +/* m06 only */ +static ssize_t header_errors_show(struct device *dev, +				  struct device_attribute *attr, char *buf) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + +	return sysfs_emit(buf, "%d\n", tsdata->header_errors); +} + +static DEVICE_ATTR_RO(header_errors); + +/* m06 only */ +static ssize_t crc_errors_show(struct device *dev, +			       struct device_attribute *attr, char *buf) +{ +	struct i2c_client *client = to_i2c_client(dev); +	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + +	return sysfs_emit(buf, "%d\n", tsdata->crc_errors); +} + +static DEVICE_ATTR_RO(crc_errors);  static struct attribute *edt_ft5x06_attrs[] = {  	&edt_ft5x06_attr_gain.dattr.attr, @@ -534,6 +588,10 @@ static struct attribute *edt_ft5x06_attrs[] = {  	&edt_ft5x06_attr_offset_y.dattr.attr,  	&edt_ft5x06_attr_threshold.dattr.attr,  	&edt_ft5x06_attr_report_rate.dattr.attr, +	&dev_attr_model.attr, +	&dev_attr_fw_version.attr, +	&dev_attr_header_errors.attr, +	&dev_attr_crc_errors.attr,  	NULL  }; @@ -820,13 +878,13 @@ static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)  #endif /* CONFIG_DEBUGFS */  static int edt_ft5x06_ts_identify(struct i2c_client *client, -					struct edt_ft5x06_ts_data *tsdata, -					char *fw_version) +				  struct edt_ft5x06_ts_data *tsdata)  {  	u8 rdbuf[EDT_NAME_LEN];  	char *p;  	int error;  	char *model_name = tsdata->name; +	char *fw_version = tsdata->fw_version;  	/* see what we find if we assume it is a M06 *  	 * if we get less than EDT_NAME_LEN, we don't want @@ -1030,7 +1088,8 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)  	case EDT_M09:  	case EDT_M12:  		reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; -		reg_addr->reg_report_rate = NO_REGISTER; +		reg_addr->reg_report_rate = tsdata->version == EDT_M12 ? +			M12_REGISTER_REPORT_RATE : NO_REGISTER;  		reg_addr->reg_gain = M09_REGISTER_GAIN;  		reg_addr->reg_offset = M09_REGISTER_OFFSET;  		reg_addr->reg_offset_x = NO_REGISTER; @@ -1081,7 +1140,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,  	struct input_dev *input;  	unsigned long irq_flags;  	int error; -	char fw_version[EDT_NAME_LEN]; +	u32 report_rate;  	dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); @@ -1194,7 +1253,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,  	tsdata->input = input;  	tsdata->factory_mode = false; -	error = edt_ft5x06_ts_identify(client, tsdata, fw_version); +	error = edt_ft5x06_ts_identify(client, tsdata);  	if (error) {  		dev_err(&client->dev, "touchscreen probe failed\n");  		return error; @@ -1210,9 +1269,30 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,  	edt_ft5x06_ts_get_defaults(&client->dev, tsdata);  	edt_ft5x06_ts_get_parameters(tsdata); +	if (tsdata->reg_addr.reg_report_rate != NO_REGISTER && +	    !device_property_read_u32(&client->dev, +				      "report-rate-hz", &report_rate)) { +		if (tsdata->version == EDT_M06) +			tsdata->report_rate = clamp_val(report_rate, 30, 140); +		else +			tsdata->report_rate = clamp_val(report_rate, 1, 255); + +		if (report_rate != tsdata->report_rate) +			dev_warn(&client->dev, +				 "report-rate %dHz is unsupported, use %dHz\n", +				 report_rate, tsdata->report_rate); + +		if (tsdata->version == EDT_M06) +			tsdata->report_rate /= 10; + +		edt_ft5x06_register_write(tsdata, +					  tsdata->reg_addr.reg_report_rate, +					  tsdata->report_rate); +	} +  	dev_dbg(&client->dev,  		"Model \"%s\", Rev. \"%s\", %dx%d sensors\n", -		tsdata->name, fw_version, tsdata->num_x, tsdata->num_y); +		tsdata->name, tsdata->fw_version, tsdata->num_x, tsdata->num_y);  	input->name = tsdata->name;  	input->id.bustype = BUS_I2C; diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index cbe0dd412912..4b7eee01c6aa 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -220,6 +220,7 @@ static int exc3000_vendor_data_request(struct exc3000_data *data, u8 *request,  {  	u8 buf[EXC3000_LEN_VENDOR_REQUEST] = { 0x67, 0x00, 0x42, 0x00, 0x03 };  	int ret; +	unsigned long time_left;  	mutex_lock(&data->query_lock); @@ -233,9 +234,9 @@ static int exc3000_vendor_data_request(struct exc3000_data *data, u8 *request,  		goto out_unlock;  	if (response) { -		ret = wait_for_completion_timeout(&data->wait_event, -						  timeout * HZ); -		if (ret <= 0) { +		time_left = wait_for_completion_timeout(&data->wait_event, +							timeout * HZ); +		if (time_left == 0) {  			ret = -ETIMEDOUT;  			goto out_unlock;  		} diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index aa45a9fee6a0..d016505fc081 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -822,22 +822,16 @@ static int goodix_resource(struct acpi_resource *ares, void *data)  	struct device *dev = &ts->client->dev;  	struct acpi_resource_gpio *gpio; -	switch (ares->type) { -	case ACPI_RESOURCE_TYPE_GPIO: -		gpio = &ares->data.gpio; -		if (gpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT) { -			if (ts->gpio_int_idx == -1) { -				ts->gpio_int_idx = ts->gpio_count; -			} else { -				dev_err(dev, "More then one GpioInt resource, ignoring ACPI GPIO resources\n"); -				ts->gpio_int_idx = -2; -			} +	if (acpi_gpio_get_irq_resource(ares, &gpio)) { +		if (ts->gpio_int_idx == -1) { +			ts->gpio_int_idx = ts->gpio_count; +		} else { +			dev_err(dev, "More then one GpioInt resource, ignoring ACPI GPIO resources\n"); +			ts->gpio_int_idx = -2;  		}  		ts->gpio_count++; -		break; -	default: -		break; -	} +	} else if (acpi_gpio_get_io_resource(ares, &gpio)) +		ts->gpio_count++;  	return 0;  } diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c index 8bd03278ad9a..52f9e9eaab14 100644 --- a/drivers/input/touchscreen/zinitix.c +++ b/drivers/input/touchscreen/zinitix.c @@ -15,75 +15,75 @@  /* Register Map */ -#define BT541_SWRESET_CMD			0x0000 -#define BT541_WAKEUP_CMD			0x0001 +#define ZINITIX_SWRESET_CMD			0x0000 +#define ZINITIX_WAKEUP_CMD			0x0001 -#define BT541_IDLE_CMD				0x0004 -#define BT541_SLEEP_CMD				0x0005 +#define ZINITIX_IDLE_CMD			0x0004 +#define ZINITIX_SLEEP_CMD			0x0005 -#define BT541_CLEAR_INT_STATUS_CMD		0x0003 -#define BT541_CALIBRATE_CMD			0x0006 -#define BT541_SAVE_STATUS_CMD			0x0007 -#define BT541_SAVE_CALIBRATION_CMD		0x0008 -#define BT541_RECALL_FACTORY_CMD		0x000f +#define ZINITIX_CLEAR_INT_STATUS_CMD		0x0003 +#define ZINITIX_CALIBRATE_CMD			0x0006 +#define ZINITIX_SAVE_STATUS_CMD			0x0007 +#define ZINITIX_SAVE_CALIBRATION_CMD		0x0008 +#define ZINITIX_RECALL_FACTORY_CMD		0x000f -#define BT541_THRESHOLD				0x0020 +#define ZINITIX_THRESHOLD			0x0020 -#define BT541_LARGE_PALM_REJECT_AREA_TH		0x003F +#define ZINITIX_LARGE_PALM_REJECT_AREA_TH	0x003F -#define BT541_DEBUG_REG				0x0115 /* 0~7 */ +#define ZINITIX_DEBUG_REG			0x0115 /* 0~7 */ -#define BT541_TOUCH_MODE			0x0010 -#define BT541_CHIP_REVISION			0x0011 -#define BT541_FIRMWARE_VERSION			0x0012 +#define ZINITIX_TOUCH_MODE			0x0010 +#define ZINITIX_CHIP_REVISION			0x0011 +#define ZINITIX_FIRMWARE_VERSION		0x0012  #define ZINITIX_USB_DETECT			0x116 -#define BT541_MINOR_FW_VERSION			0x0121 +#define ZINITIX_MINOR_FW_VERSION		0x0121 -#define BT541_VENDOR_ID				0x001C -#define BT541_HW_ID				0x0014 +#define ZINITIX_VENDOR_ID			0x001C +#define ZINITIX_HW_ID				0x0014 -#define BT541_DATA_VERSION_REG			0x0013 -#define BT541_SUPPORTED_FINGER_NUM		0x0015 -#define BT541_EEPROM_INFO			0x0018 -#define BT541_INITIAL_TOUCH_MODE		0x0019 +#define ZINITIX_DATA_VERSION_REG		0x0013 +#define ZINITIX_SUPPORTED_FINGER_NUM		0x0015 +#define ZINITIX_EEPROM_INFO			0x0018 +#define ZINITIX_INITIAL_TOUCH_MODE		0x0019 -#define BT541_TOTAL_NUMBER_OF_X			0x0060 -#define BT541_TOTAL_NUMBER_OF_Y			0x0061 +#define ZINITIX_TOTAL_NUMBER_OF_X		0x0060 +#define ZINITIX_TOTAL_NUMBER_OF_Y		0x0061 -#define BT541_DELAY_RAW_FOR_HOST		0x007f +#define ZINITIX_DELAY_RAW_FOR_HOST		0x007f -#define BT541_BUTTON_SUPPORTED_NUM		0x00B0 -#define BT541_BUTTON_SENSITIVITY		0x00B2 -#define BT541_DUMMY_BUTTON_SENSITIVITY		0X00C8 +#define ZINITIX_BUTTON_SUPPORTED_NUM		0x00B0 +#define ZINITIX_BUTTON_SENSITIVITY		0x00B2 +#define ZINITIX_DUMMY_BUTTON_SENSITIVITY	0X00C8 -#define BT541_X_RESOLUTION			0x00C0 -#define BT541_Y_RESOLUTION			0x00C1 +#define ZINITIX_X_RESOLUTION			0x00C0 +#define ZINITIX_Y_RESOLUTION			0x00C1 -#define BT541_POINT_STATUS_REG			0x0080 -#define BT541_ICON_STATUS_REG			0x00AA +#define ZINITIX_POINT_STATUS_REG		0x0080 +#define ZINITIX_ICON_STATUS_REG			0x00AA -#define BT541_POINT_COORD_REG			(BT541_POINT_STATUS_REG + 2) +#define ZINITIX_POINT_COORD_REG			(ZINITIX_POINT_STATUS_REG + 2) -#define BT541_AFE_FREQUENCY			0x0100 -#define BT541_DND_N_COUNT			0x0122 -#define BT541_DND_U_COUNT			0x0135 +#define ZINITIX_AFE_FREQUENCY			0x0100 +#define ZINITIX_DND_N_COUNT			0x0122 +#define ZINITIX_DND_U_COUNT			0x0135 -#define BT541_RAWDATA_REG			0x0200 +#define ZINITIX_RAWDATA_REG			0x0200 -#define BT541_EEPROM_INFO_REG			0x0018 +#define ZINITIX_EEPROM_INFO_REG			0x0018 -#define BT541_INT_ENABLE_FLAG			0x00f0 -#define BT541_PERIODICAL_INTERRUPT_INTERVAL	0x00f1 +#define ZINITIX_INT_ENABLE_FLAG			0x00f0 +#define ZINITIX_PERIODICAL_INTERRUPT_INTERVAL	0x00f1 -#define BT541_BTN_WIDTH				0x016d +#define ZINITIX_BTN_WIDTH			0x016d -#define BT541_CHECKSUM_RESULT			0x012c +#define ZINITIX_CHECKSUM_RESULT			0x012c -#define BT541_INIT_FLASH			0x01d0 -#define BT541_WRITE_FLASH			0x01d1 -#define BT541_READ_FLASH			0x01d2 +#define ZINITIX_INIT_FLASH			0x01d0 +#define ZINITIX_WRITE_FLASH			0x01d1 +#define ZINITIX_READ_FLASH			0x01d2  #define ZINITIX_INTERNAL_FLAG_02		0x011e  #define ZINITIX_INTERNAL_FLAG_03		0x011f @@ -196,13 +196,13 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541)  	int i;  	int error; -	error = zinitix_write_cmd(client, BT541_SWRESET_CMD); +	error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD);  	if (error) {  		dev_err(&client->dev, "Failed to write reset command\n");  		return error;  	} -	error = zinitix_write_u16(client, BT541_INT_ENABLE_FLAG, 0x0); +	error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 0x0);  	if (error) {  		dev_err(&client->dev,  			"Failed to reset interrupt enable flag\n"); @@ -210,32 +210,32 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541)  	}  	/* initialize */ -	error = zinitix_write_u16(client, BT541_X_RESOLUTION, +	error = zinitix_write_u16(client, ZINITIX_X_RESOLUTION,  				  bt541->prop.max_x);  	if (error)  		return error; -	error = zinitix_write_u16(client, BT541_Y_RESOLUTION, +	error = zinitix_write_u16(client, ZINITIX_Y_RESOLUTION,  				  bt541->prop.max_y);  	if (error)  		return error; -	error = zinitix_write_u16(client, BT541_SUPPORTED_FINGER_NUM, +	error = zinitix_write_u16(client, ZINITIX_SUPPORTED_FINGER_NUM,  				  MAX_SUPPORTED_FINGER_NUM);  	if (error)  		return error; -	error = zinitix_write_u16(client, BT541_INITIAL_TOUCH_MODE, +	error = zinitix_write_u16(client, ZINITIX_INITIAL_TOUCH_MODE,  				  bt541->zinitix_mode);  	if (error)  		return error; -	error = zinitix_write_u16(client, BT541_TOUCH_MODE, +	error = zinitix_write_u16(client, ZINITIX_TOUCH_MODE,  				  bt541->zinitix_mode);  	if (error)  		return error; -	error = zinitix_write_u16(client, BT541_INT_ENABLE_FLAG, +	error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG,  				  BIT_PT_CNT_CHANGE | BIT_DOWN | BIT_MOVE |  					BIT_UP);  	if (error) @@ -243,7 +243,7 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541)  	/* clear queue */  	for (i = 0; i < 10; i++) { -		zinitix_write_cmd(client, BT541_CLEAR_INT_STATUS_CMD); +		zinitix_write_cmd(client, ZINITIX_CLEAR_INT_STATUS_CMD);  		udelay(10);  	} @@ -361,7 +361,7 @@ static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler)  	memset(&touch_event, 0, sizeof(struct touch_event)); -	error = zinitix_read_data(bt541->client, BT541_POINT_STATUS_REG, +	error = zinitix_read_data(bt541->client, ZINITIX_POINT_STATUS_REG,  				  &touch_event, sizeof(struct touch_event));  	if (error) {  		dev_err(&client->dev, "Failed to read in touchpoint struct\n"); @@ -381,7 +381,7 @@ static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler)  	input_sync(bt541->input_dev);  out: -	zinitix_write_cmd(bt541->client, BT541_CLEAR_INT_STATUS_CMD); +	zinitix_write_cmd(bt541->client, ZINITIX_CLEAR_INT_STATUS_CMD);  	return IRQ_HANDLED;  } |