1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Linux driver for Uniwill notebooks.
4 *
5 * Special thanks go to Pőcze Barnabás, Christoffer Sandberg and Werner Sembach
6 * for supporting the development of this driver either through prior work or
7 * by answering questions regarding the underlying ACPI and WMI interfaces.
8 *
9 * Copyright (C) 2025 Armin Wolf <W_Armin@gmx.de>
10 */
11
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
14 #include <linux/acpi.h>
15 #include <linux/array_size.h>
16 #include <linux/bits.h>
17 #include <linux/bitfield.h>
18 #include <linux/cleanup.h>
19 #include <linux/debugfs.h>
20 #include <linux/delay.h>
21 #include <linux/device.h>
22 #include <linux/device/driver.h>
23 #include <linux/dmi.h>
24 #include <linux/errno.h>
25 #include <linux/fixp-arith.h>
26 #include <linux/hwmon.h>
27 #include <linux/hwmon-sysfs.h>
28 #include <linux/init.h>
29 #include <linux/input.h>
30 #include <linux/input/sparse-keymap.h>
31 #include <linux/kernel.h>
32 #include <linux/kstrtox.h>
33 #include <linux/leds.h>
34 #include <linux/led-class-multicolor.h>
35 #include <linux/limits.h>
36 #include <linux/list.h>
37 #include <linux/minmax.h>
38 #include <linux/module.h>
39 #include <linux/mutex.h>
40 #include <linux/notifier.h>
41 #include <linux/platform_device.h>
42 #include <linux/pm.h>
43 #include <linux/printk.h>
44 #include <linux/regmap.h>
45 #include <linux/string.h>
46 #include <linux/sysfs.h>
47 #include <linux/types.h>
48 #include <linux/units.h>
49
50 #include <acpi/battery.h>
51
52 #include "uniwill-wmi.h"
53
54 #define EC_ADDR_BAT_POWER_UNIT_1 0x0400
55
56 #define EC_ADDR_BAT_POWER_UNIT_2 0x0401
57
58 #define EC_ADDR_BAT_DESIGN_CAPACITY_1 0x0402
59
60 #define EC_ADDR_BAT_DESIGN_CAPACITY_2 0x0403
61
62 #define EC_ADDR_BAT_FULL_CAPACITY_1 0x0404
63
64 #define EC_ADDR_BAT_FULL_CAPACITY_2 0x0405
65
66 #define EC_ADDR_BAT_DESIGN_VOLTAGE_1 0x0408
67
68 #define EC_ADDR_BAT_DESIGN_VOLTAGE_2 0x0409
69
70 #define EC_ADDR_BAT_STATUS_1 0x0432
71 #define BAT_DISCHARGING BIT(0)
72
73 #define EC_ADDR_BAT_STATUS_2 0x0433
74
75 #define EC_ADDR_BAT_CURRENT_1 0x0434
76
77 #define EC_ADDR_BAT_CURRENT_2 0x0435
78
79 #define EC_ADDR_BAT_REMAIN_CAPACITY_1 0x0436
80
81 #define EC_ADDR_BAT_REMAIN_CAPACITY_2 0x0437
82
83 #define EC_ADDR_BAT_VOLTAGE_1 0x0438
84
85 #define EC_ADDR_BAT_VOLTAGE_2 0x0439
86
87 #define EC_ADDR_CPU_TEMP 0x043E
88
89 #define EC_ADDR_GPU_TEMP 0x044F
90
91 #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
92
93 #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
94
95 #define EC_ADDR_SECOND_FAN_RPM_1 0x046C
96
97 #define EC_ADDR_SECOND_FAN_RPM_2 0x046D
98
99 #define EC_ADDR_DEVICE_STATUS 0x047B
100 #define WIFI_STATUS_ON BIT(7)
101 /* BIT(5) is also unset depending on the rfkill state (bluetooth?) */
102
103 #define EC_ADDR_BAT_ALERT 0x0494
104
105 #define EC_ADDR_BAT_CYCLE_COUNT_1 0x04A6
106
107 #define EC_ADDR_BAT_CYCLE_COUNT_2 0x04A7
108
109 #define EC_ADDR_PROJECT_ID 0x0740
110
111 #define EC_ADDR_AP_OEM 0x0741
112 #define ENABLE_MANUAL_CTRL BIT(0)
113 #define ITE_KBD_EFFECT_REACTIVE BIT(3)
114 #define FAN_ABNORMAL BIT(5)
115
116 #define EC_ADDR_SUPPORT_5 0x0742
117 #define FAN_TURBO_SUPPORTED BIT(4)
118 #define FAN_SUPPORT BIT(5)
119
120 #define EC_ADDR_CTGP_DB_CTRL 0x0743
121 #define CTGP_DB_GENERAL_ENABLE BIT(0)
122 #define CTGP_DB_DB_ENABLE BIT(1)
123 #define CTGP_DB_CTGP_ENABLE BIT(2)
124
125 #define EC_ADDR_CTGP_OFFSET 0x0744
126
127 #define EC_ADDR_TPP_OFFSET 0x0745
128
129 #define EC_ADDR_MAX_TGP 0x0746
130
131 #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
132 #define LIGHTBAR_APP_EXISTS BIT(0)
133 #define LIGHTBAR_POWER_SAVE BIT(1)
134 #define LIGHTBAR_S0_OFF BIT(2)
135 #define LIGHTBAR_S3_OFF BIT(3) // Breathing animation when suspended
136 #define LIGHTBAR_WELCOME BIT(7) // Rainbow animation
137
138 #define EC_ADDR_LIGHTBAR_AC_RED 0x0749
139
140 #define EC_ADDR_LIGHTBAR_AC_GREEN 0x074A
141
142 #define EC_ADDR_LIGHTBAR_AC_BLUE 0x074B
143
144 #define EC_ADDR_BIOS_OEM 0x074E
145 #define FN_LOCK_STATUS BIT(4)
146
147 #define EC_ADDR_MANUAL_FAN_CTRL 0x0751
148 #define FAN_LEVEL_MASK GENMASK(2, 0)
149 #define FAN_MODE_TURBO BIT(4)
150 #define FAN_MODE_HIGH BIT(5)
151 #define FAN_MODE_BOOST BIT(6)
152 #define FAN_MODE_USER BIT(7)
153
154 #define EC_ADDR_PWM_1 0x075B
155
156 #define EC_ADDR_PWM_2 0x075C
157
158 /* Unreliable */
159 #define EC_ADDR_SUPPORT_1 0x0765
160 #define AIRPLANE_MODE BIT(0)
161 #define GPS_SWITCH BIT(1)
162 #define OVERCLOCK BIT(2)
163 #define MACRO_KEY BIT(3)
164 #define SHORTCUT_KEY BIT(4)
165 #define SUPER_KEY_LOCK BIT(5)
166 #define LIGHTBAR BIT(6)
167 #define FAN_BOOST BIT(7)
168
169 #define EC_ADDR_SUPPORT_2 0x0766
170 #define SILENT_MODE BIT(0)
171 #define USB_CHARGING BIT(1)
172 #define RGB_KEYBOARD BIT(2)
173 #define CHINA_MODE BIT(5)
174 #define MY_BATTERY BIT(6)
175
176 #define EC_ADDR_TRIGGER 0x0767
177 #define TRIGGER_SUPER_KEY_LOCK BIT(0)
178 #define TRIGGER_LIGHTBAR BIT(1)
179 #define TRIGGER_FAN_BOOST BIT(2)
180 #define TRIGGER_SILENT_MODE BIT(3)
181 #define TRIGGER_USB_CHARGING BIT(4)
182 #define RGB_APPLY_COLOR BIT(5)
183 #define RGB_LOGO_EFFECT BIT(6)
184 #define RGB_RAINBOW_EFFECT BIT(7)
185
186 #define EC_ADDR_SWITCH_STATUS 0x0768
187 #define SUPER_KEY_LOCK_STATUS BIT(0)
188 #define LIGHTBAR_STATUS BIT(1)
189 #define FAN_BOOST_STATUS BIT(2)
190 #define MACRO_KEY_STATUS BIT(3)
191 #define MY_BAT_POWER_BAT_STATUS BIT(4)
192
193 #define EC_ADDR_RGB_RED 0x0769
194
195 #define EC_ADDR_RGB_GREEN 0x076A
196
197 #define EC_ADDR_RGB_BLUE 0x076B
198
199 #define EC_ADDR_ROMID_START 0x0770
200 #define ROMID_LENGTH 14
201
202 #define EC_ADDR_ROMID_EXTRA_1 0x077E
203
204 #define EC_ADDR_ROMID_EXTRA_2 0x077F
205
206 #define EC_ADDR_BIOS_OEM_2 0x0782
207 #define FAN_V2_NEW BIT(0)
208 #define FAN_QKEY BIT(1)
209 #define FAN_TABLE_OFFICE_MODE BIT(2)
210 #define FAN_V3 BIT(3)
211 #define DEFAULT_MODE BIT(4)
212
213 #define EC_ADDR_PL1_SETTING 0x0783
214
215 #define EC_ADDR_PL2_SETTING 0x0784
216
217 #define EC_ADDR_PL4_SETTING 0x0785
218
219 #define EC_ADDR_FAN_DEFAULT 0x0786
220 #define FAN_CURVE_LENGTH 5
221
222 #define EC_ADDR_KBD_STATUS 0x078C
223 #define KBD_WHITE_ONLY BIT(0) // ~single color
224 #define KBD_SINGLE_COLOR_OFF BIT(1)
225 #define KBD_TURBO_LEVEL_MASK GENMASK(3, 2)
226 #define KBD_APPLY BIT(4)
227 #define KBD_BRIGHTNESS GENMASK(7, 5)
228
229 #define EC_ADDR_FAN_CTRL 0x078E
230 #define FAN3P5 BIT(1)
231 #define CHARGING_PROFILE BIT(3)
232 #define UNIVERSAL_FAN_CTRL BIT(6)
233
234 #define EC_ADDR_BIOS_OEM_3 0x07A3
235 #define FAN_REDUCED_DURY_CYCLE BIT(5)
236 #define FAN_ALWAYS_ON BIT(6)
237
238 #define EC_ADDR_BIOS_BYTE 0x07A4
239 #define FN_LOCK_SWITCH BIT(3)
240
241 #define EC_ADDR_OEM_3 0x07A5
242 #define POWER_LED_MASK GENMASK(1, 0)
243 #define POWER_LED_LEFT 0x00
244 #define POWER_LED_BOTH 0x01
245 #define POWER_LED_NONE 0x02
246 #define FAN_QUIET BIT(2)
247 #define OVERBOOST BIT(4)
248 #define HIGH_POWER BIT(7)
249
250 #define EC_ADDR_OEM_4 0x07A6
251 #define OVERBOOST_DYN_TEMP_OFF BIT(1)
252 #define TOUCHPAD_TOGGLE_OFF BIT(6)
253
254 #define EC_ADDR_CHARGE_CTRL 0x07B9
255 #define CHARGE_CTRL_MASK GENMASK(6, 0)
256 #define CHARGE_CTRL_REACHED BIT(7)
257
258 #define EC_ADDR_UNIVERSAL_FAN_CTRL 0x07C5
259 #define SPLIT_TABLES BIT(7)
260
261 #define EC_ADDR_AP_OEM_6 0x07C6
262 #define ENABLE_UNIVERSAL_FAN_CTRL BIT(2)
263 #define BATTERY_CHARGE_FULL_OVER_24H BIT(3)
264 #define BATTERY_ERM_STATUS_REACHED BIT(4)
265
266 #define EC_ADDR_CHARGE_PRIO 0x07CC
267 #define CHARGING_PERFORMANCE BIT(7)
268
269 /* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */
270 #define EC_ADDR_LIGHTBAR_BAT_CTRL 0x07E2
271
272 #define EC_ADDR_LIGHTBAR_BAT_RED 0x07E3
273
274 #define EC_ADDR_LIGHTBAR_BAT_GREEN 0x07E4
275
276 #define EC_ADDR_LIGHTBAR_BAT_BLUE 0x07E5
277
278 #define EC_ADDR_CPU_TEMP_END_TABLE 0x0F00
279
280 #define EC_ADDR_CPU_TEMP_START_TABLE 0x0F10
281
282 #define EC_ADDR_CPU_FAN_SPEED_TABLE 0x0F20
283
284 #define EC_ADDR_GPU_TEMP_END_TABLE 0x0F30
285
286 #define EC_ADDR_GPU_TEMP_START_TABLE 0x0F40
287
288 #define EC_ADDR_GPU_FAN_SPEED_TABLE 0x0F50
289
290 /*
291 * Those two registers technically allow for manual fan control,
292 * but are unstable on some models and are likely not meant to
293 * be used by applications as they are only accessible when using
294 * the WMI interface.
295 */
296 #define EC_ADDR_PWM_1_WRITEABLE 0x1804
297
298 #define EC_ADDR_PWM_2_WRITEABLE 0x1809
299
300 #define DRIVER_NAME "uniwill"
301
302 /*
303 * The OEM software always sleeps up to 6 ms after reading/writing EC
304 * registers, so we emulate this behaviour for maximum compatibility.
305 */
306 #define UNIWILL_EC_DELAY_US 6000
307
308 #define PWM_MAX 200
309 #define FAN_TABLE_LENGTH 16
310
311 #define LED_CHANNELS 3
312 #define LED_MAX_BRIGHTNESS 200
313
314 #define UNIWILL_FEATURE_FN_LOCK_TOGGLE BIT(0)
315 #define UNIWILL_FEATURE_SUPER_KEY_TOGGLE BIT(1)
316 #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE BIT(2)
317 #define UNIWILL_FEATURE_LIGHTBAR BIT(3)
318 #define UNIWILL_FEATURE_BATTERY BIT(4)
319 #define UNIWILL_FEATURE_HWMON BIT(5)
320
321 struct uniwill_data {
322 struct device *dev;
323 acpi_handle handle;
324 struct regmap *regmap;
325 struct acpi_battery_hook hook;
326 unsigned int last_charge_ctrl;
327 struct mutex battery_lock; /* Protects the list of currently registered batteries */
328 unsigned int last_switch_status;
329 struct mutex super_key_lock; /* Protects the toggling of the super key lock state */
330 struct list_head batteries;
331 struct mutex led_lock; /* Protects writes to the lightbar registers */
332 struct led_classdev_mc led_mc_cdev;
333 struct mc_subled led_mc_subled_info[LED_CHANNELS];
334 struct mutex input_lock; /* Protects input sequence during notify */
335 struct input_dev *input_device;
336 struct notifier_block nb;
337 };
338
339 struct uniwill_battery_entry {
340 struct list_head head;
341 struct power_supply *battery;
342 };
343
344 static bool force;
345 module_param_unsafe(force, bool, 0);
346 MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
347
348 /* Feature bitmask since the associated registers are not reliable */
349 static unsigned int supported_features;
350
351 static const char * const uniwill_temp_labels[] = {
352 "CPU",
353 "GPU",
354 };
355
356 static const char * const uniwill_fan_labels[] = {
357 "Main",
358 "Secondary",
359 };
360
361 static const struct key_entry uniwill_keymap[] = {
362 /* Reported via keyboard controller */
363 { KE_IGNORE, UNIWILL_OSD_CAPSLOCK, { KEY_CAPSLOCK }},
364 { KE_IGNORE, UNIWILL_OSD_NUMLOCK, { KEY_NUMLOCK }},
365
366 /* Reported when the user locks/unlocks the super key */
367 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_ENABLE, { KEY_UNKNOWN }},
368 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_DISABLE, { KEY_UNKNOWN }},
369 /* Optional, might not be reported by all devices */
370 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_LOCK_CHANGED, { KEY_UNKNOWN }},
371
372 /* Reported in manual mode when toggling the airplane mode status */
373 { KE_KEY, UNIWILL_OSD_RFKILL, { KEY_RFKILL }},
374 { KE_IGNORE, UNIWILL_OSD_RADIOON, { KEY_UNKNOWN }},
375 { KE_IGNORE, UNIWILL_OSD_RADIOOFF, { KEY_UNKNOWN }},
376
377 /* Reported when user wants to cycle the platform profile */
378 { KE_KEY, UNIWILL_OSD_PERFORMANCE_MODE_TOGGLE, { KEY_F14 }},
379
380 /* Reported when the user wants to adjust the brightness of the keyboard */
381 { KE_KEY, UNIWILL_OSD_KBDILLUMDOWN, { KEY_KBDILLUMDOWN }},
382 { KE_KEY, UNIWILL_OSD_KBDILLUMUP, { KEY_KBDILLUMUP }},
383
384 /* Reported when the user wants to toggle the microphone mute status */
385 { KE_KEY, UNIWILL_OSD_MIC_MUTE, { KEY_MICMUTE }},
386
387 /* Reported when the user wants to toggle the mute status */
388 { KE_IGNORE, UNIWILL_OSD_MUTE, { KEY_MUTE }},
389
390 /* Reported when the user locks/unlocks the Fn key */
391 { KE_IGNORE, UNIWILL_OSD_FN_LOCK, { KEY_FN_ESC }},
392
393 /* Reported when the user wants to toggle the brightness of the keyboard */
394 { KE_KEY, UNIWILL_OSD_KBDILLUMTOGGLE, { KEY_KBDILLUMTOGGLE }},
395 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL0, { KEY_KBDILLUMTOGGLE }},
396 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL1, { KEY_KBDILLUMTOGGLE }},
397 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL2, { KEY_KBDILLUMTOGGLE }},
398 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL3, { KEY_KBDILLUMTOGGLE }},
399 { KE_KEY, UNIWILL_OSD_KB_LED_LEVEL4, { KEY_KBDILLUMTOGGLE }},
400
401 /* FIXME: find out the exact meaning of those events */
402 { KE_IGNORE, UNIWILL_OSD_BAT_CHARGE_FULL_24_H, { KEY_UNKNOWN }},
403 { KE_IGNORE, UNIWILL_OSD_BAT_ERM_UPDATE, { KEY_UNKNOWN }},
404
405 /* Reported when the user wants to toggle the benchmark mode status */
406 { KE_IGNORE, UNIWILL_OSD_BENCHMARK_MODE_TOGGLE, { KEY_UNKNOWN }},
407
408 /* Reported when the user wants to toggle the webcam */
409 { KE_IGNORE, UNIWILL_OSD_WEBCAM_TOGGLE, { KEY_UNKNOWN }},
410
411 { KE_END }
412 };
413
uniwill_ec_reg_write(void * context,unsigned int reg,unsigned int val)414 static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
415 {
416 union acpi_object params[2] = {
417 {
418 .integer = {
419 .type = ACPI_TYPE_INTEGER,
420 .value = reg,
421 },
422 },
423 {
424 .integer = {
425 .type = ACPI_TYPE_INTEGER,
426 .value = val,
427 },
428 },
429 };
430 struct uniwill_data *data = context;
431 struct acpi_object_list input = {
432 .count = ARRAY_SIZE(params),
433 .pointer = params,
434 };
435 acpi_status status;
436
437 status = acpi_evaluate_object(data->handle, "ECRW", &input, NULL);
438 if (ACPI_FAILURE(status))
439 return -EIO;
440
441 usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2);
442
443 return 0;
444 }
445
uniwill_ec_reg_read(void * context,unsigned int reg,unsigned int * val)446 static int uniwill_ec_reg_read(void *context, unsigned int reg, unsigned int *val)
447 {
448 union acpi_object params[1] = {
449 {
450 .integer = {
451 .type = ACPI_TYPE_INTEGER,
452 .value = reg,
453 },
454 },
455 };
456 struct uniwill_data *data = context;
457 struct acpi_object_list input = {
458 .count = ARRAY_SIZE(params),
459 .pointer = params,
460 };
461 unsigned long long output;
462 acpi_status status;
463
464 status = acpi_evaluate_integer(data->handle, "ECRR", &input, &output);
465 if (ACPI_FAILURE(status))
466 return -EIO;
467
468 if (output > U8_MAX)
469 return -ENXIO;
470
471 usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2);
472
473 *val = output;
474
475 return 0;
476 }
477
478 static const struct regmap_bus uniwill_ec_bus = {
479 .reg_write = uniwill_ec_reg_write,
480 .reg_read = uniwill_ec_reg_read,
481 .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
482 .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
483 };
484
uniwill_writeable_reg(struct device * dev,unsigned int reg)485 static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
486 {
487 switch (reg) {
488 case EC_ADDR_AP_OEM:
489 case EC_ADDR_LIGHTBAR_AC_CTRL:
490 case EC_ADDR_LIGHTBAR_AC_RED:
491 case EC_ADDR_LIGHTBAR_AC_GREEN:
492 case EC_ADDR_LIGHTBAR_AC_BLUE:
493 case EC_ADDR_BIOS_OEM:
494 case EC_ADDR_TRIGGER:
495 case EC_ADDR_OEM_4:
496 case EC_ADDR_CHARGE_CTRL:
497 case EC_ADDR_LIGHTBAR_BAT_CTRL:
498 case EC_ADDR_LIGHTBAR_BAT_RED:
499 case EC_ADDR_LIGHTBAR_BAT_GREEN:
500 case EC_ADDR_LIGHTBAR_BAT_BLUE:
501 return true;
502 default:
503 return false;
504 }
505 }
506
uniwill_readable_reg(struct device * dev,unsigned int reg)507 static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
508 {
509 switch (reg) {
510 case EC_ADDR_CPU_TEMP:
511 case EC_ADDR_GPU_TEMP:
512 case EC_ADDR_MAIN_FAN_RPM_1:
513 case EC_ADDR_MAIN_FAN_RPM_2:
514 case EC_ADDR_SECOND_FAN_RPM_1:
515 case EC_ADDR_SECOND_FAN_RPM_2:
516 case EC_ADDR_BAT_ALERT:
517 case EC_ADDR_PROJECT_ID:
518 case EC_ADDR_AP_OEM:
519 case EC_ADDR_LIGHTBAR_AC_CTRL:
520 case EC_ADDR_LIGHTBAR_AC_RED:
521 case EC_ADDR_LIGHTBAR_AC_GREEN:
522 case EC_ADDR_LIGHTBAR_AC_BLUE:
523 case EC_ADDR_BIOS_OEM:
524 case EC_ADDR_PWM_1:
525 case EC_ADDR_PWM_2:
526 case EC_ADDR_TRIGGER:
527 case EC_ADDR_SWITCH_STATUS:
528 case EC_ADDR_OEM_4:
529 case EC_ADDR_CHARGE_CTRL:
530 case EC_ADDR_LIGHTBAR_BAT_CTRL:
531 case EC_ADDR_LIGHTBAR_BAT_RED:
532 case EC_ADDR_LIGHTBAR_BAT_GREEN:
533 case EC_ADDR_LIGHTBAR_BAT_BLUE:
534 return true;
535 default:
536 return false;
537 }
538 }
539
uniwill_volatile_reg(struct device * dev,unsigned int reg)540 static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
541 {
542 switch (reg) {
543 case EC_ADDR_CPU_TEMP:
544 case EC_ADDR_GPU_TEMP:
545 case EC_ADDR_MAIN_FAN_RPM_1:
546 case EC_ADDR_MAIN_FAN_RPM_2:
547 case EC_ADDR_SECOND_FAN_RPM_1:
548 case EC_ADDR_SECOND_FAN_RPM_2:
549 case EC_ADDR_BAT_ALERT:
550 case EC_ADDR_PWM_1:
551 case EC_ADDR_PWM_2:
552 case EC_ADDR_TRIGGER:
553 case EC_ADDR_SWITCH_STATUS:
554 case EC_ADDR_CHARGE_CTRL:
555 return true;
556 default:
557 return false;
558 }
559 }
560
561 static const struct regmap_config uniwill_ec_config = {
562 .reg_bits = 16,
563 .val_bits = 8,
564 .writeable_reg = uniwill_writeable_reg,
565 .readable_reg = uniwill_readable_reg,
566 .volatile_reg = uniwill_volatile_reg,
567 .can_sleep = true,
568 .max_register = 0xFFF,
569 .cache_type = REGCACHE_MAPLE,
570 .use_single_read = true,
571 .use_single_write = true,
572 };
573
fn_lock_toggle_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)574 static ssize_t fn_lock_toggle_enable_store(struct device *dev, struct device_attribute *attr,
575 const char *buf, size_t count)
576 {
577 struct uniwill_data *data = dev_get_drvdata(dev);
578 unsigned int value;
579 bool enable;
580 int ret;
581
582 ret = kstrtobool(buf, &enable);
583 if (ret < 0)
584 return ret;
585
586 if (enable)
587 value = FN_LOCK_STATUS;
588 else
589 value = 0;
590
591 ret = regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, value);
592 if (ret < 0)
593 return ret;
594
595 return count;
596 }
597
fn_lock_toggle_enable_show(struct device * dev,struct device_attribute * attr,char * buf)598 static ssize_t fn_lock_toggle_enable_show(struct device *dev, struct device_attribute *attr,
599 char *buf)
600 {
601 struct uniwill_data *data = dev_get_drvdata(dev);
602 unsigned int value;
603 int ret;
604
605 ret = regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &value);
606 if (ret < 0)
607 return ret;
608
609 return sysfs_emit(buf, "%d\n", !!(value & FN_LOCK_STATUS));
610 }
611
612 static DEVICE_ATTR_RW(fn_lock_toggle_enable);
613
super_key_toggle_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)614 static ssize_t super_key_toggle_enable_store(struct device *dev, struct device_attribute *attr,
615 const char *buf, size_t count)
616 {
617 struct uniwill_data *data = dev_get_drvdata(dev);
618 unsigned int value;
619 bool enable;
620 int ret;
621
622 ret = kstrtobool(buf, &enable);
623 if (ret < 0)
624 return ret;
625
626 guard(mutex)(&data->super_key_lock);
627
628 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
629 if (ret < 0)
630 return ret;
631
632 /*
633 * We can only toggle the super key lock, so we return early if the setting
634 * is already in the correct state.
635 */
636 if (enable == !(value & SUPER_KEY_LOCK_STATUS))
637 return count;
638
639 ret = regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK,
640 TRIGGER_SUPER_KEY_LOCK);
641 if (ret < 0)
642 return ret;
643
644 return count;
645 }
646
super_key_toggle_enable_show(struct device * dev,struct device_attribute * attr,char * buf)647 static ssize_t super_key_toggle_enable_show(struct device *dev, struct device_attribute *attr,
648 char *buf)
649 {
650 struct uniwill_data *data = dev_get_drvdata(dev);
651 unsigned int value;
652 int ret;
653
654 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
655 if (ret < 0)
656 return ret;
657
658 return sysfs_emit(buf, "%d\n", !(value & SUPER_KEY_LOCK_STATUS));
659 }
660
661 static DEVICE_ATTR_RW(super_key_toggle_enable);
662
touchpad_toggle_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)663 static ssize_t touchpad_toggle_enable_store(struct device *dev, struct device_attribute *attr,
664 const char *buf, size_t count)
665 {
666 struct uniwill_data *data = dev_get_drvdata(dev);
667 unsigned int value;
668 bool enable;
669 int ret;
670
671 ret = kstrtobool(buf, &enable);
672 if (ret < 0)
673 return ret;
674
675 if (enable)
676 value = 0;
677 else
678 value = TOUCHPAD_TOGGLE_OFF;
679
680 ret = regmap_update_bits(data->regmap, EC_ADDR_OEM_4, TOUCHPAD_TOGGLE_OFF, value);
681 if (ret < 0)
682 return ret;
683
684 return count;
685 }
686
touchpad_toggle_enable_show(struct device * dev,struct device_attribute * attr,char * buf)687 static ssize_t touchpad_toggle_enable_show(struct device *dev, struct device_attribute *attr,
688 char *buf)
689 {
690 struct uniwill_data *data = dev_get_drvdata(dev);
691 unsigned int value;
692 int ret;
693
694 ret = regmap_read(data->regmap, EC_ADDR_OEM_4, &value);
695 if (ret < 0)
696 return ret;
697
698 return sysfs_emit(buf, "%d\n", !(value & TOUCHPAD_TOGGLE_OFF));
699 }
700
701 static DEVICE_ATTR_RW(touchpad_toggle_enable);
702
rainbow_animation_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)703 static ssize_t rainbow_animation_store(struct device *dev, struct device_attribute *attr,
704 const char *buf, size_t count)
705 {
706 struct uniwill_data *data = dev_get_drvdata(dev);
707 unsigned int value;
708 bool enable;
709 int ret;
710
711 ret = kstrtobool(buf, &enable);
712 if (ret < 0)
713 return ret;
714
715 if (enable)
716 value = LIGHTBAR_WELCOME;
717 else
718 value = 0;
719
720 guard(mutex)(&data->led_lock);
721
722 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_WELCOME, value);
723 if (ret < 0)
724 return ret;
725
726 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_WELCOME, value);
727 if (ret < 0)
728 return ret;
729
730 return count;
731 }
732
rainbow_animation_show(struct device * dev,struct device_attribute * attr,char * buf)733 static ssize_t rainbow_animation_show(struct device *dev, struct device_attribute *attr, char *buf)
734 {
735 struct uniwill_data *data = dev_get_drvdata(dev);
736 unsigned int value;
737 int ret;
738
739 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
740 if (ret < 0)
741 return ret;
742
743 return sysfs_emit(buf, "%d\n", !!(value & LIGHTBAR_WELCOME));
744 }
745
746 static DEVICE_ATTR_RW(rainbow_animation);
747
breathing_in_suspend_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)748 static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attribute *attr,
749 const char *buf, size_t count)
750 {
751 struct uniwill_data *data = dev_get_drvdata(dev);
752 unsigned int value;
753 bool enable;
754 int ret;
755
756 ret = kstrtobool(buf, &enable);
757 if (ret < 0)
758 return ret;
759
760 if (enable)
761 value = 0;
762 else
763 value = LIGHTBAR_S3_OFF;
764
765 /* We only access a single register here, so we do not need to use data->led_lock */
766 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S3_OFF, value);
767 if (ret < 0)
768 return ret;
769
770 return count;
771 }
772
breathing_in_suspend_show(struct device * dev,struct device_attribute * attr,char * buf)773 static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attribute *attr,
774 char *buf)
775 {
776 struct uniwill_data *data = dev_get_drvdata(dev);
777 unsigned int value;
778 int ret;
779
780 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
781 if (ret < 0)
782 return ret;
783
784 return sysfs_emit(buf, "%d\n", !(value & LIGHTBAR_S3_OFF));
785 }
786
787 static DEVICE_ATTR_RW(breathing_in_suspend);
788
789 static struct attribute *uniwill_attrs[] = {
790 /* Keyboard-related */
791 &dev_attr_fn_lock_toggle_enable.attr,
792 &dev_attr_super_key_toggle_enable.attr,
793 &dev_attr_touchpad_toggle_enable.attr,
794 /* Lightbar-related */
795 &dev_attr_rainbow_animation.attr,
796 &dev_attr_breathing_in_suspend.attr,
797 NULL
798 };
799
uniwill_attr_is_visible(struct kobject * kobj,struct attribute * attr,int n)800 static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
801 {
802 if (attr == &dev_attr_fn_lock_toggle_enable.attr) {
803 if (supported_features & UNIWILL_FEATURE_FN_LOCK_TOGGLE)
804 return attr->mode;
805 }
806
807 if (attr == &dev_attr_super_key_toggle_enable.attr) {
808 if (supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE)
809 return attr->mode;
810 }
811
812 if (attr == &dev_attr_touchpad_toggle_enable.attr) {
813 if (supported_features & UNIWILL_FEATURE_TOUCHPAD_TOGGLE)
814 return attr->mode;
815 }
816
817 if (attr == &dev_attr_rainbow_animation.attr ||
818 attr == &dev_attr_breathing_in_suspend.attr) {
819 if (supported_features & UNIWILL_FEATURE_LIGHTBAR)
820 return attr->mode;
821 }
822
823 return 0;
824 }
825
826 static const struct attribute_group uniwill_group = {
827 .is_visible = uniwill_attr_is_visible,
828 .attrs = uniwill_attrs,
829 };
830
831 static const struct attribute_group *uniwill_groups[] = {
832 &uniwill_group,
833 NULL
834 };
835
uniwill_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)836 static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
837 long *val)
838 {
839 struct uniwill_data *data = dev_get_drvdata(dev);
840 unsigned int value;
841 __be16 rpm;
842 int ret;
843
844 switch (type) {
845 case hwmon_temp:
846 switch (channel) {
847 case 0:
848 ret = regmap_read(data->regmap, EC_ADDR_CPU_TEMP, &value);
849 break;
850 case 1:
851 ret = regmap_read(data->regmap, EC_ADDR_GPU_TEMP, &value);
852 break;
853 default:
854 return -EOPNOTSUPP;
855 }
856
857 if (ret < 0)
858 return ret;
859
860 *val = value * MILLIDEGREE_PER_DEGREE;
861 return 0;
862 case hwmon_fan:
863 switch (channel) {
864 case 0:
865 ret = regmap_bulk_read(data->regmap, EC_ADDR_MAIN_FAN_RPM_1, &rpm,
866 sizeof(rpm));
867 break;
868 case 1:
869 ret = regmap_bulk_read(data->regmap, EC_ADDR_SECOND_FAN_RPM_1, &rpm,
870 sizeof(rpm));
871 break;
872 default:
873 return -EOPNOTSUPP;
874 }
875
876 if (ret < 0)
877 return ret;
878
879 *val = be16_to_cpu(rpm);
880 return 0;
881 case hwmon_pwm:
882 switch (channel) {
883 case 0:
884 ret = regmap_read(data->regmap, EC_ADDR_PWM_1, &value);
885 break;
886 case 1:
887 ret = regmap_read(data->regmap, EC_ADDR_PWM_2, &value);
888 break;
889 default:
890 return -EOPNOTSUPP;
891 }
892
893 if (ret < 0)
894 return ret;
895
896 *val = fixp_linear_interpolate(0, 0, PWM_MAX, U8_MAX, value);
897 return 0;
898 default:
899 return -EOPNOTSUPP;
900 }
901 }
902
uniwill_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)903 static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
904 int channel, const char **str)
905 {
906 switch (type) {
907 case hwmon_temp:
908 *str = uniwill_temp_labels[channel];
909 return 0;
910 case hwmon_fan:
911 *str = uniwill_fan_labels[channel];
912 return 0;
913 default:
914 return -EOPNOTSUPP;
915 }
916 }
917
918 static const struct hwmon_ops uniwill_ops = {
919 .visible = 0444,
920 .read = uniwill_read,
921 .read_string = uniwill_read_string,
922 };
923
924 static const struct hwmon_channel_info * const uniwill_info[] = {
925 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
926 HWMON_CHANNEL_INFO(temp,
927 HWMON_T_INPUT | HWMON_T_LABEL,
928 HWMON_T_INPUT | HWMON_T_LABEL),
929 HWMON_CHANNEL_INFO(fan,
930 HWMON_F_INPUT | HWMON_F_LABEL,
931 HWMON_F_INPUT | HWMON_F_LABEL),
932 HWMON_CHANNEL_INFO(pwm,
933 HWMON_PWM_INPUT,
934 HWMON_PWM_INPUT),
935 NULL
936 };
937
938 static const struct hwmon_chip_info uniwill_chip_info = {
939 .ops = &uniwill_ops,
940 .info = uniwill_info,
941 };
942
uniwill_hwmon_init(struct uniwill_data * data)943 static int uniwill_hwmon_init(struct uniwill_data *data)
944 {
945 struct device *hdev;
946
947 if (!(supported_features & UNIWILL_FEATURE_HWMON))
948 return 0;
949
950 hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
951 &uniwill_chip_info, NULL);
952
953 return PTR_ERR_OR_ZERO(hdev);
954 }
955
956 static const unsigned int uniwill_led_channel_to_bat_reg[LED_CHANNELS] = {
957 EC_ADDR_LIGHTBAR_BAT_RED,
958 EC_ADDR_LIGHTBAR_BAT_GREEN,
959 EC_ADDR_LIGHTBAR_BAT_BLUE,
960 };
961
962 static const unsigned int uniwill_led_channel_to_ac_reg[LED_CHANNELS] = {
963 EC_ADDR_LIGHTBAR_AC_RED,
964 EC_ADDR_LIGHTBAR_AC_GREEN,
965 EC_ADDR_LIGHTBAR_AC_BLUE,
966 };
967
uniwill_led_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)968 static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness)
969 {
970 struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev);
971 struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, led_mc_cdev);
972 unsigned int value;
973 int ret;
974
975 ret = led_mc_calc_color_components(led_mc_cdev, brightness);
976 if (ret < 0)
977 return ret;
978
979 guard(mutex)(&data->led_lock);
980
981 for (int i = 0; i < LED_CHANNELS; i++) {
982 /* Prevent the brightness values from overflowing */
983 value = min(LED_MAX_BRIGHTNESS, data->led_mc_subled_info[i].brightness);
984 ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
985 if (ret < 0)
986 return ret;
987
988 ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
989 if (ret < 0)
990 return ret;
991 }
992
993 if (brightness)
994 value = 0;
995 else
996 value = LIGHTBAR_S0_OFF;
997
998 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S0_OFF, value);
999 if (ret < 0)
1000 return ret;
1001
1002 return regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_S0_OFF, value);
1003 }
1004
1005 #define LIGHTBAR_MASK (LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME)
1006
uniwill_led_init(struct uniwill_data * data)1007 static int uniwill_led_init(struct uniwill_data *data)
1008 {
1009 struct led_init_data init_data = {
1010 .devicename = DRIVER_NAME,
1011 .default_label = "multicolor:" LED_FUNCTION_STATUS,
1012 .devname_mandatory = true,
1013 };
1014 unsigned int color_indices[3] = {
1015 LED_COLOR_ID_RED,
1016 LED_COLOR_ID_GREEN,
1017 LED_COLOR_ID_BLUE,
1018 };
1019 unsigned int value;
1020 int ret;
1021
1022 if (!(supported_features & UNIWILL_FEATURE_LIGHTBAR))
1023 return 0;
1024
1025 ret = devm_mutex_init(data->dev, &data->led_lock);
1026 if (ret < 0)
1027 return ret;
1028
1029 /*
1030 * The EC has separate lightbar settings for AC and battery mode,
1031 * so we have to ensure that both settings are the same.
1032 */
1033 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
1034 if (ret < 0)
1035 return ret;
1036
1037 value |= LIGHTBAR_APP_EXISTS;
1038 ret = regmap_write(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, value);
1039 if (ret < 0)
1040 return ret;
1041
1042 /*
1043 * The breathing animation during suspend is not supported when
1044 * running on battery power.
1045 */
1046 value |= LIGHTBAR_S3_OFF;
1047 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_MASK, value);
1048 if (ret < 0)
1049 return ret;
1050
1051 data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
1052 data->led_mc_cdev.led_cdev.max_brightness = LED_MAX_BRIGHTNESS;
1053 data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
1054 data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
1055
1056 if (value & LIGHTBAR_S0_OFF)
1057 data->led_mc_cdev.led_cdev.brightness = 0;
1058 else
1059 data->led_mc_cdev.led_cdev.brightness = LED_MAX_BRIGHTNESS;
1060
1061 for (int i = 0; i < LED_CHANNELS; i++) {
1062 data->led_mc_subled_info[i].color_index = color_indices[i];
1063
1064 ret = regmap_read(data->regmap, uniwill_led_channel_to_ac_reg[i], &value);
1065 if (ret < 0)
1066 return ret;
1067
1068 /*
1069 * Make sure that the initial intensity value is not greater than
1070 * the maximum brightness.
1071 */
1072 value = min(LED_MAX_BRIGHTNESS, value);
1073 ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
1074 if (ret < 0)
1075 return ret;
1076
1077 ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
1078 if (ret < 0)
1079 return ret;
1080
1081 data->led_mc_subled_info[i].intensity = value;
1082 data->led_mc_subled_info[i].channel = i;
1083 }
1084
1085 data->led_mc_cdev.subled_info = data->led_mc_subled_info;
1086 data->led_mc_cdev.num_colors = LED_CHANNELS;
1087
1088 return devm_led_classdev_multicolor_register_ext(data->dev, &data->led_mc_cdev,
1089 &init_data);
1090 }
1091
uniwill_get_property(struct power_supply * psy,const struct power_supply_ext * ext,void * drvdata,enum power_supply_property psp,union power_supply_propval * val)1092 static int uniwill_get_property(struct power_supply *psy, const struct power_supply_ext *ext,
1093 void *drvdata, enum power_supply_property psp,
1094 union power_supply_propval *val)
1095 {
1096 struct uniwill_data *data = drvdata;
1097 union power_supply_propval prop;
1098 unsigned int regval;
1099 int ret;
1100
1101 switch (psp) {
1102 case POWER_SUPPLY_PROP_HEALTH:
1103 ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_PRESENT, &prop);
1104 if (ret < 0)
1105 return ret;
1106
1107 if (!prop.intval) {
1108 val->intval = POWER_SUPPLY_HEALTH_NO_BATTERY;
1109 return 0;
1110 }
1111
1112 ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_STATUS, &prop);
1113 if (ret < 0)
1114 return ret;
1115
1116 if (prop.intval == POWER_SUPPLY_STATUS_UNKNOWN) {
1117 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
1118 return 0;
1119 }
1120
1121 ret = regmap_read(data->regmap, EC_ADDR_BAT_ALERT, ®val);
1122 if (ret < 0)
1123 return ret;
1124
1125 if (regval) {
1126 /* Charging issue */
1127 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
1128 return 0;
1129 }
1130
1131 val->intval = POWER_SUPPLY_HEALTH_GOOD;
1132 return 0;
1133 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
1134 ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, ®val);
1135 if (ret < 0)
1136 return ret;
1137
1138 val->intval = clamp_val(FIELD_GET(CHARGE_CTRL_MASK, regval), 0, 100);
1139 return 0;
1140 default:
1141 return -EINVAL;
1142 }
1143 }
1144
uniwill_set_property(struct power_supply * psy,const struct power_supply_ext * ext,void * drvdata,enum power_supply_property psp,const union power_supply_propval * val)1145 static int uniwill_set_property(struct power_supply *psy, const struct power_supply_ext *ext,
1146 void *drvdata, enum power_supply_property psp,
1147 const union power_supply_propval *val)
1148 {
1149 struct uniwill_data *data = drvdata;
1150
1151 switch (psp) {
1152 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
1153 if (val->intval < 1 || val->intval > 100)
1154 return -EINVAL;
1155
1156 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
1157 val->intval);
1158 default:
1159 return -EINVAL;
1160 }
1161 }
1162
uniwill_property_is_writeable(struct power_supply * psy,const struct power_supply_ext * ext,void * drvdata,enum power_supply_property psp)1163 static int uniwill_property_is_writeable(struct power_supply *psy,
1164 const struct power_supply_ext *ext, void *drvdata,
1165 enum power_supply_property psp)
1166 {
1167 if (psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD)
1168 return true;
1169
1170 return false;
1171 }
1172
1173 static const enum power_supply_property uniwill_properties[] = {
1174 POWER_SUPPLY_PROP_HEALTH,
1175 POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
1176 };
1177
1178 static const struct power_supply_ext uniwill_extension = {
1179 .name = DRIVER_NAME,
1180 .properties = uniwill_properties,
1181 .num_properties = ARRAY_SIZE(uniwill_properties),
1182 .get_property = uniwill_get_property,
1183 .set_property = uniwill_set_property,
1184 .property_is_writeable = uniwill_property_is_writeable,
1185 };
1186
uniwill_add_battery(struct power_supply * battery,struct acpi_battery_hook * hook)1187 static int uniwill_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
1188 {
1189 struct uniwill_data *data = container_of(hook, struct uniwill_data, hook);
1190 struct uniwill_battery_entry *entry;
1191 int ret;
1192
1193 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1194 if (!entry)
1195 return -ENOMEM;
1196
1197 ret = power_supply_register_extension(battery, &uniwill_extension, data->dev, data);
1198 if (ret < 0) {
1199 kfree(entry);
1200 return ret;
1201 }
1202
1203 guard(mutex)(&data->battery_lock);
1204
1205 entry->battery = battery;
1206 list_add(&entry->head, &data->batteries);
1207
1208 return 0;
1209 }
1210
uniwill_remove_battery(struct power_supply * battery,struct acpi_battery_hook * hook)1211 static int uniwill_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
1212 {
1213 struct uniwill_data *data = container_of(hook, struct uniwill_data, hook);
1214 struct uniwill_battery_entry *entry, *tmp;
1215
1216 scoped_guard(mutex, &data->battery_lock) {
1217 list_for_each_entry_safe(entry, tmp, &data->batteries, head) {
1218 if (entry->battery == battery) {
1219 list_del(&entry->head);
1220 kfree(entry);
1221 break;
1222 }
1223 }
1224 }
1225
1226 power_supply_unregister_extension(battery, &uniwill_extension);
1227
1228 return 0;
1229 }
1230
uniwill_battery_init(struct uniwill_data * data)1231 static int uniwill_battery_init(struct uniwill_data *data)
1232 {
1233 int ret;
1234
1235 if (!(supported_features & UNIWILL_FEATURE_BATTERY))
1236 return 0;
1237
1238 ret = devm_mutex_init(data->dev, &data->battery_lock);
1239 if (ret < 0)
1240 return ret;
1241
1242 INIT_LIST_HEAD(&data->batteries);
1243 data->hook.name = "Uniwill Battery Extension";
1244 data->hook.add_battery = uniwill_add_battery;
1245 data->hook.remove_battery = uniwill_remove_battery;
1246
1247 return devm_battery_hook_register(data->dev, &data->hook);
1248 }
1249
uniwill_notifier_call(struct notifier_block * nb,unsigned long action,void * dummy)1250 static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action, void *dummy)
1251 {
1252 struct uniwill_data *data = container_of(nb, struct uniwill_data, nb);
1253 struct uniwill_battery_entry *entry;
1254
1255 switch (action) {
1256 case UNIWILL_OSD_BATTERY_ALERT:
1257 mutex_lock(&data->battery_lock);
1258 list_for_each_entry(entry, &data->batteries, head) {
1259 power_supply_changed(entry->battery);
1260 }
1261 mutex_unlock(&data->battery_lock);
1262
1263 return NOTIFY_OK;
1264 case UNIWILL_OSD_DC_ADAPTER_CHANGED:
1265 /* noop for the time being, will change once charging priority
1266 * gets implemented.
1267 */
1268
1269 return NOTIFY_OK;
1270 default:
1271 mutex_lock(&data->input_lock);
1272 sparse_keymap_report_event(data->input_device, action, 1, true);
1273 mutex_unlock(&data->input_lock);
1274
1275 return NOTIFY_OK;
1276 }
1277 }
1278
uniwill_input_init(struct uniwill_data * data)1279 static int uniwill_input_init(struct uniwill_data *data)
1280 {
1281 int ret;
1282
1283 ret = devm_mutex_init(data->dev, &data->input_lock);
1284 if (ret < 0)
1285 return ret;
1286
1287 data->input_device = devm_input_allocate_device(data->dev);
1288 if (!data->input_device)
1289 return -ENOMEM;
1290
1291 ret = sparse_keymap_setup(data->input_device, uniwill_keymap, NULL);
1292 if (ret < 0)
1293 return ret;
1294
1295 data->input_device->name = "Uniwill WMI hotkeys";
1296 data->input_device->phys = "wmi/input0";
1297 data->input_device->id.bustype = BUS_HOST;
1298 ret = input_register_device(data->input_device);
1299 if (ret < 0)
1300 return ret;
1301
1302 data->nb.notifier_call = uniwill_notifier_call;
1303
1304 return devm_uniwill_wmi_register_notifier(data->dev, &data->nb);
1305 }
1306
uniwill_disable_manual_control(void * context)1307 static void uniwill_disable_manual_control(void *context)
1308 {
1309 struct uniwill_data *data = context;
1310
1311 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
1312 }
1313
uniwill_ec_init(struct uniwill_data * data)1314 static int uniwill_ec_init(struct uniwill_data *data)
1315 {
1316 unsigned int value;
1317 int ret;
1318
1319 ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
1320 if (ret < 0)
1321 return ret;
1322
1323 dev_dbg(data->dev, "Project ID: %u\n", value);
1324
1325 ret = regmap_set_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
1326 if (ret < 0)
1327 return ret;
1328
1329 return devm_add_action_or_reset(data->dev, uniwill_disable_manual_control, data);
1330 }
1331
uniwill_probe(struct platform_device * pdev)1332 static int uniwill_probe(struct platform_device *pdev)
1333 {
1334 struct uniwill_data *data;
1335 struct regmap *regmap;
1336 acpi_handle handle;
1337 int ret;
1338
1339 handle = ACPI_HANDLE(&pdev->dev);
1340 if (!handle)
1341 return -ENODEV;
1342
1343 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
1344 if (!data)
1345 return -ENOMEM;
1346
1347 data->dev = &pdev->dev;
1348 data->handle = handle;
1349 platform_set_drvdata(pdev, data);
1350
1351 regmap = devm_regmap_init(&pdev->dev, &uniwill_ec_bus, data, &uniwill_ec_config);
1352 if (IS_ERR(regmap))
1353 return PTR_ERR(regmap);
1354
1355 data->regmap = regmap;
1356 ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
1357 if (ret < 0)
1358 return ret;
1359
1360 ret = uniwill_ec_init(data);
1361 if (ret < 0)
1362 return ret;
1363
1364 ret = uniwill_battery_init(data);
1365 if (ret < 0)
1366 return ret;
1367
1368 ret = uniwill_led_init(data);
1369 if (ret < 0)
1370 return ret;
1371
1372 ret = uniwill_hwmon_init(data);
1373 if (ret < 0)
1374 return ret;
1375
1376 return uniwill_input_init(data);
1377 }
1378
uniwill_shutdown(struct platform_device * pdev)1379 static void uniwill_shutdown(struct platform_device *pdev)
1380 {
1381 struct uniwill_data *data = platform_get_drvdata(pdev);
1382
1383 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
1384 }
1385
uniwill_suspend_keyboard(struct uniwill_data * data)1386 static int uniwill_suspend_keyboard(struct uniwill_data *data)
1387 {
1388 if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
1389 return 0;
1390
1391 /*
1392 * The EC_ADDR_SWITCH_STATUS is marked as volatile, so we have to restore it
1393 * ourselves.
1394 */
1395 return regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &data->last_switch_status);
1396 }
1397
uniwill_suspend_battery(struct uniwill_data * data)1398 static int uniwill_suspend_battery(struct uniwill_data *data)
1399 {
1400 if (!(supported_features & UNIWILL_FEATURE_BATTERY))
1401 return 0;
1402
1403 /*
1404 * Save the current charge limit in order to restore it during resume.
1405 * We cannot use the regmap code for that since this register needs to
1406 * be declared as volatile due to CHARGE_CTRL_REACHED.
1407 */
1408 return regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &data->last_charge_ctrl);
1409 }
1410
uniwill_suspend(struct device * dev)1411 static int uniwill_suspend(struct device *dev)
1412 {
1413 struct uniwill_data *data = dev_get_drvdata(dev);
1414 int ret;
1415
1416 ret = uniwill_suspend_keyboard(data);
1417 if (ret < 0)
1418 return ret;
1419
1420 ret = uniwill_suspend_battery(data);
1421 if (ret < 0)
1422 return ret;
1423
1424 regcache_cache_only(data->regmap, true);
1425 regcache_mark_dirty(data->regmap);
1426
1427 return 0;
1428 }
1429
uniwill_resume_keyboard(struct uniwill_data * data)1430 static int uniwill_resume_keyboard(struct uniwill_data *data)
1431 {
1432 unsigned int value;
1433 int ret;
1434
1435 if (!(supported_features & UNIWILL_FEATURE_SUPER_KEY_TOGGLE))
1436 return 0;
1437
1438 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
1439 if (ret < 0)
1440 return ret;
1441
1442 if ((data->last_switch_status & SUPER_KEY_LOCK_STATUS) == (value & SUPER_KEY_LOCK_STATUS))
1443 return 0;
1444
1445 return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK,
1446 TRIGGER_SUPER_KEY_LOCK);
1447 }
1448
uniwill_resume_battery(struct uniwill_data * data)1449 static int uniwill_resume_battery(struct uniwill_data *data)
1450 {
1451 if (!(supported_features & UNIWILL_FEATURE_BATTERY))
1452 return 0;
1453
1454 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
1455 data->last_charge_ctrl);
1456 }
1457
uniwill_resume(struct device * dev)1458 static int uniwill_resume(struct device *dev)
1459 {
1460 struct uniwill_data *data = dev_get_drvdata(dev);
1461 int ret;
1462
1463 regcache_cache_only(data->regmap, false);
1464
1465 ret = regcache_sync(data->regmap);
1466 if (ret < 0)
1467 return ret;
1468
1469 ret = uniwill_resume_keyboard(data);
1470 if (ret < 0)
1471 return ret;
1472
1473 return uniwill_resume_battery(data);
1474 }
1475
1476 static DEFINE_SIMPLE_DEV_PM_OPS(uniwill_pm_ops, uniwill_suspend, uniwill_resume);
1477
1478 /*
1479 * We only use the DMI table for auoloading because the ACPI device itself
1480 * does not guarantee that the underlying EC implementation is supported.
1481 */
1482 static const struct acpi_device_id uniwill_id_table[] = {
1483 { "INOU0000" },
1484 { },
1485 };
1486
1487 static struct platform_driver uniwill_driver = {
1488 .driver = {
1489 .name = DRIVER_NAME,
1490 .dev_groups = uniwill_groups,
1491 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
1492 .acpi_match_table = uniwill_id_table,
1493 .pm = pm_sleep_ptr(&uniwill_pm_ops),
1494 },
1495 .probe = uniwill_probe,
1496 .shutdown = uniwill_shutdown,
1497 };
1498
1499 static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
1500 {
1501 .ident = "XMG FUSION 15",
1502 .matches = {
1503 DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
1504 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
1505 },
1506 },
1507 {
1508 .ident = "XMG FUSION 15",
1509 .matches = {
1510 DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
1511 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
1512 },
1513 },
1514 {
1515 .ident = "Intel NUC x15",
1516 .matches = {
1517 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
1518 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
1519 },
1520 .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
1521 UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
1522 UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
1523 UNIWILL_FEATURE_BATTERY |
1524 UNIWILL_FEATURE_HWMON),
1525 },
1526 {
1527 .ident = "Intel NUC x15",
1528 .matches = {
1529 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
1530 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
1531 },
1532 .driver_data = (void *)(UNIWILL_FEATURE_FN_LOCK_TOGGLE |
1533 UNIWILL_FEATURE_SUPER_KEY_TOGGLE |
1534 UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
1535 UNIWILL_FEATURE_LIGHTBAR |
1536 UNIWILL_FEATURE_BATTERY |
1537 UNIWILL_FEATURE_HWMON),
1538 },
1539 {
1540 .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
1541 .matches = {
1542 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1543 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"),
1544 },
1545 },
1546 {
1547 .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
1548 .matches = {
1549 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1550 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"),
1551 },
1552 },
1553 {
1554 .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
1555 .matches = {
1556 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1557 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
1558 },
1559 },
1560 {
1561 .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
1562 .matches = {
1563 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1564 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"),
1565 },
1566 },
1567 {
1568 .ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
1569 .matches = {
1570 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1571 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"),
1572 },
1573 },
1574 {
1575 .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
1576 .matches = {
1577 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1578 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"),
1579 },
1580 },
1581 {
1582 .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
1583 .matches = {
1584 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1585 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"),
1586 },
1587 },
1588 {
1589 .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
1590 .matches = {
1591 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1592 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
1593 },
1594 },
1595 {
1596 .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
1597 .matches = {
1598 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1599 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"),
1600 },
1601 },
1602 {
1603 .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
1604 .matches = {
1605 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1606 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
1607 },
1608 },
1609 {
1610 .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
1611 .matches = {
1612 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1613 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
1614 },
1615 },
1616 {
1617 .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
1618 .matches = {
1619 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1620 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"),
1621 },
1622 },
1623 {
1624 .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
1625 .matches = {
1626 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1627 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
1628 },
1629 },
1630 {
1631 .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
1632 .matches = {
1633 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1634 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"),
1635 },
1636 },
1637 {
1638 .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
1639 .matches = {
1640 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1641 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"),
1642 },
1643 },
1644 {
1645 .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
1646 .matches = {
1647 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1648 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"),
1649 },
1650 },
1651 {
1652 .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
1653 .matches = {
1654 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1655 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"),
1656 },
1657 },
1658 {
1659 .ident = "TUXEDO Polaris 15 Gen1 AMD",
1660 .matches = {
1661 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1662 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
1663 },
1664 },
1665 {
1666 .ident = "TUXEDO Polaris 15 Gen1 AMD",
1667 .matches = {
1668 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1669 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
1670 },
1671 },
1672 {
1673 .ident = "TUXEDO Polaris 17 Gen1 AMD",
1674 .matches = {
1675 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1676 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
1677 },
1678 },
1679 {
1680 .ident = "TUXEDO Polaris 17 Gen1 AMD",
1681 .matches = {
1682 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1683 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
1684 },
1685 },
1686 {
1687 .ident = "TUXEDO Polaris 15 Gen1 Intel",
1688 .matches = {
1689 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1690 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"),
1691 },
1692 },
1693 {
1694 .ident = "TUXEDO Polaris 15 Gen1 Intel",
1695 .matches = {
1696 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1697 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"),
1698 },
1699 },
1700 {
1701 .ident = "TUXEDO Polaris 17 Gen1 Intel",
1702 .matches = {
1703 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1704 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"),
1705 },
1706 },
1707 {
1708 .ident = "TUXEDO Polaris 17 Gen1 Intel",
1709 .matches = {
1710 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1711 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"),
1712 },
1713 },
1714 {
1715 .ident = "TUXEDO Trinity 15 Intel Gen1",
1716 .matches = {
1717 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1718 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"),
1719 },
1720 },
1721 {
1722 .ident = "TUXEDO Trinity 17 Intel Gen1",
1723 .matches = {
1724 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1725 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"),
1726 },
1727 },
1728 {
1729 .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
1730 .matches = {
1731 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1732 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"),
1733 },
1734 },
1735 {
1736 .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
1737 .matches = {
1738 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1739 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
1740 },
1741 },
1742 {
1743 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
1744 .matches = {
1745 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1746 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
1747 },
1748 },
1749 {
1750 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
1751 .matches = {
1752 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1753 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"),
1754 },
1755 },
1756 {
1757 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
1758 .matches = {
1759 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1760 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
1761 },
1762 },
1763 {
1764 .ident = "TUXEDO Stellaris 15 Gen4 Intel",
1765 .matches = {
1766 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1767 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"),
1768 },
1769 },
1770 {
1771 .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
1772 .matches = {
1773 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1774 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
1775 },
1776 },
1777 {
1778 .ident = "TUXEDO Stellaris 16 Gen5 AMD",
1779 .matches = {
1780 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1781 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
1782 },
1783 },
1784 {
1785 .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
1786 .matches = {
1787 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1788 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"),
1789 },
1790 },
1791 {
1792 .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
1793 .matches = {
1794 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1795 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
1796 },
1797 },
1798 {
1799 .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
1800 .matches = {
1801 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1802 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"),
1803 },
1804 },
1805 {
1806 .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
1807 .matches = {
1808 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1809 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"),
1810 },
1811 },
1812 {
1813 .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
1814 .matches = {
1815 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1816 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"),
1817 },
1818 },
1819 {
1820 .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
1821 .matches = {
1822 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1823 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"),
1824 },
1825 },
1826 {
1827 .ident = "TUXEDO Stellaris 16 Gen7 AMD",
1828 .matches = {
1829 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1830 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"),
1831 },
1832 },
1833 {
1834 .ident = "TUXEDO Stellaris 16 Gen7 Intel",
1835 .matches = {
1836 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1837 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"),
1838 },
1839 },
1840 {
1841 .ident = "TUXEDO Stellaris 16 Gen7 Intel",
1842 .matches = {
1843 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1844 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"),
1845 },
1846 },
1847 {
1848 .ident = "TUXEDO Pulse 14 Gen1 AMD",
1849 .matches = {
1850 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1851 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"),
1852 },
1853 },
1854 {
1855 .ident = "TUXEDO Pulse 15 Gen1 AMD",
1856 .matches = {
1857 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1858 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"),
1859 },
1860 },
1861 {
1862 .ident = "TUXEDO Pulse 15 Gen2 AMD",
1863 .matches = {
1864 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
1865 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
1866 },
1867 },
1868 { }
1869 };
1870 MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
1871
uniwill_init(void)1872 static int __init uniwill_init(void)
1873 {
1874 const struct dmi_system_id *id;
1875 int ret;
1876
1877 id = dmi_first_match(uniwill_dmi_table);
1878 if (!id) {
1879 if (!force)
1880 return -ENODEV;
1881
1882 /* Assume that the device supports all features */
1883 supported_features = UINT_MAX;
1884 pr_warn("Loading on a potentially unsupported device\n");
1885 } else {
1886 supported_features = (uintptr_t)id->driver_data;
1887 }
1888
1889 ret = platform_driver_register(&uniwill_driver);
1890 if (ret < 0)
1891 return ret;
1892
1893 ret = uniwill_wmi_register_driver();
1894 if (ret < 0) {
1895 platform_driver_unregister(&uniwill_driver);
1896 return ret;
1897 }
1898
1899 return 0;
1900 }
1901 module_init(uniwill_init);
1902
uniwill_exit(void)1903 static void __exit uniwill_exit(void)
1904 {
1905 uniwill_wmi_unregister_driver();
1906 platform_driver_unregister(&uniwill_driver);
1907 }
1908 module_exit(uniwill_exit);
1909
1910 MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
1911 MODULE_DESCRIPTION("Uniwill notebook driver");
1912 MODULE_LICENSE("GPL");
1913