hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/input/keyboard/tm2-touchkey.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * TM2 touchkey device driver
34 *
....@@ -6,10 +7,6 @@
67 *
78 * Author: Beomho Seo <beomho.seo@samsung.com>
89 * Author: Jaechul Lee <jcsing.lee@samsung.com>
9
- *
10
- * This program is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License version 2 as
12
- * published by the Free Software Foundation.
1310 */
1411
1512 #include <linux/bitops.h>
....@@ -22,12 +19,14 @@
2219 #include <linux/leds.h>
2320 #include <linux/module.h>
2421 #include <linux/of.h>
22
+#include <linux/of_device.h>
2523 #include <linux/pm.h>
2624 #include <linux/regulator/consumer.h>
2725
2826 #define TM2_TOUCHKEY_DEV_NAME "tm2-touchkey"
29
-#define TM2_TOUCHKEY_KEYCODE_REG 0x03
30
-#define TM2_TOUCHKEY_BASE_REG 0x00
27
+
28
+#define ARIES_TOUCHKEY_CMD_LED_ON 0x1
29
+#define ARIES_TOUCHKEY_CMD_LED_OFF 0x2
3130 #define TM2_TOUCHKEY_CMD_LED_ON 0x10
3231 #define TM2_TOUCHKEY_CMD_LED_OFF 0x20
3332 #define TM2_TOUCHKEY_BIT_PRESS_EV BIT(3)
....@@ -35,9 +34,13 @@
3534 #define TM2_TOUCHKEY_LED_VOLTAGE_MIN 2500000
3635 #define TM2_TOUCHKEY_LED_VOLTAGE_MAX 3300000
3736
38
-enum {
39
- TM2_TOUCHKEY_KEY_MENU = 0x1,
40
- TM2_TOUCHKEY_KEY_BACK,
37
+struct touchkey_variant {
38
+ u8 keycode_reg;
39
+ u8 base_reg;
40
+ u8 cmd_led_on;
41
+ u8 cmd_led_off;
42
+ bool no_reg;
43
+ bool fixed_regulator;
4144 };
4245
4346 struct tm2_touchkey_data {
....@@ -46,9 +49,41 @@
4649 struct led_classdev led_dev;
4750 struct regulator *vdd;
4851 struct regulator_bulk_data regulators[2];
52
+ const struct touchkey_variant *variant;
53
+ u32 keycodes[4];
54
+ int num_keycodes;
4955 };
5056
51
-static void tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
57
+static const struct touchkey_variant tm2_touchkey_variant = {
58
+ .keycode_reg = 0x03,
59
+ .base_reg = 0x00,
60
+ .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON,
61
+ .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF,
62
+};
63
+
64
+static const struct touchkey_variant midas_touchkey_variant = {
65
+ .keycode_reg = 0x00,
66
+ .base_reg = 0x00,
67
+ .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON,
68
+ .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF,
69
+};
70
+
71
+static struct touchkey_variant aries_touchkey_variant = {
72
+ .no_reg = true,
73
+ .fixed_regulator = true,
74
+ .cmd_led_on = ARIES_TOUCHKEY_CMD_LED_ON,
75
+ .cmd_led_off = ARIES_TOUCHKEY_CMD_LED_OFF,
76
+};
77
+
78
+static const struct touchkey_variant tc360_touchkey_variant = {
79
+ .keycode_reg = 0x00,
80
+ .base_reg = 0x00,
81
+ .fixed_regulator = true,
82
+ .cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON,
83
+ .cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF,
84
+};
85
+
86
+static int tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
5287 enum led_brightness brightness)
5388 {
5489 struct tm2_touchkey_data *touchkey =
....@@ -58,15 +93,19 @@
5893
5994 if (brightness == LED_OFF) {
6095 volt = TM2_TOUCHKEY_LED_VOLTAGE_MIN;
61
- data = TM2_TOUCHKEY_CMD_LED_OFF;
96
+ data = touchkey->variant->cmd_led_off;
6297 } else {
6398 volt = TM2_TOUCHKEY_LED_VOLTAGE_MAX;
64
- data = TM2_TOUCHKEY_CMD_LED_ON;
99
+ data = touchkey->variant->cmd_led_on;
65100 }
66101
67
- regulator_set_voltage(touchkey->vdd, volt, volt);
68
- i2c_smbus_write_byte_data(touchkey->client,
69
- TM2_TOUCHKEY_BASE_REG, data);
102
+ if (!touchkey->variant->fixed_regulator)
103
+ regulator_set_voltage(touchkey->vdd, volt, volt);
104
+
105
+ return touchkey->variant->no_reg ?
106
+ i2c_smbus_write_byte(touchkey->client, data) :
107
+ i2c_smbus_write_byte_data(touchkey->client,
108
+ touchkey->variant->base_reg, data);
70109 }
71110
72111 static int tm2_touchkey_power_enable(struct tm2_touchkey_data *touchkey)
....@@ -96,49 +135,57 @@
96135 {
97136 struct tm2_touchkey_data *touchkey = devid;
98137 int data;
99
- int key;
138
+ int index;
139
+ int i;
100140
101
- data = i2c_smbus_read_byte_data(touchkey->client,
102
- TM2_TOUCHKEY_KEYCODE_REG);
141
+ if (touchkey->variant->no_reg)
142
+ data = i2c_smbus_read_byte(touchkey->client);
143
+ else
144
+ data = i2c_smbus_read_byte_data(touchkey->client,
145
+ touchkey->variant->keycode_reg);
103146 if (data < 0) {
104147 dev_err(&touchkey->client->dev,
105148 "failed to read i2c data: %d\n", data);
106149 goto out;
107150 }
108151
109
- switch (data & TM2_TOUCHKEY_BIT_KEYCODE) {
110
- case TM2_TOUCHKEY_KEY_MENU:
111
- key = KEY_PHONE;
112
- break;
113
-
114
- case TM2_TOUCHKEY_KEY_BACK:
115
- key = KEY_BACK;
116
- break;
117
-
118
- default:
152
+ index = (data & TM2_TOUCHKEY_BIT_KEYCODE) - 1;
153
+ if (index < 0 || index >= touchkey->num_keycodes) {
119154 dev_warn(&touchkey->client->dev,
120
- "unhandled keycode, data %#02x\n", data);
155
+ "invalid keycode index %d\n", index);
121156 goto out;
122157 }
123158
124159 if (data & TM2_TOUCHKEY_BIT_PRESS_EV) {
125
- input_report_key(touchkey->input_dev, KEY_PHONE, 0);
126
- input_report_key(touchkey->input_dev, KEY_BACK, 0);
160
+ for (i = 0; i < touchkey->num_keycodes; i++)
161
+ input_report_key(touchkey->input_dev,
162
+ touchkey->keycodes[i], 0);
127163 } else {
128
- input_report_key(touchkey->input_dev, key, 1);
164
+ input_report_key(touchkey->input_dev,
165
+ touchkey->keycodes[index], 1);
129166 }
130167
131168 input_sync(touchkey->input_dev);
132169
133170 out:
171
+ if (touchkey->variant->fixed_regulator &&
172
+ data & TM2_TOUCHKEY_BIT_PRESS_EV) {
173
+ /* touch turns backlight on, so make sure we're in sync */
174
+ if (touchkey->led_dev.brightness == LED_OFF)
175
+ tm2_touchkey_led_brightness_set(&touchkey->led_dev,
176
+ LED_OFF);
177
+ }
178
+
134179 return IRQ_HANDLED;
135180 }
136181
137182 static int tm2_touchkey_probe(struct i2c_client *client,
138183 const struct i2c_device_id *id)
139184 {
185
+ struct device_node *np = client->dev.of_node;
140186 struct tm2_touchkey_data *touchkey;
141187 int error;
188
+ int i;
142189
143190 if (!i2c_check_functionality(client->adapter,
144191 I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA)) {
....@@ -153,6 +200,8 @@
153200 touchkey->client = client;
154201 i2c_set_clientdata(client, touchkey);
155202
203
+ touchkey->variant = of_device_get_match_data(&client->dev);
204
+
156205 touchkey->regulators[0].supply = "vcc";
157206 touchkey->regulators[1].supply = "vdd";
158207 error = devm_regulator_bulk_get(&client->dev,
....@@ -165,6 +214,16 @@
165214
166215 /* Save VDD for easy access */
167216 touchkey->vdd = touchkey->regulators[1].consumer;
217
+
218
+ touchkey->num_keycodes = of_property_read_variable_u32_array(np,
219
+ "linux,keycodes", touchkey->keycodes, 0,
220
+ ARRAY_SIZE(touchkey->keycodes));
221
+ if (touchkey->num_keycodes <= 0) {
222
+ /* default keycodes */
223
+ touchkey->keycodes[0] = KEY_PHONE;
224
+ touchkey->keycodes[1] = KEY_BACK;
225
+ touchkey->num_keycodes = 2;
226
+ }
168227
169228 error = tm2_touchkey_power_enable(touchkey);
170229 if (error) {
....@@ -190,8 +249,9 @@
190249 touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME;
191250 touchkey->input_dev->id.bustype = BUS_I2C;
192251
193
- input_set_capability(touchkey->input_dev, EV_KEY, KEY_PHONE);
194
- input_set_capability(touchkey->input_dev, EV_KEY, KEY_BACK);
252
+ for (i = 0; i < touchkey->num_keycodes; i++)
253
+ input_set_capability(touchkey->input_dev, EV_KEY,
254
+ touchkey->keycodes[i]);
195255
196256 error = input_register_device(touchkey->input_dev);
197257 if (error) {
....@@ -212,9 +272,10 @@
212272
213273 /* led device */
214274 touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
215
- touchkey->led_dev.brightness = LED_FULL;
275
+ touchkey->led_dev.brightness = LED_ON;
216276 touchkey->led_dev.max_brightness = LED_ON;
217
- touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set;
277
+ touchkey->led_dev.brightness_set_blocking =
278
+ tm2_touchkey_led_brightness_set;
218279
219280 error = devm_led_classdev_register(&client->dev, &touchkey->led_dev);
220281 if (error) {
....@@ -222,6 +283,9 @@
222283 "failed to register touchkey led: %d\n", error);
223284 return error;
224285 }
286
+
287
+ if (touchkey->variant->fixed_regulator)
288
+ tm2_touchkey_led_brightness_set(&touchkey->led_dev, LED_ON);
225289
226290 return 0;
227291 }
....@@ -262,7 +326,19 @@
262326 MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table);
263327
264328 static const struct of_device_id tm2_touchkey_of_match[] = {
265
- { .compatible = "cypress,tm2-touchkey", },
329
+ {
330
+ .compatible = "cypress,tm2-touchkey",
331
+ .data = &tm2_touchkey_variant,
332
+ }, {
333
+ .compatible = "cypress,midas-touchkey",
334
+ .data = &midas_touchkey_variant,
335
+ }, {
336
+ .compatible = "cypress,aries-touchkey",
337
+ .data = &aries_touchkey_variant,
338
+ }, {
339
+ .compatible = "coreriver,tc360-touchkey",
340
+ .data = &tc360_touchkey_variant,
341
+ },
266342 { },
267343 };
268344 MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match);