From nobody Thu Dec 18 07:58:06 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16A22C77B7A for ; Fri, 14 Apr 2023 23:38:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229764AbjDNXi5 (ORCPT ); Fri, 14 Apr 2023 19:38:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52404 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229464AbjDNXix (ORCPT ); Fri, 14 Apr 2023 19:38:53 -0400 Received: from smtp1.axis.com (smtp1.axis.com [195.60.68.17]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7BA79526E; Fri, 14 Apr 2023 16:38:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1681515532; x=1713051532; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SpLMjeGM/opNypIBwbbL34Zq2CgvgZH99FHYABysyCM=; b=k7Nfc/x/6cRH72h9fg7JCb+jKF4vbeCGPsO/7eWfv6FTt0uw0aO4mgJI yoLZO3mF98guuvaEZRIOIJD7HoQElDo8ptaYzV37AmyeyJYhY5EtAGm41 Vgv0FIGZtlzsXHYnxB35sEPN0An6wninEJh14HSAZAcs6oQcCNj5TF1JQ FykzngC757S8BVPsaU9ahY6Dq8iha3DgBBc+O0z/x76kWQCAizS4I1Psl oOYRAjcoYEm+Fct5sBuvH04tKeDuWLgaV6/MrieeFsbXW4OjYG9CVsGJj IJCq+mmsr3e2mTCGRWu5hvjEF7WO6pqZA9SqQ3LhElqvGSQDvIIZ7n58H A==; From: Jiri Valek - 2N To: , CC: , , , , , Subject: [PATCH 1/2] dt-bindings: input: microchip,cap11xx: add advanced sensitivity settings Date: Sat, 15 Apr 2023 01:38:14 +0200 Message-ID: <20230414233815.4004526-2-jiriv@axis.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230414233815.4004526-1-jiriv@axis.com> References: <20230414233815.4004526-1-jiriv@axis.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.0.5.60] X-ClientProxiedBy: se-mail02w.axis.com (10.20.40.8) To se-mail01w.axis.com (10.20.40.7) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for advanced sensitivity settings and signal guard feature. Signed-off-by: Jiri Valek - 2N --- .../bindings/input/microchip,cap11xx.yaml | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml= b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml index 5fa625b5c5fb..08e28226a164 100644 --- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml +++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml @@ -45,13 +45,13 @@ properties: Enables the Linux input system's autorepeat feature on the input dev= ice. =20 linux,keycodes: - minItems: 6 - maxItems: 6 + minItems: 3 + maxItems: 8 description: | Specifies an array of numeric keycode values to be used for the channels. If this property is omitted, KEY_A, KEY_B, etc are used as defaults. - The array must have exactly six entries. + The number of entries must correspond to the number of channels. =20 microchip,sensor-gain: $ref: /schemas/types.yaml#/definitions/uint32 @@ -70,6 +70,58 @@ properties: open drain. This property allows using the active high push-pull output. =20 + microchip,sensitivity-delta-sense: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 32 + enum: [1, 2, 4, 8, 16, 32, 64, 128] + description: | + Optional parameter. Controls the sensitivity multiplier of a touch d= etection. + At the more sensitive settings, touches are detected for a smaller d= elta + capacitance corresponding to a =E2=80=9Clighter=E2=80=9D touch. + + microchip,sensitivity-base-shift: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 256 + enum: [1, 2, 4, 8, 16, 32, 64, 128, 256] + description: | + Optional parameter. Controls data scaling factor. + The higher the value of these bits, the larger the range and the low= er + the resolution of the data presented. These settings will not affect + touch detection or sensitivity. + + microchip,signal-guard: + minItems: 3 + maxItems: 8 + enum: [0, 1] + default: 0 + description: | + Optional parameter supported only for CAP129x. + The signal guard isolates the signal from virtual grounds. + If enabled then the behavior of the channel is changed to signal gua= rd. + The number of entries must correspond to the number of channels. + + microchip,input-treshold: + minItems: 3 + maxItems: 8 + minimum: 0 + maximum: 127 + default: 64 + description: | + Optional parameter. Specifies the delta threshold that is used to + determine if a touch has been detected. + The number of entries must correspond to the number of channels. + + microchip,calib-sensitivity: + minItems: 3 + maxItems: 8 + enum: [1, 2, 4] + default: 1 + description: | + Optional parameter supported only for CAP129x. Specifies an array of + numeric values that controls the gain used by the calibration routin= e to + enable sensor inputs to be more sensitive for proximity detection. + The number of entries must correspond to the number of channels. + patternProperties: "^led@[0-7]$": type: object @@ -122,6 +174,12 @@ examples: reg =3D <0x28>; autorepeat; microchip,sensor-gain =3D <2>; + microchip,sensitivity-delta-sense =3D <16>; + microchip,sensitivity-base-shift =3D <128>; + + microchip,signal-guard =3D <0>, <0>, <0>, <0>, <0>, <0>; + microchip,input-treshold =3D <21>, <18>, <46>, <46>, <46>, <21>; + microchip,calib-sensitivityj =3D <1>, <2>, <2>, <1>, <1>, <2>; =20 linux,keycodes =3D <103>, /* KEY_UP */ <106>, /* KEY_RIGHT */ --=20 2.25.1 From nobody Thu Dec 18 07:58:06 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF3B8C77B71 for ; Fri, 14 Apr 2023 23:39:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229729AbjDNXi7 (ORCPT ); Fri, 14 Apr 2023 19:38:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229638AbjDNXiy (ORCPT ); Fri, 14 Apr 2023 19:38:54 -0400 Received: from smtp2.axis.com (smtp2.axis.com [195.60.68.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 16F70558B; Fri, 14 Apr 2023 16:38:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=axis.com; q=dns/txt; s=axis-central1; t=1681515533; x=1713051533; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6QIxtJ/MY1fTBU4VbKkd3bP6Ke+kH+7tOPWORRgbwss=; b=fY5zqx/Apfu1+6mh8UFt67+iQBrwqAvvpukAqmhhU52iszNhLF06TcIj XtEj2CQgRnbBNz/OVifr6S3fsuve68hE447ZFEuCtea9M90dQ9iMA5Dd/ wCjSi4t5vbE0gweIGi+/jGmf7l69z6dCZpw4vLVeEfHKHT5c955/7qRNM m9s5cGOI95kFyvNE/fLpsb4LtUqzvtZwGrfPgTyLN6QQKTbpqMjLTWocU 2s8wt5cQ3uVYt1mIhPCa6Qeavy1pr0+gsMF//4tdWHTSXVjOI6V6RkDpq bsbzhld2uKr7GXJYmSU2VuYFRtEJE1HC079gygFjZSawB55OGPW8H2yaN Q==; From: Jiri Valek - 2N To: , CC: , , , , , Subject: [PATCH 2/2] Input: cap11xx - add advanced sensitivity settings Date: Sat, 15 Apr 2023 01:38:15 +0200 Message-ID: <20230414233815.4004526-3-jiriv@axis.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230414233815.4004526-1-jiriv@axis.com> References: <20230414233815.4004526-1-jiriv@axis.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.0.5.60] X-ClientProxiedBy: se-mail02w.axis.com (10.20.40.8) To se-mail01w.axis.com (10.20.40.7) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add support for advanced sensitivity settings that allows more precise tunig of touch buttons. Input-treshold allows to set the sensitivity for each channel separately. Also add signal guard feature for CAP129x chips. Signed-off-by: Jiri Valek - 2N --- drivers/input/keyboard/cap11xx.c | 263 +++++++++++++++++++++++++------ 1 file changed, 217 insertions(+), 46 deletions(-) diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap1= 1xx.c index 040696d0e49c..d387754e76f5 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -14,6 +14,7 @@ #include #include #include +#include =20 #define CAP11XX_REG_MAIN_CONTROL 0x00 #define CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT (6) @@ -24,6 +25,8 @@ #define CAP11XX_REG_NOISE_FLAG_STATUS 0x0a #define CAP11XX_REG_SENOR_DELTA(X) (0x10 + (X)) #define CAP11XX_REG_SENSITIVITY_CONTROL 0x1f +#define CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK 0x70 +#define CAP11XX_REG_SENSITIVITY_CONTROL_BASE_SHIFT_MASK 0x0F #define CAP11XX_REG_CONFIG 0x20 #define CAP11XX_REG_SENSOR_ENABLE 0x21 #define CAP11XX_REG_SENSOR_CONFIG 0x22 @@ -32,6 +35,7 @@ #define CAP11XX_REG_CALIBRATION 0x26 #define CAP11XX_REG_INT_ENABLE 0x27 #define CAP11XX_REG_REPEAT_RATE 0x28 +#define CAP11XX_REG_SIGNAL_GUARD_ENABLE 0x29 #define CAP11XX_REG_MT_CONFIG 0x2a #define CAP11XX_REG_MT_PATTERN_CONFIG 0x2b #define CAP11XX_REG_MT_PATTERN 0x2d @@ -47,6 +51,8 @@ #define CAP11XX_REG_SENSOR_BASE_CNT(X) (0x50 + (X)) #define CAP11XX_REG_LED_POLARITY 0x73 #define CAP11XX_REG_LED_OUTPUT_CONTROL 0x74 +#define CAP11XX_REG_CALIB_SENSITIVITY_CONFIG 0x80 +#define CAP11XX_REG_CALIB_SENSITIVITY_CONFIG2 0x81 =20 #define CAP11XX_REG_LED_DUTY_CYCLE_1 0x90 #define CAP11XX_REG_LED_DUTY_CYCLE_2 0x91 @@ -78,12 +84,21 @@ struct cap11xx_led { =20 struct cap11xx_priv { struct regmap *regmap; + struct device *dev; struct input_dev *idev; + const struct cap11xx_hw_model *model; + u8 id; =20 struct cap11xx_led *leds; int num_leds; =20 /* config */ + u8 analog_gain; + u8 sensitivity_delta_sense; + u8 sensitivity_base_shift; + u8 signal_guard_inputs_mask; + u32 thresholds[8]; + u32 calib_sensitivities[8]; u32 keycodes[]; }; =20 @@ -181,6 +196,197 @@ static const struct regmap_config cap11xx_regmap_conf= ig =3D { .volatile_reg =3D cap11xx_volatile_reg, }; =20 +static int +cap11xx_write_calib_sens_config_1(struct cap11xx_priv *priv) +{ + return regmap_write(priv->regmap, + CAP11XX_REG_CALIB_SENSITIVITY_CONFIG, + (priv->calib_sensitivities[3] << 6) | + (priv->calib_sensitivities[2] << 4) | + (priv->calib_sensitivities[1] << 2) | + priv->calib_sensitivities[0]); +} + +static int +cap11xx_write_calib_sens_config_2(struct cap11xx_priv *priv) +{ + return regmap_write(priv->regmap, + CAP11XX_REG_CALIB_SENSITIVITY_CONFIG2, + (priv->calib_sensitivities[7] << 6) | + (priv->calib_sensitivities[6] << 4) | + (priv->calib_sensitivities[5] << 2) | + priv->calib_sensitivities[4]); +} + +static int +cap11xx_init_keys(struct cap11xx_priv *priv) +{ + struct device_node *node =3D priv->dev->of_node; + struct device *dev =3D priv->dev; + int i, error; + u32 u32_val; + + if (!node) { + dev_err(dev, "Corresponding DT entry is not available\n"); + return -ENODEV; + } + + if (!of_property_read_u32(node, "microchip,sensor-gain", &u32_val)) { + if (priv->model->no_gain) { + dev_warn(dev, + "This model doesn't support 'sensor-gain'\n"); + } else if (is_power_of_2(u32_val) && u32_val <=3D 8) { + priv->analog_gain =3D (u8)ilog2(u32_val); + + error =3D regmap_update_bits(priv->regmap, + CAP11XX_REG_MAIN_CONTROL, + CAP11XX_REG_MAIN_CONTROL_GAIN_MASK, + priv->analog_gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT); + if (error) + return error; + } else { + dev_err(dev, "Invalid sensor-gain value %u\n", u32_val); + return -EINVAL; + } + } + + if (of_property_read_bool(node, "microchip,irq-active-high")) { + if (priv->id =3D=3D CAP1106 || + priv->id =3D=3D CAP1126 || + priv->id =3D=3D CAP1188) { + error =3D regmap_update_bits(priv->regmap, + CAP11XX_REG_CONFIG2, + CAP11XX_REG_CONFIG2_ALT_POL, + 0); + if (error) + return error; + } else { + dev_warn(dev, + "This model doesn't support 'irq-active-high'\n"); + } + } + + if (!of_property_read_u32(node, + "microchip,sensitivity-delta-sense", &u32_val)) { + if (!is_power_of_2(u32_val) || u32_val > 128) { + dev_err(dev, "Invalid sensitivity-delta-sense value %u\n", u32_val); + return -EINVAL; + } + + priv->sensitivity_delta_sense =3D (u8)ilog2(u32_val); + u32_val =3D ~(FIELD_PREP(CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MAS= K, + priv->sensitivity_delta_sense)); + + error =3D regmap_update_bits(priv->regmap, + CAP11XX_REG_SENSITIVITY_CONTROL, + CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK, + u32_val); + if (error) + return error; + } + + if (!of_property_read_u32(node, + "microchip,sensitivity-base-shift", &u32_val)) { + if (!is_power_of_2(u32_val) || u32_val > 256) { + dev_err(dev, "Invalid sensitivity-base-shift value %u\n", u32_val); + return -EINVAL; + } + + priv->sensitivity_base_shift =3D (u8)ilog2(u32_val); + u32_val =3D FIELD_PREP(CAP11XX_REG_SENSITIVITY_CONTROL_BASE_SHIFT_MASK, + priv->sensitivity_base_shift); + + error =3D regmap_update_bits(priv->regmap, + CAP11XX_REG_SENSITIVITY_CONTROL, + CAP11XX_REG_SENSITIVITY_CONTROL_BASE_SHIFT_MASK, + u32_val); + if (error) + return error; + } + + if (!of_property_read_u32_array(node, "microchip,input-treshold", + priv->thresholds, priv->model->num_channels)) { + for (i =3D 0; i < priv->model->num_channels; i++) { + if (priv->thresholds[i] > 127) { + dev_err(dev, "Invalid input-treshold value %u\n", + priv->thresholds[i]); + return -EINVAL; + } + + error =3D regmap_write(priv->regmap, + CAP11XX_REG_SENSOR_THRESH(i), + priv->thresholds[i]); + if (error) + return error; + } + } + + if (!of_property_read_u32_array(node, "microchip,calib-sensitivity", + priv->calib_sensitivities, priv->model->num_channels)) { + if (priv->id =3D=3D CAP1293 || priv->id =3D=3D CAP1298) { + for (i =3D 0; i < priv->model->num_channels; i++) { + if (!is_power_of_2(priv->calib_sensitivities[i]) || + priv->calib_sensitivities[i] > 4) { + dev_err(dev, "Invalid calib-sensitivity value %u\n", + priv->calib_sensitivities[i]); + return -EINVAL; + } + priv->calib_sensitivities[i] =3D ilog2(priv->calib_sensitivities[i]); + } + + error =3D cap11xx_write_calib_sens_config_1(priv); + if (error) + return error; + + if (priv->id =3D=3D CAP1298) { + error =3D cap11xx_write_calib_sens_config_2(priv); + if (error) + return error; + } + } else { + dev_warn(dev, + "This model doesn't support 'calib-sensitivity'\n"); + } + } + + for (i =3D 0; i < priv->model->num_channels; i++) { + if (!of_property_read_u32_index(node, "microchip,signal-guard", + i, &u32_val)) { + if (u32_val > 1) + return -EINVAL; + if (u32_val) + priv->signal_guard_inputs_mask |=3D 0x01 << i; + } + } + + if (priv->signal_guard_inputs_mask) { + if (priv->id =3D=3D CAP1293 || priv->id =3D=3D CAP1298) { + error =3D regmap_write(priv->regmap, + CAP11XX_REG_SIGNAL_GUARD_ENABLE, + priv->signal_guard_inputs_mask); + if (error) + return error; + } else { + dev_warn(dev, + "This model doesn't support 'signal-guard'\n"); + } + } + + /* Provide some useful defaults */ + for (i =3D 0; i < priv->model->num_channels; i++) + priv->keycodes[i] =3D KEY_A + i; + + of_property_read_u32_array(node, "linux,keycodes", + priv->keycodes, priv->model->num_channels); + + /* Disable autorepeat. The Linux input system has its own handling. */ + error =3D regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0); + if (error) + return error; + + return 0; +} + static irqreturn_t cap11xx_thread_func(int irq_num, void *data) { struct cap11xx_priv *priv =3D data; @@ -332,11 +538,9 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_cl= ient) const struct i2c_device_id *id =3D i2c_client_get_device_id(i2c_client); struct device *dev =3D &i2c_client->dev; struct cap11xx_priv *priv; - struct device_node *node; const struct cap11xx_hw_model *cap; - int i, error, irq, gain =3D 0; + int i, error, irq; unsigned int val, rev; - u32 gain32; =20 if (id->driver_data >=3D ARRAY_SIZE(cap11xx_devices)) { dev_err(dev, "Invalid device ID %lu\n", id->driver_data); @@ -355,6 +559,8 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_cli= ent) if (!priv) return -ENOMEM; =20 + priv->dev =3D dev; + priv->regmap =3D devm_regmap_init_i2c(i2c_client, &cap11xx_regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); @@ -384,50 +590,15 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_c= lient) return error; =20 dev_info(dev, "CAP11XX detected, model %s, revision 0x%02x\n", - id->name, rev); - node =3D dev->of_node; - - if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) { - if (cap->no_gain) - dev_warn(dev, - "This version doesn't support sensor gain\n"); - else if (is_power_of_2(gain32) && gain32 <=3D 8) - gain =3D ilog2(gain32); - else - dev_err(dev, "Invalid sensor-gain value %d\n", gain32); - } + id->name, rev); =20 - if (id->driver_data =3D=3D CAP1106 || - id->driver_data =3D=3D CAP1126 || - id->driver_data =3D=3D CAP1188) { - if (of_property_read_bool(node, "microchip,irq-active-high")) { - error =3D regmap_update_bits(priv->regmap, - CAP11XX_REG_CONFIG2, - CAP11XX_REG_CONFIG2_ALT_POL, - 0); - if (error) - return error; - } - } + priv->model =3D cap; + priv->id =3D id->driver_data; =20 - /* Provide some useful defaults */ - for (i =3D 0; i < cap->num_channels; i++) - priv->keycodes[i] =3D KEY_A + i; - - of_property_read_u32_array(node, "linux,keycodes", - priv->keycodes, cap->num_channels); - - if (!cap->no_gain) { - error =3D regmap_update_bits(priv->regmap, - CAP11XX_REG_MAIN_CONTROL, - CAP11XX_REG_MAIN_CONTROL_GAIN_MASK, - gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT); - if (error) - return error; - } + dev_info(dev, "CAP11XX device detected, model %s, revision 0x%02x\n", + id->name, rev); =20 - /* Disable autorepeat. The Linux input system has its own handling. */ - error =3D regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0); + error =3D cap11xx_init_keys(priv); if (error) return error; =20 @@ -439,7 +610,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_cli= ent) priv->idev->id.bustype =3D BUS_I2C; priv->idev->evbit[0] =3D BIT_MASK(EV_KEY); =20 - if (of_property_read_bool(node, "autorepeat")) + if (of_property_read_bool(dev->of_node, "autorepeat")) __set_bit(EV_REP, priv->idev->evbit); =20 for (i =3D 0; i < cap->num_channels; i++) @@ -474,7 +645,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_cli= ent) if (error) return error; =20 - irq =3D irq_of_parse_and_map(node, 0); + irq =3D irq_of_parse_and_map(dev->of_node, 0); if (!irq) { dev_err(dev, "Unable to parse or map IRQ\n"); return -ENXIO; --=20 2.25.1