diff options
-rw-r--r-- | Documentation/input/rotary-encoder.txt | 9 | ||||
-rw-r--r-- | drivers/input/misc/rotary_encoder.c | 61 | ||||
-rw-r--r-- | include/linux/rotary_encoder.h | 2 |
3 files changed, 51 insertions, 21 deletions
diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt index 435102a26d96..3a6aec40c0b0 100644 --- a/Documentation/input/rotary-encoder.txt +++ b/Documentation/input/rotary-encoder.txt | |||
@@ -67,7 +67,12 @@ data with it. | |||
67 | struct rotary_encoder_platform_data is declared in | 67 | struct rotary_encoder_platform_data is declared in |
68 | include/linux/rotary-encoder.h and needs to be filled with the number of | 68 | include/linux/rotary-encoder.h and needs to be filled with the number of |
69 | steps the encoder has and can carry information about externally inverted | 69 | steps the encoder has and can carry information about externally inverted |
70 | signals (because of used invertig buffer or other reasons). | 70 | signals (because of an inverting buffer or other reasons). The encoder |
71 | can be set up to deliver input information as either an absolute or relative | ||
72 | axes. For relative axes the input event returns +/-1 for each step. For | ||
73 | absolute axes the position of the encoder can either roll over between zero | ||
74 | and the number of steps or will clamp at the maximum and zero depending on | ||
75 | the configuration. | ||
71 | 76 | ||
72 | Because GPIO to IRQ mapping is platform specific, this information must | 77 | Because GPIO to IRQ mapping is platform specific, this information must |
73 | be given in seperately to the driver. See the example below. | 78 | be given in seperately to the driver. See the example below. |
@@ -85,6 +90,8 @@ be given in seperately to the driver. See the example below. | |||
85 | static struct rotary_encoder_platform_data my_rotary_encoder_info = { | 90 | static struct rotary_encoder_platform_data my_rotary_encoder_info = { |
86 | .steps = 24, | 91 | .steps = 24, |
87 | .axis = ABS_X, | 92 | .axis = ABS_X, |
93 | .relative_axis = false, | ||
94 | .rollover = false, | ||
88 | .gpio_a = GPIO_ROTARY_A, | 95 | .gpio_a = GPIO_ROTARY_A, |
89 | .gpio_b = GPIO_ROTARY_B, | 96 | .gpio_b = GPIO_ROTARY_B, |
90 | .inverted_a = 0, | 97 | .inverted_a = 0, |
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 5bb3ab51b8c6..c806fbf1e174 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -26,13 +26,17 @@ | |||
26 | #define DRV_NAME "rotary-encoder" | 26 | #define DRV_NAME "rotary-encoder" |
27 | 27 | ||
28 | struct rotary_encoder { | 28 | struct rotary_encoder { |
29 | unsigned int irq_a; | ||
30 | unsigned int irq_b; | ||
31 | unsigned int pos; | ||
32 | unsigned int armed; | ||
33 | unsigned int dir; | ||
34 | struct input_dev *input; | 29 | struct input_dev *input; |
35 | struct rotary_encoder_platform_data *pdata; | 30 | struct rotary_encoder_platform_data *pdata; |
31 | |||
32 | unsigned int axis; | ||
33 | unsigned int pos; | ||
34 | |||
35 | unsigned int irq_a; | ||
36 | unsigned int irq_b; | ||
37 | |||
38 | bool armed; | ||
39 | unsigned char dir; /* 0 - clockwise, 1 - CCW */ | ||
36 | }; | 40 | }; |
37 | 41 | ||
38 | static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | 42 | static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) |
@@ -53,21 +57,32 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | |||
53 | if (!encoder->armed) | 57 | if (!encoder->armed) |
54 | break; | 58 | break; |
55 | 59 | ||
56 | if (encoder->dir) { | 60 | if (pdata->relative_axis) { |
57 | /* turning counter-clockwise */ | 61 | input_report_rel(encoder->input, pdata->axis, |
58 | encoder->pos += pdata->steps; | 62 | encoder->dir ? -1 : 1); |
59 | encoder->pos--; | ||
60 | encoder->pos %= pdata->steps; | ||
61 | } else { | 63 | } else { |
62 | /* turning clockwise */ | 64 | unsigned int pos = encoder->pos; |
63 | encoder->pos++; | 65 | |
64 | encoder->pos %= pdata->steps; | 66 | if (encoder->dir) { |
67 | /* turning counter-clockwise */ | ||
68 | if (pdata->rollover) | ||
69 | pos += pdata->steps; | ||
70 | if (pos) | ||
71 | pos--; | ||
72 | } else { | ||
73 | /* turning clockwise */ | ||
74 | if (pdata->rollover || pos < pdata->steps) | ||
75 | pos++; | ||
76 | } | ||
77 | if (pdata->rollover) | ||
78 | pos %= pdata->steps; | ||
79 | encoder->pos = pos; | ||
80 | input_report_abs(encoder->input, pdata->axis, | ||
81 | encoder->pos); | ||
65 | } | 82 | } |
66 | |||
67 | input_report_abs(encoder->input, pdata->axis, encoder->pos); | ||
68 | input_sync(encoder->input); | 83 | input_sync(encoder->input); |
69 | 84 | ||
70 | encoder->armed = 0; | 85 | encoder->armed = false; |
71 | break; | 86 | break; |
72 | 87 | ||
73 | case 0x1: | 88 | case 0x1: |
@@ -77,7 +92,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | |||
77 | break; | 92 | break; |
78 | 93 | ||
79 | case 0x3: | 94 | case 0x3: |
80 | encoder->armed = 1; | 95 | encoder->armed = true; |
81 | break; | 96 | break; |
82 | } | 97 | } |
83 | 98 | ||
@@ -113,9 +128,15 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
113 | input->name = pdev->name; | 128 | input->name = pdev->name; |
114 | input->id.bustype = BUS_HOST; | 129 | input->id.bustype = BUS_HOST; |
115 | input->dev.parent = &pdev->dev; | 130 | input->dev.parent = &pdev->dev; |
116 | input->evbit[0] = BIT_MASK(EV_ABS); | 131 | |
117 | input_set_abs_params(encoder->input, | 132 | if (pdata->relative_axis) { |
118 | pdata->axis, 0, pdata->steps, 0, 1); | 133 | input->evbit[0] = BIT_MASK(EV_REL); |
134 | input->relbit[0] = BIT_MASK(pdata->axis); | ||
135 | } else { | ||
136 | input->evbit[0] = BIT_MASK(EV_ABS); | ||
137 | input_set_abs_params(encoder->input, | ||
138 | pdata->axis, 0, pdata->steps, 0, 1); | ||
139 | } | ||
119 | 140 | ||
120 | err = input_register_device(input); | 141 | err = input_register_device(input); |
121 | if (err) { | 142 | if (err) { |
diff --git a/include/linux/rotary_encoder.h b/include/linux/rotary_encoder.h index 12d63a30c347..215278b8df2a 100644 --- a/include/linux/rotary_encoder.h +++ b/include/linux/rotary_encoder.h | |||
@@ -8,6 +8,8 @@ struct rotary_encoder_platform_data { | |||
8 | unsigned int gpio_b; | 8 | unsigned int gpio_b; |
9 | unsigned int inverted_a; | 9 | unsigned int inverted_a; |
10 | unsigned int inverted_b; | 10 | unsigned int inverted_b; |
11 | bool relative_axis; | ||
12 | bool rollover; | ||
11 | }; | 13 | }; |
12 | 14 | ||
13 | #endif /* __ROTARY_ENCODER_H__ */ | 15 | #endif /* __ROTARY_ENCODER_H__ */ |