add z1 and z2 channels support for resistive-adc-touch driver

Started by Oleksij Rempel on May 19, 2021 · 10 messages from 2 authors · Last reply May 21, 2021

Series

5 patches, 4 files

+223 −47

Subsystems (4)

Show 1 more

Maintainers (6)

Show 2 more
STALE2003d SUPERSEDED

Status: Superseded by v6 (posted 2021-05-25). [go to v6]

Revision v4 (5 revisions archived).

Revisions (5)
  1. v2
  2. v3 [diff against previous]
  3. v4 current [diff against previous]
  4. v5 [diff against previous]
  5. v6 [diff against previous]

open the first message on its own page

  1. [PATCH v4 5/5] Input: resistive-adc-touch: add support for z1 and z2 channels
    Revisions and related patches
    Revisions (3)
    1. v3
    2. v4 current [diff against previous]
    3. v5 [diff against previous]
  2. [PATCH v4 4/5] dt-bindings: touchscreen: resistive-adc-touch: add support for z1 and z2 channels
    Revisions and related patches
    Revisions (5)
    1. v2
    2. v3 [diff against previous]
    3. v4 current [diff against previous]
    4. v5 [diff against previous]
    5. v6 [diff against previous]
  3. [PATCH v4 3/5] dt-bindings: touchscreen: add touchscreen-x/y-plate-ohms property
    Revisions and related patches
    Revisions (5)
    1. v2
    2. v3 [diff against previous]
    3. v4 current [diff against previous]
    4. v5 [diff against previous]
    5. v6 [diff against previous]
  4. [PATCH v4 1/5] dt-bindings: touchscreen: validate nodename
    Revisions and related patches
    Revisions (5)
    1. v2
    2. v3 [diff against previous]
    3. v4 current [diff against previous]
    4. v5 [diff against previous]
    5. v6 [diff against previous]
  5. [PATCH v4 2/5] dt-bindings: touchscreen: Convert resistive-adc-touch binding to json schema
    Revisions and related patches
    Revisions (5)
    1. v2
    2. v3 [diff against previous]
    3. v4 current [diff against previous]
    4. v5 [diff against previous]
    5. v6 [diff against previous]
Message details and related content
changes v4:
- resistive-adc-touch: remove unused variable

changes v3:
- yaml: fix validation for channel names
- yaml: add nodename validation

changes v2:
- add yaml conversion patch to this series
- reword commit message for the last patch
- fix possible overflow on the buffer dispatcher

Oleksij Rempel (5):
  dt-bindings: touchscreen: validate nodename
  dt-bindings: touchscreen: Convert resistive-adc-touch binding to json
    schema
  dt-bindings: touchscreen: add touchscreen-x/y-plate-ohms property
  dt-bindings: touchscreen: resistive-adc-touch: add support for z1 and
    z2 channels
  Input: resistive-adc-touch: add support for z1 and z2 channels

 .../input/touchscreen/resistive-adc-touch.txt |  33 ----
 .../touchscreen/resistive-adc-touch.yaml      |  86 +++++++++++
 .../input/touchscreen/touchscreen.yaml        |   9 ++
 .../input/touchscreen/resistive-adc-touch.c   | 142 ++++++++++++++++--
 4 files changed, 223 insertions(+), 47 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml

-- 
2.29.2

[PATCH v4 5/5] Input: resistive-adc-touch: add support for z1 and z2 channels

Message details and related content
This patch adds support for the z1 and z2 channels. These are used to
calculate the applied pressure. As there is no common order of the
individual channels of a resistive touch ADC, support for
io-channel-names is added (although the DT bindings stated the
driver already supports these).

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../input/touchscreen/resistive-adc-touch.c   | 142 ++++++++++++++++--
 1 file changed, 128 insertions(+), 14 deletions(-)
diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c
index e50af30183f4..fa90005b7bc9 100644
--- a/drivers/input/touchscreen/resistive-adc-touch.c
+++ b/drivers/input/touchscreen/resistive-adc-touch.c
@@ -20,7 +20,18 @@
 
 #define DRIVER_NAME					"resistive-adc-touch"
 #define GRTS_DEFAULT_PRESSURE_MIN			50000
+#define GRTS_DEFAULT_PRESSURE_MAX			65535
 #define GRTS_MAX_POS_MASK				GENMASK(11, 0)
+#define GRTS_MAX_CHANNELS				4
+
+enum grts_ch_type {
+	GRTS_CH_NONE = 0,
+	GRTS_CH_X,
+	GRTS_CH_Y,
+	GRTS_CH_PRESSURE,
+	GRTS_CH_Z1,
+	GRTS_CH_Z2,
+};
 
 /**
  * struct grts_state - generic resistive touch screen information struct
@@ -33,24 +44,61 @@
  */
 struct grts_state {
 	u32				pressure_min;
+	u32				x_plate_ohms;
 	bool				pressure;
 	struct iio_channel		*iio_chans;
 	struct iio_cb_buffer		*iio_cb;
 	struct input_dev		*input;
 	struct touchscreen_properties	prop;
+	u8				ch[GRTS_MAX_CHANNELS];
 };
 
 static int grts_cb(const void *data, void *private)
 {
 	const u16 *touch_info = data;
 	struct grts_state *st = private;
-	unsigned int x, y, press = 0x0;
+	unsigned int x, y, press = 0, z1 = 0, z2;
+	unsigned int Rt, i;
+
+	for (i = 0; i < ARRAY_SIZE(st->ch) && st->ch[i] != GRTS_CH_NONE; i++) {
+		switch (st->ch[i]) {
+		case GRTS_CH_X:
+			x = touch_info[i];
+			break;
+		case GRTS_CH_Y:
+			y = touch_info[i];
+			break;
+		case GRTS_CH_PRESSURE:
+			press = touch_info[i];
+			break;
+		case GRTS_CH_Z1:
+			z1 = touch_info[i];
+			break;
+		case GRTS_CH_Z2:
+			z2 = touch_info[i];
+			break;
+		case GRTS_CH_NONE:
+			break;
+		}
+	}
 
-	/* channel data coming in buffer in the order below */
-	x = touch_info[0];
-	y = touch_info[1];
-	if (st->pressure)
-		press = touch_info[2];
+	if (z1) {
+		Rt = z2;
+		Rt -= z1;
+		Rt *= st->x_plate_ohms;
+		Rt = DIV_ROUND_CLOSEST(Rt, 16);
+		Rt *= x;
+		Rt /= z1;
+		Rt = DIV_ROUND_CLOSEST(Rt, 256);
+		/*
+		 * On increased pressure the resistance (Rt) is decreasing
+		 * so, convert values to make it looks as real pressure.
+		 */
+		if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
+			press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
+		else
+			press = 0;
+	}
 
 	if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
 		/* report end of touch */
@@ -94,12 +142,77 @@ static void grts_disable(void *data)
 	iio_channel_release_all_cb(data);
 }
 
+static int grts_get_properties(struct grts_state *st, struct device *dev)
+{
+	int idx, error;
+
+	idx = device_property_match_string(dev, "io-channel-names", "x");
+	if (idx < 0)
+		return idx;
+
+	if (idx >= ARRAY_SIZE(st->ch))
+		return -EOVERFLOW;
+
+	st->ch[idx] = GRTS_CH_X;
+
+	idx = device_property_match_string(dev, "io-channel-names", "y");
+	if (idx < 0)
+		return idx;
+
+	if (idx >= ARRAY_SIZE(st->ch))
+		return -EOVERFLOW;
+
+	st->ch[idx] = GRTS_CH_Y;
+
+	/* pressure is optional */
+	idx = device_property_match_string(dev, "io-channel-names", "pressure");
+	if (idx >= 0) {
+		if (idx >= ARRAY_SIZE(st->ch))
+			return -EOVERFLOW;
+
+		st->ch[idx] = GRTS_CH_PRESSURE;
+		st->pressure = true;
+
+		return 0;
+	}
+
+	/* if no pressure is defined, try optional z1 + z2 */
+	idx = device_property_match_string(dev, "io-channel-names", "z1");
+	if (idx < 0)
+		return 0;
+
+	if (idx >= ARRAY_SIZE(st->ch))
+		return -EOVERFLOW;
+
+	st->ch[idx] = GRTS_CH_Z1;
+
+	/* if z1 is provided z2 is not optional */
+	idx = device_property_match_string(dev, "io-channel-names", "z2");
+	if (idx < 0)
+		return idx;
+
+	if (idx >= ARRAY_SIZE(st->ch))
+		return -EOVERFLOW;
+
+	st->ch[idx] = GRTS_CH_Z2;
+	st->pressure = true;
+
+	error = device_property_read_u32(dev,
+					 "touchscreen-x-plate-ohms",
+					 &st->x_plate_ohms);
+	if (error) {
+		dev_err(dev, "can't get touchscreen-x-plate-ohms property\n");
+		return error;
+	}
+
+	return 0;
+}
+
 static int grts_probe(struct platform_device *pdev)
 {
 	struct grts_state *st;
 	struct input_dev *input;
 	struct device *dev = &pdev->dev;
-	struct iio_channel *chan;
 	int error;
 
 	st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
@@ -115,12 +228,13 @@ static int grts_probe(struct platform_device *pdev)
 		return error;
 	}
 
-	chan = &st->iio_chans[0];
-	st->pressure = false;
-	while (chan && chan->indio_dev) {
-		if (!strcmp(chan->channel->datasheet_name, "pressure"))
-			st->pressure = true;
-		chan++;
+	if (!device_property_present(dev, "io-channel-names"))
+		return -ENODEV;
+
+	error = grts_get_properties(st, dev);
+	if (error) {
+		dev_err(dev, "Failed to parse properties\n");
+		return error;
 	}
 
 	if (st->pressure) {
@@ -148,7 +262,7 @@ static int grts_probe(struct platform_device *pdev)
 	input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
 	if (st->pressure)
 		input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
-				     0xffff, 0, 0);
+				     GRTS_DEFAULT_PRESSURE_MAX, 0, 0);
 
 	input_set_capability(input, EV_KEY, BTN_TOUCH);
 
-- 
2.29.2

[PATCH v4 4/5] dt-bindings: touchscreen: resistive-adc-touch: add support for z1 and z2 channels

Message details and related content
For pressure calculation based on plates resistance we need some additional
properties:
- z1 and z2 channels with additional measurements between plates
- actual resistance of the touchscreen. Currently we use only
  X-resistance.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../input/touchscreen/resistive-adc-touch.yaml   | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
index 38b4cbee9429..7fc22a403d48 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
@@ -27,6 +27,8 @@ properties:
       - description: x
       - description: y
       - description: pressure (optional)
+      - description: z1 (optional)
+      - description: z2 (optional)
 
   io-channel-names:
     oneOf:
@@ -37,6 +39,11 @@ properties:
           - enum: [x, y, pressure]
           - enum: [x, y, pressure]
           - enum: [x, y, pressure]
+      - items:
+          - enum: [x, y, z1, z2]
+          - enum: [x, y, z1, z2]
+          - enum: [x, y, z1, z2]
+          - enum: [x, y, z1, z2]
 
   touchscreen-size-x: true
   touchscreen-size-y: true
@@ -46,6 +53,7 @@ properties:
   touchscreen-inverted-y: true
   touchscreen-swapped-x-y: true
   touchscreen-min-pressure: true
+  touchscreen-x-plate-ohms: true
 
 additionalProperties: false
 
@@ -68,3 +76,11 @@ examples:
       io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
       io-channel-names = "y", "pressure", "x";
     };
+  - |
+    touchscreen {
+      compatible = "resistive-adc-touch";
+      touchscreen-min-pressure = <50000>;
+      io-channels = <&adc 1>, <&adc 2>, <&adc 3>, <&adc 4>;
+      io-channel-names = "x", "z1", "z2", "y";
+      touchscreen-x-plate-ohms = <800>;
+    };
-- 
2.29.2

[PATCH v4 3/5] dt-bindings: touchscreen: add touchscreen-x/y-plate-ohms property

Message details and related content
Te calculate the pressure on a restrictive touchscreen we need need to
know resistance at least of X plate. Some calculations need to use both
X and Y values.
So, add generic properties which can be used by all drivers

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../devicetree/bindings/input/touchscreen/touchscreen.yaml  | 6 ++++++
 1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
index 057e1063759c..2d7b039ce47f 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
@@ -77,6 +77,12 @@ properties:
   touchscreen-y-mm:
     description: vertical length in mm of the touchscreen
 
+  touchscreen-x-plate-ohms:
+    description: Resistance of the X-plate in Ohms
+
+  touchscreen-y-plate-ohms:
+    description: Resistance of the Y-plate in Ohms
+
 dependencies:
   touchscreen-size-x: [ touchscreen-size-y ]
   touchscreen-size-y: [ touchscreen-size-x ]
-- 
2.29.2

[PATCH v4 1/5] dt-bindings: touchscreen: validate nodename

Message details and related content
Validate touchscreen nodes. Make sure it is named touchscreen*.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../devicetree/bindings/input/touchscreen/touchscreen.yaml     | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
index 046ace461cc9..057e1063759c 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
@@ -10,6 +10,9 @@ maintainers:
   - Dmitry Torokhov <dmitry.torokhov@gmail.com>
 
 properties:
+  $nodename:
+    pattern: "^touchscreen(@.*)?$"
+
   touchscreen-min-x:
     description: minimum x coordinate reported
     $ref: /schemas/types.yaml#/definitions/uint32
-- 
2.29.2

[PATCH v4 2/5] dt-bindings: touchscreen: Convert resistive-adc-touch binding to json schema

Message details and related content
Convert the resistive-adc-touch binding to DT schema format using json-schema.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../input/touchscreen/resistive-adc-touch.txt | 33 ---------
 .../touchscreen/resistive-adc-touch.yaml      | 70 +++++++++++++++++++
 2 files changed, 70 insertions(+), 33 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
deleted file mode 100644
index af5223bb5bdd..000000000000
--- a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-Generic resistive touchscreen ADC
-
-Required properties:
-
- - compatible: must be "resistive-adc-touch"
-The device must be connected to an ADC device that provides channels for
-position measurement and optional pressure.
-Refer to
-https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
-for details
-
- - iio-channels: must have at least two channels connected to an ADC device.
-These should correspond to the channels exposed by the ADC device and should
-have the right index as the ADC device registers them. These channels
-represent the relative position on the "x" and "y" axes.
- - iio-channel-names: must have all the channels' names. Mandatory channels
-are "x" and "y".
-
-Optional properties:
- - iio-channels: The third channel named "pressure" is optional and can be
-used if the ADC device also measures pressure besides position.
-If this channel is missing, pressure will be ignored and the touchscreen
-will only report position.
- - iio-channel-names: optional channel named "pressure".
-
-Example:
-
-	resistive_touch: resistive_touch {
-		compatible = "resistive-adc-touch";
-		touchscreen-min-pressure = <50000>;
-		io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
-		io-channel-names = "x", "y", "pressure";
-	};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
new file mode 100644
index 000000000000..38b4cbee9429
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/resistive-adc-touch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic resistive touchscreen ADC
+
+maintainers:
+  - Oleksij Rempel <o.rempel@pengutronix.de>
+
+description: |
+  Generic ADC based resistive touchscreen controller
+  The device must be connected to an ADC device that provides channels for
+  position measurement and optional pressure.
+
+allOf:
+  - $ref: touchscreen.yaml#
+
+properties:
+  compatible:
+    const: resistive-adc-touch
+
+  io-channels:
+    minItems: 2
+    items:
+      - description: x
+      - description: y
+      - description: pressure (optional)
+
+  io-channel-names:
+    oneOf:
+      - items:
+          - enum: [x, y]
+          - enum: [x, y]
+      - items:
+          - enum: [x, y, pressure]
+          - enum: [x, y, pressure]
+          - enum: [x, y, pressure]
+
+  touchscreen-size-x: true
+  touchscreen-size-y: true
+  touchscreen-fuzz-x: true
+  touchscreen-fuzz-y: true
+  touchscreen-inverted-x: true
+  touchscreen-inverted-y: true
+  touchscreen-swapped-x-y: true
+  touchscreen-min-pressure: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - io-channels
+  - io-channel-names
+
+examples:
+  - |
+    touchscreen {
+      compatible = "resistive-adc-touch";
+      io-channels = <&adc 24>, <&adc 25>;
+      io-channel-names = "y", "x";
+    };
+  - |
+    touchscreen {
+      compatible = "resistive-adc-touch";
+      touchscreen-min-pressure = <50000>;
+      io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
+      io-channel-names = "y", "pressure", "x";
+    };
-- 
2.29.2

Re: [PATCH v4 1/5] dt-bindings: touchscreen: validate nodename

Message details and related content
On Wed, 19 May 2021 11:42:17 +0200, Oleksij Rempel wrote:
Validate touchscreen nodes. Make sure it is named touchscreen*.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../devicetree/bindings/input/touchscreen/touchscreen.yaml     | 3 +++
 1 file changed, 3 insertions(+)
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.example.dt.yaml: edt-ft5x06@38: $nodename:0: 'edt-ft5x06@38' does not match '^touchscreen(@.*)?$'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/input/touchscreen/goodix.example.dt.yaml: gt928@5d: $nodename:0: 'gt928@5d' does not match '^touchscreen(@.*)?$'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/input/touchscreen/goodix.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/input/iqs626a.example.dt.yaml: iqs626a@44: $nodename:0: 'iqs626a@44' does not match '^touchscreen(@.*)?$'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/input/iqs626a.yaml

See https://patchwork.ozlabs.org/patch/1480791

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.

Re: [PATCH v4 2/5] dt-bindings: touchscreen: Convert resistive-adc-touch binding to json schema

Message details and related content
On Wed, 19 May 2021 11:42:18 +0200, Oleksij Rempel wrote:
Convert the resistive-adc-touch binding to DT schema format using json-schema.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../input/touchscreen/resistive-adc-touch.txt | 33 ---------
 .../touchscreen/resistive-adc-touch.yaml      | 70 +++++++++++++++++++
 2 files changed, 70 insertions(+), 33 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.yaml
Reviewed-by: Rob Herring <robh@kernel.org>

Re: [PATCH v4 3/5] dt-bindings: touchscreen: add touchscreen-x/y-plate-ohms property

Message details and related content
On Wed, 19 May 2021 11:42:19 +0200, Oleksij Rempel wrote:
Te calculate the pressure on a restrictive touchscreen we need need to
know resistance at least of X plate. Some calculations need to use both
X and Y values.
So, add generic properties which can be used by all drivers

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../devicetree/bindings/input/touchscreen/touchscreen.yaml  | 6 ++++++
 1 file changed, 6 insertions(+)
Reviewed-by: Rob Herring <robh@kernel.org>

Re: [PATCH v4 4/5] dt-bindings: touchscreen: resistive-adc-touch: add support for z1 and z2 channels

Message details and related content
On Wed, 19 May 2021 11:42:20 +0200, Oleksij Rempel wrote:
For pressure calculation based on plates resistance we need some additional
properties:
- z1 and z2 channels with additional measurements between plates
- actual resistance of the touchscreen. Currently we use only
  X-resistance.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../input/touchscreen/resistive-adc-touch.yaml   | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
Reviewed-by: Rob Herring <robh@kernel.org>
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help