Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: resistive-adc-touch - add support for z1 and z2 channels

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>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/20210525054634.9134-5-o.rempel@pengutronix.de
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Oleksij Rempel and committed by
Dmitry Torokhov
fb082cd5 241a952f

+126 -14
+126 -14
drivers/input/touchscreen/resistive-adc-touch.c
··· 20 20 21 21 #define DRIVER_NAME "resistive-adc-touch" 22 22 #define GRTS_DEFAULT_PRESSURE_MIN 50000 23 + #define GRTS_DEFAULT_PRESSURE_MAX 65535 23 24 #define GRTS_MAX_POS_MASK GENMASK(11, 0) 25 + #define GRTS_MAX_CHANNELS 4 26 + 27 + enum grts_ch_type { 28 + GRTS_CH_NONE = 0, 29 + GRTS_CH_X, 30 + GRTS_CH_Y, 31 + GRTS_CH_PRESSURE, 32 + GRTS_CH_Z1, 33 + GRTS_CH_Z2, 34 + }; 24 35 25 36 /** 26 37 * struct grts_state - generic resistive touch screen information struct ··· 44 33 */ 45 34 struct grts_state { 46 35 u32 pressure_min; 36 + u32 x_plate_ohms; 47 37 bool pressure; 48 38 struct iio_channel *iio_chans; 49 39 struct iio_cb_buffer *iio_cb; 50 40 struct input_dev *input; 51 41 struct touchscreen_properties prop; 42 + u8 ch[GRTS_MAX_CHANNELS]; 52 43 }; 53 44 54 45 static int grts_cb(const void *data, void *private) 55 46 { 56 47 const u16 *touch_info = data; 57 48 struct grts_state *st = private; 58 - unsigned int x, y, press = 0x0; 49 + unsigned int x, y, press = 0, z1 = 0, z2; 50 + unsigned int Rt, i; 59 51 60 - /* channel data coming in buffer in the order below */ 61 - x = touch_info[0]; 62 - y = touch_info[1]; 63 - if (st->pressure) 64 - press = touch_info[2]; 52 + for (i = 0; i < ARRAY_SIZE(st->ch) && st->ch[i] != GRTS_CH_NONE; i++) { 53 + switch (st->ch[i]) { 54 + case GRTS_CH_X: 55 + x = touch_info[i]; 56 + break; 57 + case GRTS_CH_Y: 58 + y = touch_info[i]; 59 + break; 60 + case GRTS_CH_PRESSURE: 61 + press = touch_info[i]; 62 + break; 63 + case GRTS_CH_Z1: 64 + z1 = touch_info[i]; 65 + break; 66 + case GRTS_CH_Z2: 67 + z2 = touch_info[i]; 68 + break; 69 + } 70 + } 71 + 72 + if (z1) { 73 + Rt = z2; 74 + Rt -= z1; 75 + Rt *= st->x_plate_ohms; 76 + Rt = DIV_ROUND_CLOSEST(Rt, 16); 77 + Rt *= x; 78 + Rt /= z1; 79 + Rt = DIV_ROUND_CLOSEST(Rt, 256); 80 + /* 81 + * On increased pressure the resistance (Rt) is decreasing 82 + * so, convert values to make it looks as real pressure. 83 + */ 84 + if (Rt < GRTS_DEFAULT_PRESSURE_MAX) 85 + press = GRTS_DEFAULT_PRESSURE_MAX - Rt; 86 + else 87 + press = 0; 88 + } 65 89 66 90 if ((!x && !y) || (st->pressure && (press < st->pressure_min))) { 67 91 /* report end of touch */ ··· 140 94 iio_channel_release_all_cb(data); 141 95 } 142 96 97 + static int grts_get_properties(struct grts_state *st, struct device *dev) 98 + { 99 + int idx, error; 100 + 101 + idx = device_property_match_string(dev, "io-channel-names", "x"); 102 + if (idx < 0) 103 + return idx; 104 + 105 + if (idx >= ARRAY_SIZE(st->ch)) 106 + return -EOVERFLOW; 107 + 108 + st->ch[idx] = GRTS_CH_X; 109 + 110 + idx = device_property_match_string(dev, "io-channel-names", "y"); 111 + if (idx < 0) 112 + return idx; 113 + 114 + if (idx >= ARRAY_SIZE(st->ch)) 115 + return -EOVERFLOW; 116 + 117 + st->ch[idx] = GRTS_CH_Y; 118 + 119 + /* pressure is optional */ 120 + idx = device_property_match_string(dev, "io-channel-names", "pressure"); 121 + if (idx >= 0) { 122 + if (idx >= ARRAY_SIZE(st->ch)) 123 + return -EOVERFLOW; 124 + 125 + st->ch[idx] = GRTS_CH_PRESSURE; 126 + st->pressure = true; 127 + 128 + return 0; 129 + } 130 + 131 + /* if no pressure is defined, try optional z1 + z2 */ 132 + idx = device_property_match_string(dev, "io-channel-names", "z1"); 133 + if (idx < 0) 134 + return 0; 135 + 136 + if (idx >= ARRAY_SIZE(st->ch)) 137 + return -EOVERFLOW; 138 + 139 + st->ch[idx] = GRTS_CH_Z1; 140 + 141 + /* if z1 is provided z2 is not optional */ 142 + idx = device_property_match_string(dev, "io-channel-names", "z2"); 143 + if (idx < 0) 144 + return idx; 145 + 146 + if (idx >= ARRAY_SIZE(st->ch)) 147 + return -EOVERFLOW; 148 + 149 + st->ch[idx] = GRTS_CH_Z2; 150 + st->pressure = true; 151 + 152 + error = device_property_read_u32(dev, 153 + "touchscreen-x-plate-ohms", 154 + &st->x_plate_ohms); 155 + if (error) { 156 + dev_err(dev, "can't get touchscreen-x-plate-ohms property\n"); 157 + return error; 158 + } 159 + 160 + return 0; 161 + } 162 + 143 163 static int grts_probe(struct platform_device *pdev) 144 164 { 145 165 struct grts_state *st; 146 166 struct input_dev *input; 147 167 struct device *dev = &pdev->dev; 148 - struct iio_channel *chan; 149 168 int error; 150 169 151 170 st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL); ··· 226 115 return error; 227 116 } 228 117 229 - chan = &st->iio_chans[0]; 230 - st->pressure = false; 231 - while (chan && chan->indio_dev) { 232 - if (!strcmp(chan->channel->datasheet_name, "pressure")) 233 - st->pressure = true; 234 - chan++; 118 + if (!device_property_present(dev, "io-channel-names")) 119 + return -ENODEV; 120 + 121 + error = grts_get_properties(st, dev); 122 + if (error) { 123 + dev_err(dev, "Failed to parse properties\n"); 124 + return error; 235 125 } 236 126 237 127 if (st->pressure) { ··· 260 148 input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0); 261 149 if (st->pressure) 262 150 input_set_abs_params(input, ABS_PRESSURE, st->pressure_min, 263 - 0xffff, 0, 0); 151 + GRTS_DEFAULT_PRESSURE_MAX, 0, 0); 264 152 265 153 input_set_capability(input, EV_KEY, BTN_TOUCH); 266 154