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_SYSTEM_ID 0x0456
92 #define HAS_GPU BIT(7)
93
94 #define EC_ADDR_MAIN_FAN_RPM_1 0x0464
95
96 #define EC_ADDR_MAIN_FAN_RPM_2 0x0465
97
98 #define EC_ADDR_SCREEN_STATUS 0x0466
99 #define SCREEN_SUSPENDED BIT(6)
100
101 #define EC_ADDR_SECOND_FAN_RPM_1 0x046C
102
103 #define EC_ADDR_SECOND_FAN_RPM_2 0x046D
104
105 #define EC_ADDR_DEVICE_STATUS 0x047B
106 #define WIFI_STATUS_ON BIT(7)
107 /* BIT(5) is also unset depending on the rfkill state (bluetooth?) */
108
109 #define EC_ADDR_BAT_ALERT 0x0494
110
111 #define EC_ADDR_BAT_CYCLE_COUNT_1 0x04A6
112
113 #define EC_ADDR_BAT_CYCLE_COUNT_2 0x04A7
114
115 #define EC_ADDR_OEM_9 0x0726
116 #define AC_AUTO_BOOT_ENABLE BIT(3)
117
118 #define EC_ADDR_PROJECT_ID 0x0740
119 #define PROJECT_ID_NONE 0x00
120 #define PROJECT_ID_GI 0x01
121 #define PROJECT_ID_GJ 0x02
122 #define PROJECT_ID_GK 0x03
123 #define PROJECT_ID_GICN 0x04
124 #define PROJECT_ID_GJCN 0x05
125 #define PROJECT_ID_GK5CN_X 0x06
126 #define PROJECT_ID_GK7CN_S 0x07
127 #define PROJECT_ID_GK7CPCS_GK5CQ7Z 0x08
128 #define PROJECT_ID_PF 0x09
129 #define PROJECT_ID_GK5CP_4X_5X_6X 0x0A
130 #define PROJECT_ID_IDP 0x0B
131 #define PROJECT_ID_IDY_6Y 0x0C
132 #define PROJECT_ID_IDY_7Y 0x0D
133 #define PROJECT_ID_PF4MU_PF4MN_PF5MU 0x0E
134 #define PROJECT_ID_CML_GAMING 0x0F
135 #define PROJECT_ID_GK7NXXR 0x10
136 #define PROJECT_ID_GM5MU1Y 0x11
137 #define PROJECT_ID_PH4TRX1 0x12
138 #define PROJECT_ID_PH4TUX1 0x13
139 #define PROJECT_ID_PH4TQX1 0x14
140 #define PROJECT_ID_PH6TRX1 0x15
141 #define PROJECT_ID_PH6TQXX 0x16
142 #define PROJECT_ID_PHXAXXX 0x17
143 #define PROJECT_ID_PHXPXXX 0x18
144
145 #define EC_ADDR_AP_OEM 0x0741
146 #define ENABLE_MANUAL_CTRL BIT(0)
147 #define ITE_KBD_EFFECT_REACTIVE BIT(3)
148 #define FAN_ABNORMAL BIT(5)
149
150 #define EC_ADDR_SUPPORT_5 0x0742
151 #define FAN_TURBO_SUPPORTED BIT(4)
152 #define FAN_SUPPORT BIT(5)
153
154 #define EC_ADDR_CTGP_DB_CTRL 0x0743
155 #define CTGP_DB_GENERAL_ENABLE BIT(0)
156 #define CTGP_DB_DB_ENABLE BIT(1)
157 #define CTGP_DB_CTGP_ENABLE BIT(2)
158
159 #define EC_ADDR_CTGP_DB_CTGP_OFFSET 0x0744
160
161 #define EC_ADDR_CTGP_DB_TPP_OFFSET 0x0745
162
163 #define EC_ADDR_CTGP_DB_DB_OFFSET 0x0746
164
165 #define EC_ADDR_LIGHTBAR_AC_CTRL 0x0748
166 #define LIGHTBAR_APP_EXISTS BIT(0)
167 #define LIGHTBAR_POWER_SAVE BIT(1)
168 #define LIGHTBAR_S0_OFF BIT(2)
169 #define LIGHTBAR_S3_OFF BIT(3) // Breathing animation when suspended
170 #define LIGHTBAR_WELCOME BIT(7) // Rainbow animation
171
172 #define EC_ADDR_LIGHTBAR_AC_RED 0x0749
173
174 #define EC_ADDR_LIGHTBAR_AC_GREEN 0x074A
175
176 #define EC_ADDR_LIGHTBAR_AC_BLUE 0x074B
177
178 #define EC_ADDR_BIOS_OEM 0x074E
179 #define FN_LOCK_STATUS BIT(4)
180
181 #define EC_ADDR_MANUAL_FAN_CTRL 0x0751
182 #define FAN_LEVEL_MASK GENMASK(2, 0)
183 #define FAN_MODE_TURBO BIT(4)
184 #define FAN_MODE_HIGH BIT(5)
185 #define FAN_MODE_BOOST BIT(6)
186 #define FAN_MODE_USER BIT(7)
187
188 #define EC_ADDR_PWM_1 0x075B
189
190 #define EC_ADDR_PWM_2 0x075C
191
192 /* Unreliable */
193 #define EC_ADDR_SUPPORT_1 0x0765
194 #define AIRPLANE_MODE BIT(0)
195 #define GPS_SWITCH BIT(1)
196 #define OVERCLOCK BIT(2)
197 #define MACRO_KEY BIT(3)
198 #define SHORTCUT_KEY BIT(4)
199 #define SUPER_KEY_LOCK BIT(5)
200 #define LIGHTBAR BIT(6)
201 #define FAN_BOOST BIT(7)
202
203 #define EC_ADDR_SUPPORT_2 0x0766
204 #define SILENT_MODE BIT(0)
205 #define USB_CHARGING BIT(1)
206 #define RGB_KEYBOARD BIT(2)
207 #define CHINA_MODE BIT(5)
208 #define MY_BATTERY BIT(6)
209
210 #define EC_ADDR_TRIGGER 0x0767
211 #define TRIGGER_SUPER_KEY_LOCK BIT(0)
212 #define TRIGGER_LIGHTBAR BIT(1)
213 #define TRIGGER_FAN_BOOST BIT(2)
214 #define TRIGGER_SILENT_MODE BIT(3)
215 #define TRIGGER_USB_CHARGING BIT(4)
216 #define RGB_APPLY_COLOR BIT(5)
217 #define RGB_LOGO_EFFECT BIT(6)
218 #define RGB_RAINBOW_EFFECT BIT(7)
219
220 #define EC_ADDR_SWITCH_STATUS 0x0768
221 #define SUPER_KEY_LOCK_STATUS BIT(0)
222 #define LIGHTBAR_STATUS BIT(1)
223 #define FAN_BOOST_STATUS BIT(2)
224 #define MACRO_KEY_STATUS BIT(3)
225 #define MY_BAT_POWER_BAT_STATUS BIT(4)
226
227 #define EC_ADDR_RGB_RED 0x0769
228
229 #define EC_ADDR_RGB_GREEN 0x076A
230
231 #define EC_ADDR_RGB_BLUE 0x076B
232
233 #define EC_ADDR_ROMID_START 0x0770
234 #define ROMID_LENGTH 14
235
236 #define EC_ADDR_ROMID_EXTRA_1 0x077E
237
238 #define EC_ADDR_ROMID_EXTRA_2 0x077F
239
240 #define EC_ADDR_BIOS_OEM_2 0x0782
241 #define FAN_V2_NEW BIT(0)
242 #define FAN_QKEY BIT(1)
243 #define FAN_TABLE_OFFICE_MODE BIT(2)
244 #define FAN_V3 BIT(3)
245 #define DEFAULT_MODE BIT(4)
246 #define ENABLE_CHINA_MODE BIT(6)
247
248 #define EC_ADDR_PL1_SETTING 0x0783
249
250 #define EC_ADDR_PL2_SETTING 0x0784
251
252 #define EC_ADDR_PL4_SETTING 0x0785
253
254 #define EC_ADDR_FAN_DEFAULT 0x0786
255 #define FAN_CURVE_LENGTH 5
256
257 #define EC_ADDR_KBD_STATUS 0x078C
258 /* Unreliable on some models, use the device descriptor instead. */
259 #define KBD_WHITE_ONLY BIT(0)
260 #define KBD_POWER_OFF BIT(1)
261 #define KBD_TURBO_LEVEL_MASK GENMASK(3, 2)
262 #define KBD_APPLY BIT(4)
263 #define KBD_BRIGHTNESS_MASK GENMASK(7, 5)
264
265 #define EC_ADDR_FAN_CTRL 0x078E
266 #define FAN3P5 BIT(1)
267 #define CHARGING_PROFILE BIT(3)
268 #define UNIVERSAL_FAN_CTRL BIT(6)
269
270 #define EC_ADDR_BIOS_OEM_3 0x07A3
271 #define FAN_REDUCED_DURY_CYCLE BIT(5)
272 #define FAN_ALWAYS_ON BIT(6)
273
274 #define EC_ADDR_BIOS_BYTE 0x07A4
275 #define FN_LOCK_SWITCH BIT(3)
276
277 #define EC_ADDR_OEM_3 0x07A5
278 #define POWER_LED_MASK GENMASK(1, 0)
279 #define POWER_LED_LEFT 0x00
280 #define POWER_LED_BOTH 0x01
281 #define POWER_LED_NONE 0x02
282 #define FAN_QUIET BIT(2)
283 #define OVERBOOST BIT(4)
284 #define HIGH_POWER BIT(7)
285
286 #define EC_ADDR_OEM_4 0x07A6
287 #define OVERBOOST_DYN_TEMP_OFF BIT(1)
288 #define CHARGING_PROFILE_MASK GENMASK(5, 4)
289 #define CHARGING_PROFILE_HIGH_CAPACITY 0x00
290 #define CHARGING_PROFILE_BALANCED 0x01
291 #define CHARGING_PROFILE_STATIONARY 0x02
292 #define TOUCHPAD_TOGGLE_OFF BIT(6)
293
294 #define EC_ADDR_CHARGE_CTRL 0x07B9
295 #define CHARGE_CTRL_MASK GENMASK(6, 0)
296 #define CHARGE_CTRL_REACHED BIT(7)
297
298 #define EC_ADDR_UNIVERSAL_FAN_CTRL 0x07C5
299 #define SPLIT_TABLES BIT(7)
300
301 #define EC_ADDR_AP_OEM_6 0x07C6
302 #define ENABLE_UNIVERSAL_FAN_CTRL BIT(2)
303 #define BATTERY_CHARGE_FULL_OVER_24H BIT(3)
304 #define BATTERY_ERM_STATUS_REACHED BIT(4)
305
306 #define EC_ADDR_USB_C_POWER_PRIORITY 0x07CC
307 #define USB_C_POWER_PRIORITY BIT(7)
308
309 /* Same bits as EC_ADDR_LIGHTBAR_AC_CTRL except LIGHTBAR_S3_OFF */
310 #define EC_ADDR_LIGHTBAR_BAT_CTRL 0x07E2
311
312 #define EC_ADDR_LIGHTBAR_BAT_RED 0x07E3
313
314 #define EC_ADDR_LIGHTBAR_BAT_GREEN 0x07E4
315
316 #define EC_ADDR_LIGHTBAR_BAT_BLUE 0x07E5
317
318 #define EC_ADDR_CPU_TEMP_END_TABLE 0x0F00
319
320 #define EC_ADDR_CPU_TEMP_START_TABLE 0x0F10
321
322 #define EC_ADDR_CPU_FAN_SPEED_TABLE 0x0F20
323
324 #define EC_ADDR_GPU_TEMP_END_TABLE 0x0F30
325
326 #define EC_ADDR_GPU_TEMP_START_TABLE 0x0F40
327
328 #define EC_ADDR_GPU_FAN_SPEED_TABLE 0x0F50
329
330 /*
331 * Those two registers technically allow for manual fan control,
332 * but are unstable on some models and are likely not meant to
333 * be used by applications as they are only accessible when using
334 * the WMI interface.
335 */
336 #define EC_ADDR_PWM_1_WRITEABLE 0x1804
337
338 #define EC_ADDR_PWM_2_WRITEABLE 0x1809
339
340 #define DRIVER_NAME "uniwill"
341
342 /*
343 * The OEM software always sleeps up to 6 ms after reading/writing EC
344 * registers, so we emulate this behaviour for maximum compatibility.
345 */
346 #define UNIWILL_EC_DELAY_US 6000
347
348 #define PWM_MAX 200
349 #define FAN_TABLE_LENGTH 16
350
351 #define LED_CHANNELS 3
352
353 #define KBD_LED_CHANNELS 3
354 #define KBD_LED_MAX_INTENSITY 50
355
356 #define UNIWILL_FEATURE_FN_LOCK BIT(0)
357 #define UNIWILL_FEATURE_SUPER_KEY BIT(1)
358 #define UNIWILL_FEATURE_TOUCHPAD_TOGGLE BIT(2)
359 #define UNIWILL_FEATURE_LIGHTBAR BIT(3)
360 #define UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT BIT(4)
361 /* Mutually exclusive with the charge limit feature */
362 #define UNIWILL_FEATURE_BATTERY_CHARGE_MODES BIT(5)
363 #define UNIWILL_FEATURE_CPU_TEMP BIT(6)
364 #define UNIWILL_FEATURE_GPU_TEMP BIT(7)
365 #define UNIWILL_FEATURE_PRIMARY_FAN BIT(8)
366 #define UNIWILL_FEATURE_SECONDARY_FAN BIT(9)
367 #define UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL BIT(10)
368 #define UNIWILL_FEATURE_USB_C_POWER_PRIORITY BIT(11)
369 #define UNIWILL_FEATURE_KEYBOARD_BACKLIGHT BIT(12)
370 #define UNIWILL_FEATURE_AC_AUTO_BOOT BIT(13)
371 #define UNIWILL_FEATURE_USB_POWERSHARE BIT(14)
372
373 enum usb_c_power_priority_options {
374 USB_C_POWER_PRIORITY_CHARGING = 0,
375 USB_C_POWER_PRIORITY_PERFORMANCE,
376 };
377
378 struct uniwill_data {
379 struct device *dev;
380 acpi_handle handle;
381 struct regmap *regmap;
382 unsigned int features;
383 u8 project_id;
384 struct acpi_battery_hook hook;
385 struct mutex battery_lock; /* Protects the list of currently registered batteries */
386 union {
387 struct {
388 /* Protects writes to last_charge_type */
389 struct mutex charge_type_lock;
390 enum power_supply_charge_type last_charge_type;
391 };
392 unsigned int last_charge_ctrl;
393 };
394 bool last_fn_lock_state;
395 bool last_super_key_enable_state;
396 bool last_touchpad_toggle_enable_state;
397 bool last_usb_powershare_high_state;
398 struct mutex super_key_lock; /* Protects the toggling of the super key lock state */
399 struct list_head batteries;
400 struct mutex led_lock; /* Protects writes to the lightbar registers */
401 u8 lightbar_max_brightness;
402 struct led_classdev_mc led_mc_cdev;
403 struct mc_subled led_mc_subled_info[LED_CHANNELS];
404 bool kbd_led_single_color;
405 u8 kbd_led_max_brightness;
406 unsigned int last_kbd_status;
407 union {
408 struct {
409 /* Protects writes to the RGB keyboard backlight registers */
410 struct mutex kbd_rgb_led_lock;
411 struct led_classdev_mc kbd_led_mc_cdev;
412 struct mc_subled kbd_led_mc_subled_info[KBD_LED_CHANNELS];
413 };
414 struct led_classdev kbd_led_cdev;
415 };
416 struct mutex input_lock; /* Protects input sequence during notify */
417 struct input_dev *input_device;
418 struct notifier_block nb;
419 struct mutex usb_c_power_priority_lock; /* Protects dependent bit write and state safe */
420 enum usb_c_power_priority_options last_usb_c_power_priority_option;
421 };
422
423 struct uniwill_battery_entry {
424 struct list_head head;
425 struct power_supply *battery;
426 };
427
428 struct uniwill_device_descriptor {
429 unsigned int features;
430 bool kbd_led_single_color;
431 u8 kbd_led_max_brightness;
432 u8 lightbar_max_brightness;
433 /* Executed during driver probing */
434 int (*probe)(struct uniwill_data *data);
435 };
436
437 static bool force;
438 module_param_unsafe(force, bool, 0);
439 MODULE_PARM_DESC(force, "Force loading without checking for supported devices\n");
440
441 /*
442 * Contains device specific data like the feature bitmap since
443 * the associated registers are not always reliable.
444 */
445 static struct uniwill_device_descriptor device_descriptor __ro_after_init;
446
447 static const char * const uniwill_temp_labels[] = {
448 "CPU",
449 "GPU",
450 };
451
452 static const char * const uniwill_fan_labels[] = {
453 "Main",
454 "Secondary",
455 };
456
457 static const struct key_entry uniwill_keymap[] = {
458 /* Reported via keyboard controller */
459 { KE_IGNORE, UNIWILL_OSD_CAPSLOCK, { KEY_CAPSLOCK }},
460 { KE_IGNORE, UNIWILL_OSD_NUMLOCK, { KEY_NUMLOCK }},
461
462 /*
463 * Reported when the user enables/disables the super key.
464 * Those events might even be reported when the change was done
465 * using the sysfs attribute!
466 */
467 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_DISABLE, { KEY_UNKNOWN }},
468 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_ENABLE, { KEY_UNKNOWN }},
469 /* Optional, might not be reported by all devices */
470 { KE_IGNORE, UNIWILL_OSD_SUPER_KEY_STATE_CHANGED, { KEY_UNKNOWN }},
471
472 /* Reported in manual mode when toggling the airplane mode status */
473 { KE_KEY, UNIWILL_OSD_RFKILL, { KEY_RFKILL }},
474 { KE_IGNORE, UNIWILL_OSD_RADIOON, { KEY_UNKNOWN }},
475 { KE_IGNORE, UNIWILL_OSD_RADIOOFF, { KEY_UNKNOWN }},
476
477 /* Reported when user wants to cycle the platform profile */
478 { KE_KEY, UNIWILL_OSD_PERFORMANCE_MODE_TOGGLE, { KEY_F14 }},
479
480 /* Reported when the user wants to adjust the brightness of the keyboard */
481 { KE_KEY, UNIWILL_OSD_KBDILLUMDOWN, { KEY_KBDILLUMDOWN }},
482 { KE_KEY, UNIWILL_OSD_KBDILLUMUP, { KEY_KBDILLUMUP }},
483
484 /* Reported when the EC changed the keyboard backlight brightness */
485 { KE_IGNORE, UNIWILL_OSD_BACKLIGHT_LEVEL_CHANGE, { KEY_UNKNOWN }},
486
487 /* Reported when the user wants to toggle the microphone mute status */
488 { KE_KEY, UNIWILL_OSD_MIC_MUTE, { KEY_MICMUTE }},
489
490 /* Reported when the user wants to toggle the mute status */
491 { KE_IGNORE, UNIWILL_OSD_MUTE, { KEY_MUTE }},
492
493 /* Reported when the user wants to toggle the brightness of the keyboard */
494 { KE_KEY, UNIWILL_OSD_KBDILLUMTOGGLE, { KEY_KBDILLUMTOGGLE }},
495
496 /* FIXME: find out the exact meaning of those events */
497 { KE_IGNORE, UNIWILL_OSD_BAT_CHARGE_FULL_24_H, { KEY_UNKNOWN }},
498 { KE_IGNORE, UNIWILL_OSD_BAT_ERM_UPDATE, { KEY_UNKNOWN }},
499
500 /* Reported when the user wants to toggle the benchmark mode status */
501 { KE_IGNORE, UNIWILL_OSD_BENCHMARK_MODE_TOGGLE, { KEY_UNKNOWN }},
502
503 /* Reported when the screen is enabled/disabled during resume/suspend */
504 { KE_IGNORE, UNIWILL_OSD_SCREEN_STATE_CHANGED, { KEY_UNKNOWN }},
505
506 /* Reported when the user wants to toggle the webcam */
507 { KE_IGNORE, UNIWILL_OSD_WEBCAM_TOGGLE, { KEY_UNKNOWN }},
508
509 { KE_END }
510 };
511
uniwill_device_supports(const struct uniwill_data * data,unsigned int features)512 static inline bool uniwill_device_supports(const struct uniwill_data *data,
513 unsigned int features)
514 {
515 return (data->features & features) == features;
516 }
517
uniwill_device_supports_any(const struct uniwill_data * data,unsigned int features)518 static inline bool uniwill_device_supports_any(const struct uniwill_data *data,
519 unsigned int features)
520 {
521 return data->features & features;
522 }
523
uniwill_ec_reg_write(void * context,unsigned int reg,unsigned int val)524 static int uniwill_ec_reg_write(void *context, unsigned int reg, unsigned int val)
525 {
526 union acpi_object params[2] = {
527 {
528 .integer = {
529 .type = ACPI_TYPE_INTEGER,
530 .value = reg,
531 },
532 },
533 {
534 .integer = {
535 .type = ACPI_TYPE_INTEGER,
536 .value = val,
537 },
538 },
539 };
540 struct uniwill_data *data = context;
541 struct acpi_object_list input = {
542 .count = ARRAY_SIZE(params),
543 .pointer = params,
544 };
545 acpi_status status;
546
547 status = acpi_evaluate_object(data->handle, "ECRW", &input, NULL);
548 if (ACPI_FAILURE(status))
549 return -EIO;
550
551 usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2);
552
553 return 0;
554 }
555
uniwill_ec_reg_read(void * context,unsigned int reg,unsigned int * val)556 static int uniwill_ec_reg_read(void *context, unsigned int reg, unsigned int *val)
557 {
558 union acpi_object params[1] = {
559 {
560 .integer = {
561 .type = ACPI_TYPE_INTEGER,
562 .value = reg,
563 },
564 },
565 };
566 struct uniwill_data *data = context;
567 struct acpi_object_list input = {
568 .count = ARRAY_SIZE(params),
569 .pointer = params,
570 };
571 unsigned long long output;
572 acpi_status status;
573
574 status = acpi_evaluate_integer(data->handle, "ECRR", &input, &output);
575 if (ACPI_FAILURE(status))
576 return -EIO;
577
578 if (output > U8_MAX)
579 return -ENXIO;
580
581 usleep_range(UNIWILL_EC_DELAY_US, UNIWILL_EC_DELAY_US * 2);
582
583 *val = output;
584
585 return 0;
586 }
587
588 static const struct regmap_bus uniwill_ec_bus = {
589 .reg_write = uniwill_ec_reg_write,
590 .reg_read = uniwill_ec_reg_read,
591 .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
592 .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
593 };
594
uniwill_writeable_reg(struct device * dev,unsigned int reg)595 static bool uniwill_writeable_reg(struct device *dev, unsigned int reg)
596 {
597 switch (reg) {
598 case EC_ADDR_OEM_9:
599 case EC_ADDR_AP_OEM:
600 case EC_ADDR_LIGHTBAR_AC_CTRL:
601 case EC_ADDR_LIGHTBAR_AC_RED:
602 case EC_ADDR_LIGHTBAR_AC_GREEN:
603 case EC_ADDR_LIGHTBAR_AC_BLUE:
604 case EC_ADDR_BIOS_OEM:
605 case EC_ADDR_TRIGGER:
606 case EC_ADDR_RGB_RED:
607 case EC_ADDR_RGB_GREEN:
608 case EC_ADDR_RGB_BLUE:
609 case EC_ADDR_BIOS_OEM_2:
610 case EC_ADDR_KBD_STATUS:
611 case EC_ADDR_OEM_4:
612 case EC_ADDR_CHARGE_CTRL:
613 case EC_ADDR_LIGHTBAR_BAT_CTRL:
614 case EC_ADDR_LIGHTBAR_BAT_RED:
615 case EC_ADDR_LIGHTBAR_BAT_GREEN:
616 case EC_ADDR_LIGHTBAR_BAT_BLUE:
617 case EC_ADDR_CTGP_DB_CTRL:
618 case EC_ADDR_CTGP_DB_CTGP_OFFSET:
619 case EC_ADDR_CTGP_DB_TPP_OFFSET:
620 case EC_ADDR_CTGP_DB_DB_OFFSET:
621 case EC_ADDR_USB_C_POWER_PRIORITY:
622 return true;
623 default:
624 return false;
625 }
626 }
627
uniwill_readable_reg(struct device * dev,unsigned int reg)628 static bool uniwill_readable_reg(struct device *dev, unsigned int reg)
629 {
630 switch (reg) {
631 case EC_ADDR_CPU_TEMP:
632 case EC_ADDR_GPU_TEMP:
633 case EC_ADDR_MAIN_FAN_RPM_1:
634 case EC_ADDR_MAIN_FAN_RPM_2:
635 case EC_ADDR_SECOND_FAN_RPM_1:
636 case EC_ADDR_SECOND_FAN_RPM_2:
637 case EC_ADDR_BAT_ALERT:
638 case EC_ADDR_OEM_9:
639 case EC_ADDR_PROJECT_ID:
640 case EC_ADDR_AP_OEM:
641 case EC_ADDR_LIGHTBAR_AC_CTRL:
642 case EC_ADDR_LIGHTBAR_AC_RED:
643 case EC_ADDR_LIGHTBAR_AC_GREEN:
644 case EC_ADDR_LIGHTBAR_AC_BLUE:
645 case EC_ADDR_BIOS_OEM:
646 case EC_ADDR_PWM_1:
647 case EC_ADDR_PWM_2:
648 case EC_ADDR_SUPPORT_2:
649 case EC_ADDR_TRIGGER:
650 case EC_ADDR_SWITCH_STATUS:
651 case EC_ADDR_RGB_RED:
652 case EC_ADDR_RGB_GREEN:
653 case EC_ADDR_RGB_BLUE:
654 case EC_ADDR_BIOS_OEM_2:
655 case EC_ADDR_KBD_STATUS:
656 case EC_ADDR_OEM_4:
657 case EC_ADDR_CHARGE_CTRL:
658 case EC_ADDR_LIGHTBAR_BAT_CTRL:
659 case EC_ADDR_LIGHTBAR_BAT_RED:
660 case EC_ADDR_LIGHTBAR_BAT_GREEN:
661 case EC_ADDR_LIGHTBAR_BAT_BLUE:
662 case EC_ADDR_SYSTEM_ID:
663 case EC_ADDR_CTGP_DB_CTRL:
664 case EC_ADDR_CTGP_DB_CTGP_OFFSET:
665 case EC_ADDR_CTGP_DB_TPP_OFFSET:
666 case EC_ADDR_CTGP_DB_DB_OFFSET:
667 case EC_ADDR_USB_C_POWER_PRIORITY:
668 return true;
669 default:
670 return false;
671 }
672 }
673
uniwill_volatile_reg(struct device * dev,unsigned int reg)674 static bool uniwill_volatile_reg(struct device *dev, unsigned int reg)
675 {
676 switch (reg) {
677 case EC_ADDR_CPU_TEMP:
678 case EC_ADDR_GPU_TEMP:
679 case EC_ADDR_MAIN_FAN_RPM_1:
680 case EC_ADDR_MAIN_FAN_RPM_2:
681 case EC_ADDR_SECOND_FAN_RPM_1:
682 case EC_ADDR_SECOND_FAN_RPM_2:
683 case EC_ADDR_BAT_ALERT:
684 case EC_ADDR_BIOS_OEM:
685 case EC_ADDR_PWM_1:
686 case EC_ADDR_PWM_2:
687 case EC_ADDR_SUPPORT_2:
688 case EC_ADDR_TRIGGER:
689 case EC_ADDR_SWITCH_STATUS:
690 case EC_ADDR_KBD_STATUS:
691 case EC_ADDR_OEM_4:
692 case EC_ADDR_CHARGE_CTRL:
693 case EC_ADDR_USB_C_POWER_PRIORITY:
694 return true;
695 default:
696 return false;
697 }
698 }
699
700 static const struct regmap_config uniwill_ec_config = {
701 .reg_bits = 16,
702 .val_bits = 8,
703 .writeable_reg = uniwill_writeable_reg,
704 .readable_reg = uniwill_readable_reg,
705 .volatile_reg = uniwill_volatile_reg,
706 .can_sleep = true,
707 .max_register = 0xFFF,
708 .cache_type = REGCACHE_MAPLE,
709 .use_single_read = true,
710 .use_single_write = true,
711 };
712
uniwill_write_fn_lock(struct uniwill_data * data,bool status)713 static int uniwill_write_fn_lock(struct uniwill_data *data, bool status)
714 {
715 unsigned int value;
716
717 if (status)
718 value = FN_LOCK_STATUS;
719 else
720 value = 0;
721
722 return regmap_update_bits(data->regmap, EC_ADDR_BIOS_OEM, FN_LOCK_STATUS, value);
723 }
724
fn_lock_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)725 static ssize_t fn_lock_store(struct device *dev, struct device_attribute *attr, const char *buf,
726 size_t count)
727 {
728 struct uniwill_data *data = dev_get_drvdata(dev);
729 bool enable;
730 int ret;
731
732 ret = kstrtobool(buf, &enable);
733 if (ret < 0)
734 return ret;
735
736 ret = uniwill_write_fn_lock(data, enable);
737 if (ret < 0)
738 return ret;
739
740 return count;
741 }
742
uniwill_read_fn_lock(struct uniwill_data * data,bool * status)743 static int uniwill_read_fn_lock(struct uniwill_data *data, bool *status)
744 {
745 unsigned int value;
746 int ret;
747
748 ret = regmap_read(data->regmap, EC_ADDR_BIOS_OEM, &value);
749 if (ret < 0)
750 return ret;
751
752 *status = !!(value & FN_LOCK_STATUS);
753
754 return 0;
755 }
756
fn_lock_show(struct device * dev,struct device_attribute * attr,char * buf)757 static ssize_t fn_lock_show(struct device *dev, struct device_attribute *attr, char *buf)
758 {
759 struct uniwill_data *data = dev_get_drvdata(dev);
760 bool status;
761 int ret;
762
763 ret = uniwill_read_fn_lock(data, &status);
764 if (ret < 0)
765 return ret;
766
767 return sysfs_emit(buf, "%d\n", status);
768 }
769
770 static DEVICE_ATTR_RW(fn_lock);
771
uniwill_write_super_key_enable(struct uniwill_data * data,bool status)772 static int uniwill_write_super_key_enable(struct uniwill_data *data, bool status)
773 {
774 unsigned int value;
775 int ret;
776
777 guard(mutex)(&data->super_key_lock);
778
779 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
780 if (ret < 0)
781 return ret;
782
783 /*
784 * We can only toggle the super key lock, so we return early if the setting
785 * is already in the correct state.
786 */
787 if (status == !(value & SUPER_KEY_LOCK_STATUS))
788 return 0;
789
790 return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_SUPER_KEY_LOCK,
791 TRIGGER_SUPER_KEY_LOCK);
792 }
793
super_key_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)794 static ssize_t super_key_enable_store(struct device *dev, struct device_attribute *attr,
795 const char *buf, size_t count)
796 {
797 struct uniwill_data *data = dev_get_drvdata(dev);
798 bool enable;
799 int ret;
800
801 ret = kstrtobool(buf, &enable);
802 if (ret < 0)
803 return ret;
804
805 ret = uniwill_write_super_key_enable(data, enable);
806 if (ret < 0)
807 return ret;
808
809 return count;
810 }
811
uniwill_read_super_key_enable(struct uniwill_data * data,bool * status)812 static int uniwill_read_super_key_enable(struct uniwill_data *data, bool *status)
813 {
814 unsigned int value;
815 int ret;
816
817 ret = regmap_read(data->regmap, EC_ADDR_SWITCH_STATUS, &value);
818 if (ret < 0)
819 return ret;
820
821 *status = !(value & SUPER_KEY_LOCK_STATUS);
822
823 return 0;
824 }
825
super_key_enable_show(struct device * dev,struct device_attribute * attr,char * buf)826 static ssize_t super_key_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
827 {
828 struct uniwill_data *data = dev_get_drvdata(dev);
829 bool status;
830 int ret;
831
832 ret = uniwill_read_super_key_enable(data, &status);
833 if (ret < 0)
834 return ret;
835
836 return sysfs_emit(buf, "%d\n", status);
837 }
838
839 static DEVICE_ATTR_RW(super_key_enable);
840
uniwill_write_touchpad_toggle_enable(struct uniwill_data * data,bool status)841 static int uniwill_write_touchpad_toggle_enable(struct uniwill_data *data, bool status)
842 {
843 unsigned int value;
844
845 if (status)
846 value = 0;
847 else
848 value = TOUCHPAD_TOGGLE_OFF;
849
850 return regmap_update_bits(data->regmap, EC_ADDR_OEM_4, TOUCHPAD_TOGGLE_OFF, value);
851 }
852
touchpad_toggle_enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)853 static ssize_t touchpad_toggle_enable_store(struct device *dev, struct device_attribute *attr,
854 const char *buf, size_t count)
855 {
856 struct uniwill_data *data = dev_get_drvdata(dev);
857 bool enable;
858 int ret;
859
860 ret = kstrtobool(buf, &enable);
861 if (ret < 0)
862 return ret;
863
864 ret = uniwill_write_touchpad_toggle_enable(data, enable);
865 if (ret < 0)
866 return ret;
867
868 return count;
869 }
870
uniwill_read_touchpad_toggle_enable(struct uniwill_data * data,bool * status)871 static int uniwill_read_touchpad_toggle_enable(struct uniwill_data *data, bool *status)
872 {
873 unsigned int value;
874 int ret;
875
876 ret = regmap_read(data->regmap, EC_ADDR_OEM_4, &value);
877 if (ret < 0)
878 return ret;
879
880 *status = !(value & TOUCHPAD_TOGGLE_OFF);
881
882 return 0;
883 }
884
touchpad_toggle_enable_show(struct device * dev,struct device_attribute * attr,char * buf)885 static ssize_t touchpad_toggle_enable_show(struct device *dev, struct device_attribute *attr,
886 char *buf)
887 {
888 struct uniwill_data *data = dev_get_drvdata(dev);
889 bool status;
890 int ret;
891
892 ret = uniwill_read_touchpad_toggle_enable(data, &status);
893 if (ret < 0)
894 return ret;
895
896 return sysfs_emit(buf, "%d\n", status);
897 }
898
899 static DEVICE_ATTR_RW(touchpad_toggle_enable);
900
rainbow_animation_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)901 static ssize_t rainbow_animation_store(struct device *dev, struct device_attribute *attr,
902 const char *buf, size_t count)
903 {
904 struct uniwill_data *data = dev_get_drvdata(dev);
905 unsigned int value;
906 bool enable;
907 int ret;
908
909 ret = kstrtobool(buf, &enable);
910 if (ret < 0)
911 return ret;
912
913 if (enable)
914 value = LIGHTBAR_WELCOME;
915 else
916 value = 0;
917
918 guard(mutex)(&data->led_lock);
919
920 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_WELCOME, value);
921 if (ret < 0)
922 return ret;
923
924 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_WELCOME, value);
925 if (ret < 0)
926 return ret;
927
928 return count;
929 }
930
rainbow_animation_show(struct device * dev,struct device_attribute * attr,char * buf)931 static ssize_t rainbow_animation_show(struct device *dev, struct device_attribute *attr, char *buf)
932 {
933 struct uniwill_data *data = dev_get_drvdata(dev);
934 unsigned int value;
935 int ret;
936
937 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
938 if (ret < 0)
939 return ret;
940
941 return sysfs_emit(buf, "%d\n", !!(value & LIGHTBAR_WELCOME));
942 }
943
944 static DEVICE_ATTR_RW(rainbow_animation);
945
breathing_in_suspend_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)946 static ssize_t breathing_in_suspend_store(struct device *dev, struct device_attribute *attr,
947 const char *buf, size_t count)
948 {
949 struct uniwill_data *data = dev_get_drvdata(dev);
950 unsigned int value;
951 bool enable;
952 int ret;
953
954 ret = kstrtobool(buf, &enable);
955 if (ret < 0)
956 return ret;
957
958 if (enable)
959 value = 0;
960 else
961 value = LIGHTBAR_S3_OFF;
962
963 /* We only access a single register here, so we do not need to use data->led_lock */
964 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S3_OFF, value);
965 if (ret < 0)
966 return ret;
967
968 return count;
969 }
970
breathing_in_suspend_show(struct device * dev,struct device_attribute * attr,char * buf)971 static ssize_t breathing_in_suspend_show(struct device *dev, struct device_attribute *attr,
972 char *buf)
973 {
974 struct uniwill_data *data = dev_get_drvdata(dev);
975 unsigned int value;
976 int ret;
977
978 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
979 if (ret < 0)
980 return ret;
981
982 return sysfs_emit(buf, "%d\n", !(value & LIGHTBAR_S3_OFF));
983 }
984
985 static DEVICE_ATTR_RW(breathing_in_suspend);
986
ctgp_offset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)987 static ssize_t ctgp_offset_store(struct device *dev, struct device_attribute *attr,
988 const char *buf, size_t count)
989 {
990 struct uniwill_data *data = dev_get_drvdata(dev);
991 unsigned int value;
992 int ret;
993
994 ret = kstrtouint(buf, 0, &value);
995 if (ret < 0)
996 return ret;
997
998 if (value > U8_MAX)
999 return -EINVAL;
1000
1001 ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, value);
1002 if (ret < 0)
1003 return ret;
1004
1005 return count;
1006 }
1007
ctgp_offset_show(struct device * dev,struct device_attribute * attr,char * buf)1008 static ssize_t ctgp_offset_show(struct device *dev, struct device_attribute *attr,
1009 char *buf)
1010 {
1011 struct uniwill_data *data = dev_get_drvdata(dev);
1012 unsigned int value;
1013 int ret;
1014
1015 ret = regmap_read(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, &value);
1016 if (ret < 0)
1017 return ret;
1018
1019 return sysfs_emit(buf, "%u\n", value);
1020 }
1021
1022 static DEVICE_ATTR_RW(ctgp_offset);
1023
uniwill_nvidia_ctgp_init(struct uniwill_data * data)1024 static int uniwill_nvidia_ctgp_init(struct uniwill_data *data)
1025 {
1026 int ret;
1027
1028 if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
1029 return 0;
1030
1031 ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_CTGP_OFFSET, 0);
1032 if (ret < 0)
1033 return ret;
1034
1035 ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_TPP_OFFSET, 255);
1036 if (ret < 0)
1037 return ret;
1038
1039 ret = regmap_write(data->regmap, EC_ADDR_CTGP_DB_DB_OFFSET, 25);
1040 if (ret < 0)
1041 return ret;
1042
1043 ret = regmap_set_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
1044 CTGP_DB_GENERAL_ENABLE | CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
1045 if (ret < 0)
1046 return ret;
1047
1048 return 0;
1049 }
1050
1051 static const char * const usb_c_power_priority_text[] = {
1052 [USB_C_POWER_PRIORITY_CHARGING] = "charging",
1053 [USB_C_POWER_PRIORITY_PERFORMANCE] = "performance",
1054 };
1055
1056 static const u8 usb_c_power_priority_value[] = {
1057 [USB_C_POWER_PRIORITY_CHARGING] = 0,
1058 [USB_C_POWER_PRIORITY_PERFORMANCE] = USB_C_POWER_PRIORITY,
1059 };
1060
usb_c_power_priority_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1061 static ssize_t usb_c_power_priority_store(struct device *dev,
1062 struct device_attribute *attr,
1063 const char *buf, size_t count)
1064 {
1065 struct uniwill_data *data = dev_get_drvdata(dev);
1066 enum usb_c_power_priority_options option;
1067 unsigned int value;
1068 int ret;
1069
1070 ret = sysfs_match_string(usb_c_power_priority_text, buf);
1071 if (ret < 0)
1072 return ret;
1073
1074 option = ret;
1075 value = usb_c_power_priority_value[option];
1076
1077 guard(mutex)(&data->usb_c_power_priority_lock);
1078
1079 ret = regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
1080 USB_C_POWER_PRIORITY, value);
1081 if (ret < 0)
1082 return ret;
1083
1084 data->last_usb_c_power_priority_option = option;
1085
1086 return count;
1087 }
1088
usb_c_power_priority_show(struct device * dev,struct device_attribute * attr,char * buf)1089 static ssize_t usb_c_power_priority_show(struct device *dev,
1090 struct device_attribute *attr,
1091 char *buf)
1092 {
1093 struct uniwill_data *data = dev_get_drvdata(dev);
1094 unsigned int value;
1095 int ret;
1096
1097 ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
1098 if (ret < 0)
1099 return ret;
1100
1101 value &= USB_C_POWER_PRIORITY;
1102
1103 if (usb_c_power_priority_value[USB_C_POWER_PRIORITY_PERFORMANCE] == value)
1104 return sysfs_emit(buf, "%s\n",
1105 usb_c_power_priority_text[USB_C_POWER_PRIORITY_PERFORMANCE]);
1106
1107 return sysfs_emit(buf, "%s\n", usb_c_power_priority_text[USB_C_POWER_PRIORITY_CHARGING]);
1108 }
1109
1110 static DEVICE_ATTR_RW(usb_c_power_priority);
1111
usb_c_power_priority_restore(struct uniwill_data * data)1112 static int usb_c_power_priority_restore(struct uniwill_data *data)
1113 {
1114 unsigned int value;
1115
1116 value = usb_c_power_priority_value[data->last_usb_c_power_priority_option];
1117
1118 guard(mutex)(&data->usb_c_power_priority_lock);
1119
1120 return regmap_update_bits(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY,
1121 USB_C_POWER_PRIORITY, value);
1122 }
1123
usb_c_power_priority_init(struct uniwill_data * data)1124 static int usb_c_power_priority_init(struct uniwill_data *data)
1125 {
1126 unsigned int value;
1127 int ret;
1128
1129 if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
1130 return 0;
1131
1132 ret = devm_mutex_init(data->dev, &data->usb_c_power_priority_lock);
1133 if (ret < 0)
1134 return ret;
1135
1136 ret = regmap_read(data->regmap, EC_ADDR_USB_C_POWER_PRIORITY, &value);
1137 if (ret < 0)
1138 return ret;
1139
1140 value &= USB_C_POWER_PRIORITY;
1141
1142 data->last_usb_c_power_priority_option =
1143 usb_c_power_priority_value[USB_C_POWER_PRIORITY_PERFORMANCE] == value ?
1144 USB_C_POWER_PRIORITY_PERFORMANCE :
1145 USB_C_POWER_PRIORITY_CHARGING;
1146
1147 return 0;
1148 }
1149
ac_auto_boot_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1150 static ssize_t ac_auto_boot_store(struct device *dev, struct device_attribute *attr,
1151 const char *buf, size_t count)
1152 {
1153 struct uniwill_data *data = dev_get_drvdata(dev);
1154 unsigned int regval;
1155 bool enable;
1156 int ret;
1157
1158 ret = kstrtobool(buf, &enable);
1159 if (ret < 0)
1160 return ret;
1161
1162 if (enable)
1163 regval = AC_AUTO_BOOT_ENABLE;
1164 else
1165 regval = 0;
1166
1167 ret = regmap_update_bits(data->regmap, EC_ADDR_OEM_9, AC_AUTO_BOOT_ENABLE, regval);
1168 if (ret < 0)
1169 return ret;
1170
1171 return count;
1172 }
1173
ac_auto_boot_show(struct device * dev,struct device_attribute * attr,char * buf)1174 static ssize_t ac_auto_boot_show(struct device *dev, struct device_attribute *attr, char *buf)
1175 {
1176 struct uniwill_data *data = dev_get_drvdata(dev);
1177 unsigned int regval;
1178 int ret;
1179
1180 ret = regmap_read(data->regmap, EC_ADDR_OEM_9, ®val);
1181 if (ret < 0)
1182 return ret;
1183
1184 return sysfs_emit(buf, "%d\n", !!(regval & AC_AUTO_BOOT_ENABLE));
1185 }
1186
1187 static DEVICE_ATTR_RW(ac_auto_boot);
1188
uniwill_write_usb_powershare_high(struct uniwill_data * data,bool status)1189 static int uniwill_write_usb_powershare_high(struct uniwill_data *data, bool status)
1190 {
1191 unsigned int value;
1192
1193 if (status)
1194 value = TRIGGER_USB_CHARGING;
1195 else
1196 value = 0;
1197
1198 /*
1199 * Normaly this RMW-sequence could also trigger the super key toggle,
1200 * but the EC seems to take care that those bits are always read as 0.
1201 */
1202 return regmap_update_bits(data->regmap, EC_ADDR_TRIGGER, TRIGGER_USB_CHARGING, value);
1203 }
1204
usb_powershare_high_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1205 static ssize_t usb_powershare_high_store(struct device *dev, struct device_attribute *attr,
1206 const char *buf, size_t count)
1207 {
1208 struct uniwill_data *data = dev_get_drvdata(dev);
1209 bool enable;
1210 int ret;
1211
1212 ret = kstrtobool(buf, &enable);
1213 if (ret < 0)
1214 return ret;
1215
1216 ret = uniwill_write_usb_powershare_high(data, enable);
1217 if (ret < 0)
1218 return ret;
1219
1220 return count;
1221 }
1222
uniwill_read_usb_powershare_high(struct uniwill_data * data,bool * status)1223 static int uniwill_read_usb_powershare_high(struct uniwill_data *data, bool *status)
1224 {
1225 unsigned int value;
1226 int ret;
1227
1228 ret = regmap_read(data->regmap, EC_ADDR_TRIGGER, &value);
1229 if (ret < 0)
1230 return ret;
1231
1232 *status = !!(value & TRIGGER_USB_CHARGING);
1233
1234 return 0;
1235 }
1236
usb_powershare_high_show(struct device * dev,struct device_attribute * attr,char * buf)1237 static ssize_t usb_powershare_high_show(struct device *dev, struct device_attribute *attr,
1238 char *buf)
1239 {
1240 struct uniwill_data *data = dev_get_drvdata(dev);
1241 bool status;
1242 int ret;
1243
1244 ret = uniwill_read_usb_powershare_high(data, &status);
1245 if (ret < 0)
1246 return ret;
1247
1248 return sysfs_emit(buf, "%d\n", status);
1249 }
1250
1251 static DEVICE_ATTR_RW(usb_powershare_high);
1252
1253 static struct attribute *uniwill_attrs[] = {
1254 /* Keyboard-related */
1255 &dev_attr_fn_lock.attr,
1256 &dev_attr_super_key_enable.attr,
1257 &dev_attr_touchpad_toggle_enable.attr,
1258 /* Lightbar-related */
1259 &dev_attr_rainbow_animation.attr,
1260 &dev_attr_breathing_in_suspend.attr,
1261 /* Power-management-related */
1262 &dev_attr_ctgp_offset.attr,
1263 &dev_attr_usb_c_power_priority.attr,
1264 &dev_attr_ac_auto_boot.attr,
1265 &dev_attr_usb_powershare_high.attr,
1266 NULL
1267 };
1268
uniwill_attr_is_visible(struct kobject * kobj,struct attribute * attr,int n)1269 static umode_t uniwill_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
1270 {
1271 struct device *dev = kobj_to_dev(kobj);
1272 struct uniwill_data *data = dev_get_drvdata(dev);
1273
1274 if (attr == &dev_attr_fn_lock.attr) {
1275 if (uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
1276 return attr->mode;
1277 }
1278
1279 if (attr == &dev_attr_super_key_enable.attr) {
1280 if (uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
1281 return attr->mode;
1282 }
1283
1284 if (attr == &dev_attr_touchpad_toggle_enable.attr) {
1285 if (uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
1286 return attr->mode;
1287 }
1288
1289 if (attr == &dev_attr_rainbow_animation.attr ||
1290 attr == &dev_attr_breathing_in_suspend.attr) {
1291 if (uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
1292 return attr->mode;
1293 }
1294
1295 if (attr == &dev_attr_ctgp_offset.attr) {
1296 if (uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
1297 return attr->mode;
1298 }
1299
1300 if (attr == &dev_attr_usb_c_power_priority.attr) {
1301 if (uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
1302 return attr->mode;
1303 }
1304
1305 if (attr == &dev_attr_ac_auto_boot.attr) {
1306 if (uniwill_device_supports(data, UNIWILL_FEATURE_AC_AUTO_BOOT))
1307 return attr->mode;
1308 }
1309
1310 if (attr == &dev_attr_usb_powershare_high.attr) {
1311 if (uniwill_device_supports(data, UNIWILL_FEATURE_USB_POWERSHARE))
1312 return attr->mode;
1313 }
1314
1315 return 0;
1316 }
1317
1318 static const struct attribute_group uniwill_group = {
1319 .is_visible = uniwill_attr_is_visible,
1320 .attrs = uniwill_attrs,
1321 };
1322
1323 static const struct attribute_group *uniwill_groups[] = {
1324 &uniwill_group,
1325 NULL
1326 };
1327
uniwill_is_visible(const void * drvdata,enum hwmon_sensor_types type,u32 attr,int channel)1328 static umode_t uniwill_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
1329 int channel)
1330 {
1331 const struct uniwill_data *data = drvdata;
1332 unsigned int feature;
1333
1334 switch (type) {
1335 case hwmon_temp:
1336 switch (channel) {
1337 case 0:
1338 feature = UNIWILL_FEATURE_CPU_TEMP;
1339 break;
1340 case 1:
1341 feature = UNIWILL_FEATURE_GPU_TEMP;
1342 break;
1343 default:
1344 return 0;
1345 }
1346 break;
1347 case hwmon_fan:
1348 case hwmon_pwm:
1349 switch (channel) {
1350 case 0:
1351 feature = UNIWILL_FEATURE_PRIMARY_FAN;
1352 break;
1353 case 1:
1354 feature = UNIWILL_FEATURE_SECONDARY_FAN;
1355 break;
1356 default:
1357 return 0;
1358 }
1359 break;
1360 default:
1361 return 0;
1362 }
1363
1364 if (uniwill_device_supports(data, feature))
1365 return 0444;
1366
1367 return 0;
1368 }
1369
uniwill_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)1370 static int uniwill_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
1371 long *val)
1372 {
1373 struct uniwill_data *data = dev_get_drvdata(dev);
1374 unsigned int value;
1375 __be16 rpm;
1376 int ret;
1377
1378 switch (type) {
1379 case hwmon_temp:
1380 switch (channel) {
1381 case 0:
1382 ret = regmap_read(data->regmap, EC_ADDR_CPU_TEMP, &value);
1383 break;
1384 case 1:
1385 ret = regmap_read(data->regmap, EC_ADDR_GPU_TEMP, &value);
1386 break;
1387 default:
1388 return -EOPNOTSUPP;
1389 }
1390
1391 if (ret < 0)
1392 return ret;
1393
1394 *val = value * MILLIDEGREE_PER_DEGREE;
1395 return 0;
1396 case hwmon_fan:
1397 switch (channel) {
1398 case 0:
1399 ret = regmap_bulk_read(data->regmap, EC_ADDR_MAIN_FAN_RPM_1, &rpm,
1400 sizeof(rpm));
1401 break;
1402 case 1:
1403 ret = regmap_bulk_read(data->regmap, EC_ADDR_SECOND_FAN_RPM_1, &rpm,
1404 sizeof(rpm));
1405 break;
1406 default:
1407 return -EOPNOTSUPP;
1408 }
1409
1410 if (ret < 0)
1411 return ret;
1412
1413 *val = be16_to_cpu(rpm);
1414 return 0;
1415 case hwmon_pwm:
1416 switch (channel) {
1417 case 0:
1418 ret = regmap_read(data->regmap, EC_ADDR_PWM_1, &value);
1419 break;
1420 case 1:
1421 ret = regmap_read(data->regmap, EC_ADDR_PWM_2, &value);
1422 break;
1423 default:
1424 return -EOPNOTSUPP;
1425 }
1426
1427 if (ret < 0)
1428 return ret;
1429
1430 *val = fixp_linear_interpolate(0, 0, PWM_MAX, U8_MAX, value);
1431 return 0;
1432 default:
1433 return -EOPNOTSUPP;
1434 }
1435 }
1436
uniwill_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)1437 static int uniwill_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
1438 int channel, const char **str)
1439 {
1440 switch (type) {
1441 case hwmon_temp:
1442 *str = uniwill_temp_labels[channel];
1443 return 0;
1444 case hwmon_fan:
1445 *str = uniwill_fan_labels[channel];
1446 return 0;
1447 default:
1448 return -EOPNOTSUPP;
1449 }
1450 }
1451
1452 static const struct hwmon_ops uniwill_ops = {
1453 .is_visible = uniwill_is_visible,
1454 .read = uniwill_read,
1455 .read_string = uniwill_read_string,
1456 };
1457
1458 static const struct hwmon_channel_info * const uniwill_info[] = {
1459 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
1460 HWMON_CHANNEL_INFO(temp,
1461 HWMON_T_INPUT | HWMON_T_LABEL,
1462 HWMON_T_INPUT | HWMON_T_LABEL),
1463 HWMON_CHANNEL_INFO(fan,
1464 HWMON_F_INPUT | HWMON_F_LABEL,
1465 HWMON_F_INPUT | HWMON_F_LABEL),
1466 HWMON_CHANNEL_INFO(pwm,
1467 HWMON_PWM_INPUT,
1468 HWMON_PWM_INPUT),
1469 NULL
1470 };
1471
1472 static const struct hwmon_chip_info uniwill_chip_info = {
1473 .ops = &uniwill_ops,
1474 .info = uniwill_info,
1475 };
1476
uniwill_hwmon_init(struct uniwill_data * data)1477 static int uniwill_hwmon_init(struct uniwill_data *data)
1478 {
1479 struct device *hdev;
1480
1481 if (!uniwill_device_supports(data, UNIWILL_FEATURE_CPU_TEMP) &&
1482 !uniwill_device_supports(data, UNIWILL_FEATURE_GPU_TEMP) &&
1483 !uniwill_device_supports(data, UNIWILL_FEATURE_PRIMARY_FAN) &&
1484 !uniwill_device_supports(data, UNIWILL_FEATURE_SECONDARY_FAN))
1485 return 0;
1486
1487 hdev = devm_hwmon_device_register_with_info(data->dev, "uniwill", data,
1488 &uniwill_chip_info, NULL);
1489
1490 return PTR_ERR_OR_ZERO(hdev);
1491 }
1492
1493 static const unsigned int uniwill_led_channel_to_bat_reg[LED_CHANNELS] = {
1494 EC_ADDR_LIGHTBAR_BAT_RED,
1495 EC_ADDR_LIGHTBAR_BAT_GREEN,
1496 EC_ADDR_LIGHTBAR_BAT_BLUE,
1497 };
1498
1499 static const unsigned int uniwill_led_channel_to_ac_reg[LED_CHANNELS] = {
1500 EC_ADDR_LIGHTBAR_AC_RED,
1501 EC_ADDR_LIGHTBAR_AC_GREEN,
1502 EC_ADDR_LIGHTBAR_AC_BLUE,
1503 };
1504
uniwill_led_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)1505 static int uniwill_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness)
1506 {
1507 struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev);
1508 struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, led_mc_cdev);
1509 unsigned int value;
1510 int ret;
1511
1512 ret = led_mc_calc_color_components(led_mc_cdev, brightness);
1513 if (ret < 0)
1514 return ret;
1515
1516 guard(mutex)(&data->led_lock);
1517
1518 for (int i = 0; i < LED_CHANNELS; i++) {
1519 /* Prevent the brightness values from overflowing */
1520 value = min(data->lightbar_max_brightness, data->led_mc_subled_info[i].brightness);
1521 ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
1522 if (ret < 0)
1523 return ret;
1524
1525 ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
1526 if (ret < 0)
1527 return ret;
1528 }
1529
1530 if (brightness)
1531 value = 0;
1532 else
1533 value = LIGHTBAR_S0_OFF;
1534
1535 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, LIGHTBAR_S0_OFF, value);
1536 if (ret < 0)
1537 return ret;
1538
1539 return regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_S0_OFF, value);
1540 }
1541
1542 #define LIGHTBAR_MASK (LIGHTBAR_APP_EXISTS | LIGHTBAR_S0_OFF | LIGHTBAR_S3_OFF | LIGHTBAR_WELCOME)
1543
uniwill_led_init(struct uniwill_data * data)1544 static int uniwill_led_init(struct uniwill_data *data)
1545 {
1546 struct led_init_data init_data = {
1547 .devicename = DRIVER_NAME,
1548 .default_label = "multicolor:" LED_FUNCTION_STATUS,
1549 .devname_mandatory = true,
1550 };
1551 unsigned int color_indices[3] = {
1552 LED_COLOR_ID_RED,
1553 LED_COLOR_ID_GREEN,
1554 LED_COLOR_ID_BLUE,
1555 };
1556 unsigned int value;
1557 int ret;
1558
1559 if (!uniwill_device_supports(data, UNIWILL_FEATURE_LIGHTBAR))
1560 return 0;
1561
1562 ret = devm_mutex_init(data->dev, &data->led_lock);
1563 if (ret < 0)
1564 return ret;
1565
1566 /*
1567 * The EC has separate lightbar settings for AC and battery mode,
1568 * so we have to ensure that both settings are the same.
1569 */
1570 ret = regmap_read(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, &value);
1571 if (ret < 0)
1572 return ret;
1573
1574 value |= LIGHTBAR_APP_EXISTS;
1575 ret = regmap_write(data->regmap, EC_ADDR_LIGHTBAR_AC_CTRL, value);
1576 if (ret < 0)
1577 return ret;
1578
1579 /*
1580 * The breathing animation during suspend is not supported when
1581 * running on battery power.
1582 */
1583 value |= LIGHTBAR_S3_OFF;
1584 ret = regmap_update_bits(data->regmap, EC_ADDR_LIGHTBAR_BAT_CTRL, LIGHTBAR_MASK, value);
1585 if (ret < 0)
1586 return ret;
1587
1588 data->led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
1589 data->led_mc_cdev.led_cdev.max_brightness = data->lightbar_max_brightness;
1590 data->led_mc_cdev.led_cdev.flags = LED_REJECT_NAME_CONFLICT;
1591 data->led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_led_brightness_set;
1592
1593 if (value & LIGHTBAR_S0_OFF)
1594 data->led_mc_cdev.led_cdev.brightness = 0;
1595 else
1596 data->led_mc_cdev.led_cdev.brightness = data->lightbar_max_brightness;
1597
1598 for (int i = 0; i < LED_CHANNELS; i++) {
1599 data->led_mc_subled_info[i].color_index = color_indices[i];
1600
1601 ret = regmap_read(data->regmap, uniwill_led_channel_to_ac_reg[i], &value);
1602 if (ret < 0)
1603 return ret;
1604
1605 /*
1606 * Make sure that the initial intensity value is not greater than
1607 * the maximum brightness.
1608 */
1609 value = min(data->lightbar_max_brightness, value);
1610 ret = regmap_write(data->regmap, uniwill_led_channel_to_ac_reg[i], value);
1611 if (ret < 0)
1612 return ret;
1613
1614 ret = regmap_write(data->regmap, uniwill_led_channel_to_bat_reg[i], value);
1615 if (ret < 0)
1616 return ret;
1617
1618 data->led_mc_subled_info[i].intensity = value;
1619 data->led_mc_subled_info[i].channel = i;
1620 }
1621
1622 data->led_mc_cdev.subled_info = data->led_mc_subled_info;
1623 data->led_mc_cdev.num_colors = LED_CHANNELS;
1624
1625 return devm_led_classdev_multicolor_register_ext(data->dev, &data->led_mc_cdev,
1626 &init_data);
1627 }
1628
uniwill_notify_kbd_led(struct uniwill_data * data,int brightness)1629 static int uniwill_notify_kbd_led(struct uniwill_data *data, int brightness)
1630 {
1631 struct led_classdev *led_cdev;
1632 int ret;
1633
1634 if (data->kbd_led_single_color)
1635 led_cdev = &data->kbd_led_cdev;
1636 else
1637 led_cdev = &data->kbd_led_mc_cdev.led_cdev;
1638
1639 guard(mutex)(&led_cdev->led_access);
1640
1641 /* Sync the LED brightness with the actual hardware state */
1642 ret = led_update_brightness(led_cdev);
1643 if (ret < 0)
1644 return ret;
1645
1646 led_classdev_notify_brightness_hw_changed(led_cdev, brightness);
1647
1648 return 0;
1649 }
1650
1651 #define KBD_LED_MASK (KBD_BRIGHTNESS_MASK | KBD_APPLY | KBD_POWER_OFF)
1652
uniwill_kbd_led_write_brightness(struct uniwill_data * data,int brightness)1653 static int uniwill_kbd_led_write_brightness(struct uniwill_data *data, int brightness)
1654 {
1655 /* KBD_POWER_OFF is always implicitly cleared */
1656 unsigned int regval = FIELD_PREP(KBD_BRIGHTNESS_MASK, brightness) | KBD_APPLY;
1657
1658 /* We must ensure that the "apply" bit is always written */
1659 return regmap_write_bits(data->regmap, EC_ADDR_KBD_STATUS, KBD_LED_MASK, regval);
1660 }
1661
uniwill_kbd_led_read_brightness(struct uniwill_data * data)1662 static int uniwill_kbd_led_read_brightness(struct uniwill_data *data)
1663 {
1664 unsigned int regval;
1665 int ret;
1666
1667 ret = regmap_read(data->regmap, EC_ADDR_KBD_STATUS, ®val);
1668 if (ret < 0)
1669 return ret;
1670
1671 return min(FIELD_GET(KBD_BRIGHTNESS_MASK, regval), data->kbd_led_max_brightness);
1672 }
1673
uniwill_kbd_led_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)1674 static int uniwill_kbd_led_brightness_set(struct led_classdev *led_cdev,
1675 enum led_brightness brightness)
1676 {
1677 struct uniwill_data *data = container_of(led_cdev, struct uniwill_data, kbd_led_cdev);
1678
1679 return uniwill_kbd_led_write_brightness(data, brightness);
1680 }
1681
uniwill_kbd_led_brightness_get(struct led_classdev * led_cdev)1682 static enum led_brightness uniwill_kbd_led_brightness_get(struct led_classdev *led_cdev)
1683 {
1684 struct uniwill_data *data = container_of(led_cdev, struct uniwill_data, kbd_led_cdev);
1685
1686 return uniwill_kbd_led_read_brightness(data);
1687 }
1688
1689 static const unsigned int uniwill_kbd_led_channel_to_reg[KBD_LED_CHANNELS] = {
1690 EC_ADDR_RGB_RED,
1691 EC_ADDR_RGB_GREEN,
1692 EC_ADDR_RGB_BLUE,
1693 };
1694
uniwill_kbd_led_mc_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)1695 static int uniwill_kbd_led_mc_brightness_set(struct led_classdev *led_cdev,
1696 enum led_brightness brightness)
1697 {
1698 struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev);
1699 struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, kbd_led_mc_cdev);
1700 unsigned int min_intensity = 0;
1701 unsigned int regval;
1702 int ret;
1703
1704 guard(mutex)(&data->kbd_rgb_led_lock);
1705
1706 /*
1707 * The EC interprets a RGB value of 0x000000 as a command to restore
1708 * the device-specfic default RGB value. Work around this by writing
1709 * a RGB value of 0x010101 (faint white) instead.
1710 */
1711 if (data->kbd_led_mc_subled_info[0].intensity == 0 &&
1712 data->kbd_led_mc_subled_info[1].intensity == 0 &&
1713 data->kbd_led_mc_subled_info[2].intensity == 0)
1714 min_intensity = 1;
1715
1716 for (int i = 0; i < KBD_LED_CHANNELS; i++) {
1717 regval = max(data->kbd_led_mc_subled_info[i].intensity, min_intensity);
1718 ret = regmap_write(data->regmap, uniwill_kbd_led_channel_to_reg[i], regval);
1719 if (ret < 0)
1720 return ret;
1721 }
1722
1723 ret = regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, RGB_APPLY_COLOR, RGB_APPLY_COLOR);
1724 if (ret < 0)
1725 return ret;
1726
1727 return uniwill_kbd_led_write_brightness(data, brightness);
1728 }
1729
uniwill_kbd_led_mc_brightness_get(struct led_classdev * led_cdev)1730 static enum led_brightness uniwill_kbd_led_mc_brightness_get(struct led_classdev *led_cdev)
1731 {
1732 struct led_classdev_mc *led_mc_cdev = lcdev_to_mccdev(led_cdev);
1733 struct uniwill_data *data = container_of(led_mc_cdev, struct uniwill_data, kbd_led_mc_cdev);
1734
1735 return uniwill_kbd_led_read_brightness(data);
1736 }
1737
uniwill_white_kbd_led_init(struct uniwill_data * data)1738 static int uniwill_white_kbd_led_init(struct uniwill_data *data)
1739 {
1740 struct led_init_data init_data = {
1741 .default_label = "white:" LED_FUNCTION_KBD_BACKLIGHT,
1742 .devicename = DRIVER_NAME,
1743 .devname_mandatory = true,
1744 };
1745
1746 data->kbd_led_cdev.max_brightness = data->kbd_led_max_brightness;
1747 data->kbd_led_cdev.color = LED_COLOR_ID_WHITE;
1748 data->kbd_led_cdev.flags = LED_BRIGHT_HW_CHANGED | LED_REJECT_NAME_CONFLICT;
1749 data->kbd_led_cdev.brightness_set_blocking = uniwill_kbd_led_brightness_set;
1750 data->kbd_led_cdev.brightness_get = uniwill_kbd_led_brightness_get;
1751
1752 return devm_led_classdev_register_ext(data->dev, &data->kbd_led_cdev, &init_data);
1753 }
1754
uniwill_rgb_kbd_led_init(struct uniwill_data * data)1755 static int uniwill_rgb_kbd_led_init(struct uniwill_data *data)
1756 {
1757 unsigned int color_indices[KBD_LED_CHANNELS] = {
1758 LED_COLOR_ID_RED,
1759 LED_COLOR_ID_GREEN,
1760 LED_COLOR_ID_BLUE,
1761 };
1762 struct led_init_data init_data = {
1763 .default_label = "multicolor:" LED_FUNCTION_KBD_BACKLIGHT,
1764 .devicename = DRIVER_NAME,
1765 .devname_mandatory = true,
1766 };
1767 bool intensity_all_zeros = true;
1768 bool needs_trigger = false;
1769 unsigned int regval;
1770 int ret;
1771
1772 for (int i = 0; i < KBD_LED_CHANNELS; i++) {
1773 data->kbd_led_mc_subled_info[i].color_index = color_indices[i];
1774
1775 ret = regmap_read(data->regmap, uniwill_kbd_led_channel_to_reg[i], ®val);
1776 if (ret < 0)
1777 return ret;
1778
1779 /*
1780 * Make sure that the initial intensity value is not greater than
1781 * the maximum intensity.
1782 */
1783 if (regval > KBD_LED_MAX_INTENSITY) {
1784 regval = KBD_LED_MAX_INTENSITY;
1785 ret = regmap_write(data->regmap, uniwill_kbd_led_channel_to_reg[i], regval);
1786 if (ret < 0)
1787 return ret;
1788
1789 needs_trigger = true;
1790 }
1791
1792 if (regval)
1793 intensity_all_zeros = false;
1794
1795 data->kbd_led_mc_subled_info[i].intensity = regval;
1796 data->kbd_led_mc_subled_info[i].max_intensity = KBD_LED_MAX_INTENSITY;
1797 data->kbd_led_mc_subled_info[i].channel = i;
1798 }
1799
1800 /* See uniwill_kbd_led_mc_brightness_set() for an explaination. */
1801 if (intensity_all_zeros) {
1802 for (int i = 0; i < KBD_LED_CHANNELS; i++) {
1803 data->kbd_led_mc_subled_info[i].intensity = 1;
1804 ret = regmap_write(data->regmap, uniwill_kbd_led_channel_to_reg[i], 1);
1805 if (ret < 0)
1806 return ret;
1807 }
1808
1809 needs_trigger = true;
1810 }
1811
1812 if (needs_trigger) {
1813 ret = regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, RGB_APPLY_COLOR,
1814 RGB_APPLY_COLOR);
1815 if (ret < 0)
1816 return ret;
1817 }
1818
1819 ret = devm_mutex_init(data->dev, &data->kbd_rgb_led_lock);
1820 if (ret < 0)
1821 return ret;
1822
1823 data->kbd_led_mc_cdev.led_cdev.max_brightness = data->kbd_led_max_brightness;
1824 data->kbd_led_mc_cdev.led_cdev.color = LED_COLOR_ID_MULTI;
1825 data->kbd_led_mc_cdev.led_cdev.flags = LED_BRIGHT_HW_CHANGED | LED_REJECT_NAME_CONFLICT;
1826 data->kbd_led_mc_cdev.led_cdev.brightness_set_blocking = uniwill_kbd_led_mc_brightness_set;
1827 data->kbd_led_mc_cdev.led_cdev.brightness_get = uniwill_kbd_led_mc_brightness_get;
1828 data->kbd_led_mc_cdev.subled_info = data->kbd_led_mc_subled_info;
1829 data->kbd_led_mc_cdev.num_colors = KBD_LED_CHANNELS;
1830
1831 return devm_led_classdev_multicolor_register_ext(data->dev, &data->kbd_led_mc_cdev,
1832 &init_data);
1833 }
1834
uniwill_kbd_led_init(struct uniwill_data * data)1835 static int uniwill_kbd_led_init(struct uniwill_data *data)
1836 {
1837 unsigned int regval;
1838 int ret;
1839
1840 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
1841 return 0;
1842
1843 ret = regmap_read(data->regmap, EC_ADDR_SUPPORT_2, ®val);
1844 if (ret < 0)
1845 return ret;
1846
1847 if (!(regval & CHINA_MODE)) {
1848 ret = regmap_set_bits(data->regmap, EC_ADDR_BIOS_OEM_2, ENABLE_CHINA_MODE);
1849 if (ret < 0)
1850 return ret;
1851 }
1852
1853 ret = regmap_read(data->regmap, EC_ADDR_KBD_STATUS, ®val);
1854 if (ret < 0)
1855 return ret;
1856
1857 regval |= KBD_APPLY;
1858 regval &= ~KBD_POWER_OFF;
1859 ret = regmap_write(data->regmap, EC_ADDR_KBD_STATUS, regval);
1860 if (ret < 0)
1861 return ret;
1862
1863 if (data->kbd_led_single_color)
1864 return uniwill_white_kbd_led_init(data);
1865
1866 return uniwill_rgb_kbd_led_init(data);
1867 }
1868
uniwill_sanitize_battery_threshold(unsigned int value)1869 static unsigned int uniwill_sanitize_battery_threshold(unsigned int value)
1870 {
1871 /* 0 means "charging threshold not active" */
1872 if (!value)
1873 return 100;
1874
1875 /* Guard against invalid values */
1876 return min(value, 100);
1877 }
1878
uniwill_read_charge_type(struct uniwill_data * data,enum power_supply_charge_type * type)1879 static int uniwill_read_charge_type(struct uniwill_data *data, enum power_supply_charge_type *type)
1880 {
1881 unsigned int value;
1882 int ret;
1883
1884 ret = regmap_read(data->regmap, EC_ADDR_OEM_4, &value);
1885 if (ret < 0)
1886 return ret;
1887
1888 switch (FIELD_GET(CHARGING_PROFILE_MASK, value)) {
1889 case CHARGING_PROFILE_HIGH_CAPACITY:
1890 *type = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
1891 return 0;
1892 case CHARGING_PROFILE_BALANCED:
1893 *type = POWER_SUPPLY_CHARGE_TYPE_LONGLIFE;
1894 return 0;
1895 case CHARGING_PROFILE_STATIONARY:
1896 *type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
1897 return 0;
1898 default:
1899 return -EPROTO;
1900 }
1901 }
1902
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)1903 static int uniwill_get_property(struct power_supply *psy, const struct power_supply_ext *ext,
1904 void *drvdata, enum power_supply_property psp,
1905 union power_supply_propval *val)
1906 {
1907 struct uniwill_data *data = drvdata;
1908 union power_supply_propval prop;
1909 unsigned int regval;
1910 int ret;
1911
1912 switch (psp) {
1913 case POWER_SUPPLY_PROP_CHARGE_TYPES:
1914 /*
1915 * We need to use the cached value here because the charging mode
1916 * reported by the EC might temporarily change when a external power
1917 * source has been connected.
1918 */
1919 mutex_lock(&data->charge_type_lock);
1920 val->intval = data->last_charge_type;
1921 mutex_unlock(&data->charge_type_lock);
1922 return 0;
1923 case POWER_SUPPLY_PROP_HEALTH:
1924 ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_PRESENT, &prop);
1925 if (ret < 0)
1926 return ret;
1927
1928 if (!prop.intval) {
1929 val->intval = POWER_SUPPLY_HEALTH_NO_BATTERY;
1930 return 0;
1931 }
1932
1933 ret = power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_STATUS, &prop);
1934 if (ret < 0)
1935 return ret;
1936
1937 if (prop.intval == POWER_SUPPLY_STATUS_UNKNOWN) {
1938 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
1939 return 0;
1940 }
1941
1942 ret = regmap_read(data->regmap, EC_ADDR_BAT_ALERT, ®val);
1943 if (ret < 0)
1944 return ret;
1945
1946 if (regval) {
1947 /* Charging issue */
1948 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
1949 return 0;
1950 }
1951
1952 val->intval = POWER_SUPPLY_HEALTH_GOOD;
1953 return 0;
1954 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
1955 ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, ®val);
1956 if (ret < 0)
1957 return ret;
1958
1959 regval = FIELD_GET(CHARGE_CTRL_MASK, regval);
1960 val->intval = uniwill_sanitize_battery_threshold(regval);
1961 return 0;
1962 default:
1963 return -EINVAL;
1964 }
1965 }
1966
uniwill_write_charge_type(struct uniwill_data * data,enum power_supply_charge_type type)1967 static int uniwill_write_charge_type(struct uniwill_data *data, enum power_supply_charge_type type)
1968 {
1969 unsigned int value;
1970
1971 switch (type) {
1972 case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
1973 value = FIELD_PREP(CHARGING_PROFILE_MASK, CHARGING_PROFILE_STATIONARY);
1974 break;
1975 case POWER_SUPPLY_CHARGE_TYPE_STANDARD:
1976 value = FIELD_PREP(CHARGING_PROFILE_MASK, CHARGING_PROFILE_HIGH_CAPACITY);
1977 break;
1978 case POWER_SUPPLY_CHARGE_TYPE_LONGLIFE:
1979 value = FIELD_PREP(CHARGING_PROFILE_MASK, CHARGING_PROFILE_BALANCED);
1980 break;
1981 default:
1982 return -EINVAL;
1983 }
1984
1985 return regmap_update_bits(data->regmap, EC_ADDR_OEM_4, CHARGING_PROFILE_MASK, value);
1986 }
1987
uniwill_restore_charge_type(struct uniwill_data * data)1988 static int uniwill_restore_charge_type(struct uniwill_data *data)
1989 {
1990 guard(mutex)(&data->charge_type_lock);
1991
1992 return uniwill_write_charge_type(data, data->last_charge_type);
1993 }
1994
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)1995 static int uniwill_set_property(struct power_supply *psy, const struct power_supply_ext *ext,
1996 void *drvdata, enum power_supply_property psp,
1997 const union power_supply_propval *val)
1998 {
1999 struct uniwill_data *data = drvdata;
2000 int ret;
2001
2002 switch (psp) {
2003 case POWER_SUPPLY_PROP_CHARGE_TYPES:
2004 mutex_lock(&data->charge_type_lock);
2005
2006 ret = uniwill_write_charge_type(data, val->intval);
2007 if (ret >= 0)
2008 data->last_charge_type = val->intval;
2009
2010 mutex_unlock(&data->charge_type_lock);
2011
2012 return ret;
2013 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
2014 if (val->intval < 0 || val->intval > 100)
2015 return -EINVAL;
2016
2017 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
2018 max(val->intval, 1));
2019 default:
2020 return -EINVAL;
2021 }
2022 }
2023
uniwill_property_is_writeable(struct power_supply * psy,const struct power_supply_ext * ext,void * drvdata,enum power_supply_property psp)2024 static int uniwill_property_is_writeable(struct power_supply *psy,
2025 const struct power_supply_ext *ext, void *drvdata,
2026 enum power_supply_property psp)
2027 {
2028 switch (psp) {
2029 case POWER_SUPPLY_PROP_CHARGE_TYPES:
2030 case POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD:
2031 return true;
2032 default:
2033 return false;
2034 }
2035 }
2036
2037 static const enum power_supply_property uniwill_charge_limit_properties[] = {
2038 POWER_SUPPLY_PROP_HEALTH,
2039 POWER_SUPPLY_PROP_CHARGE_CONTROL_END_THRESHOLD,
2040 };
2041
2042 static const struct power_supply_ext uniwill_charge_limit_extension = {
2043 .name = DRIVER_NAME,
2044 .properties = uniwill_charge_limit_properties,
2045 .num_properties = ARRAY_SIZE(uniwill_charge_limit_properties),
2046 .get_property = uniwill_get_property,
2047 .set_property = uniwill_set_property,
2048 .property_is_writeable = uniwill_property_is_writeable,
2049 };
2050
2051 static const enum power_supply_property uniwill_charge_modes_properties[] = {
2052 POWER_SUPPLY_PROP_CHARGE_TYPES,
2053 POWER_SUPPLY_PROP_HEALTH,
2054 };
2055
2056 static const struct power_supply_ext uniwill_charge_modes_extension = {
2057 .name = DRIVER_NAME,
2058 .charge_types = BIT(POWER_SUPPLY_CHARGE_TYPE_TRICKLE) |
2059 BIT(POWER_SUPPLY_CHARGE_TYPE_STANDARD) |
2060 BIT(POWER_SUPPLY_CHARGE_TYPE_LONGLIFE),
2061 .properties = uniwill_charge_modes_properties,
2062 .num_properties = ARRAY_SIZE(uniwill_charge_modes_properties),
2063 .get_property = uniwill_get_property,
2064 .set_property = uniwill_set_property,
2065 .property_is_writeable = uniwill_property_is_writeable,
2066 };
2067
uniwill_add_battery(struct power_supply * battery,struct acpi_battery_hook * hook)2068 static int uniwill_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
2069 {
2070 struct uniwill_data *data = container_of(hook, struct uniwill_data, hook);
2071 struct uniwill_battery_entry *entry;
2072 int ret;
2073
2074 entry = kzalloc_obj(*entry);
2075 if (!entry)
2076 return -ENOMEM;
2077
2078 if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
2079 ret = power_supply_register_extension(battery, &uniwill_charge_limit_extension,
2080 data->dev, data);
2081 else
2082 ret = power_supply_register_extension(battery, &uniwill_charge_modes_extension,
2083 data->dev, data);
2084
2085 if (ret < 0) {
2086 kfree(entry);
2087 return ret;
2088 }
2089
2090 guard(mutex)(&data->battery_lock);
2091
2092 entry->battery = battery;
2093 list_add(&entry->head, &data->batteries);
2094
2095 return 0;
2096 }
2097
uniwill_remove_battery(struct power_supply * battery,struct acpi_battery_hook * hook)2098 static int uniwill_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
2099 {
2100 struct uniwill_data *data = container_of(hook, struct uniwill_data, hook);
2101 struct uniwill_battery_entry *entry, *tmp;
2102
2103 scoped_guard(mutex, &data->battery_lock) {
2104 list_for_each_entry_safe(entry, tmp, &data->batteries, head) {
2105 if (entry->battery == battery) {
2106 list_del(&entry->head);
2107 kfree(entry);
2108 break;
2109 }
2110 }
2111 }
2112
2113 if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
2114 power_supply_unregister_extension(battery, &uniwill_charge_limit_extension);
2115 else
2116 power_supply_unregister_extension(battery, &uniwill_charge_modes_extension);
2117
2118 return 0;
2119 }
2120
uniwill_battery_init(struct uniwill_data * data)2121 static int uniwill_battery_init(struct uniwill_data *data)
2122 {
2123 unsigned int value, threshold, sanitized;
2124 int ret;
2125
2126 if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT)) {
2127 ret = regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &value);
2128 if (ret < 0)
2129 return ret;
2130
2131 /*
2132 * The charge control threshold might be initialized with 0 by
2133 * the EC to signal that said threshold is uninitialized. We thus
2134 * need to replace this placeholder value with a valid one (100)
2135 * to signal that we want to take control of battery charging.
2136 * For the sake of completeness we also apply this to other
2137 * invalid threshold values.
2138 */
2139 threshold = FIELD_GET(CHARGE_CTRL_MASK, value);
2140 sanitized = uniwill_sanitize_battery_threshold(threshold);
2141 if (threshold != sanitized) {
2142 FIELD_MODIFY(CHARGE_CTRL_MASK, &value, sanitized);
2143 ret = regmap_write(data->regmap, EC_ADDR_CHARGE_CTRL, value);
2144 if (ret < 0)
2145 return ret;
2146 }
2147 } else if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_MODES)) {
2148 ret = devm_mutex_init(data->dev, &data->charge_type_lock);
2149 if (ret < 0)
2150 return ret;
2151
2152 ret = uniwill_read_charge_type(data, &data->last_charge_type);
2153 if (ret < 0)
2154 return ret;
2155 } else {
2156 return 0;
2157 }
2158
2159 ret = devm_mutex_init(data->dev, &data->battery_lock);
2160 if (ret < 0)
2161 return ret;
2162
2163 INIT_LIST_HEAD(&data->batteries);
2164 data->hook.name = "Uniwill Battery Extension";
2165 data->hook.add_battery = uniwill_add_battery;
2166 data->hook.remove_battery = uniwill_remove_battery;
2167
2168 return devm_battery_hook_register(data->dev, &data->hook);
2169 }
2170
uniwill_notifier_call(struct notifier_block * nb,unsigned long action,void * dummy)2171 static int uniwill_notifier_call(struct notifier_block *nb, unsigned long action, void *dummy)
2172 {
2173 struct uniwill_data *data = container_of(nb, struct uniwill_data, nb);
2174 struct uniwill_battery_entry *entry;
2175 int ret;
2176
2177 switch (action) {
2178 case UNIWILL_OSD_BATTERY_ALERT:
2179 if (!uniwill_device_supports_any(data,
2180 UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
2181 UNIWILL_FEATURE_BATTERY_CHARGE_MODES))
2182 return NOTIFY_DONE;
2183
2184 mutex_lock(&data->battery_lock);
2185 list_for_each_entry(entry, &data->batteries, head) {
2186 power_supply_changed(entry->battery);
2187 }
2188 mutex_unlock(&data->battery_lock);
2189
2190 return NOTIFY_OK;
2191 case UNIWILL_OSD_DC_ADAPTER_CHANGED:
2192 if (!uniwill_device_supports_any(data,
2193 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2194 UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
2195 return NOTIFY_DONE;
2196
2197 if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_MODES)) {
2198 ret = uniwill_restore_charge_type(data);
2199 if (ret < 0)
2200 return notifier_from_errno(ret);
2201 }
2202
2203 if (uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY)) {
2204 ret = usb_c_power_priority_restore(data);
2205 if (ret < 0)
2206 return notifier_from_errno(ret);
2207 }
2208
2209 return NOTIFY_OK;
2210 case UNIWILL_OSD_FN_LOCK:
2211 if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
2212 return NOTIFY_DONE;
2213
2214 sysfs_notify(&data->dev->kobj, NULL, "fn_lock");
2215
2216 return NOTIFY_OK;
2217 case UNIWILL_OSD_KB_LED_LEVEL0:
2218 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2219 return NOTIFY_DONE;
2220
2221 return notifier_from_errno(uniwill_notify_kbd_led(data, 0));
2222 case UNIWILL_OSD_KB_LED_LEVEL1:
2223 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2224 return NOTIFY_DONE;
2225
2226 return notifier_from_errno(uniwill_notify_kbd_led(data, 1));
2227 case UNIWILL_OSD_KB_LED_LEVEL2:
2228 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2229 return NOTIFY_DONE;
2230
2231 return notifier_from_errno(uniwill_notify_kbd_led(data, 2));
2232 case UNIWILL_OSD_KB_LED_LEVEL3:
2233 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2234 return NOTIFY_DONE;
2235
2236 return notifier_from_errno(uniwill_notify_kbd_led(data, 3));
2237 case UNIWILL_OSD_KB_LED_LEVEL4:
2238 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2239 return NOTIFY_DONE;
2240
2241 return notifier_from_errno(uniwill_notify_kbd_led(data, 4));
2242 default:
2243 mutex_lock(&data->input_lock);
2244 sparse_keymap_report_event(data->input_device, action, 1, true);
2245 mutex_unlock(&data->input_lock);
2246
2247 return NOTIFY_OK;
2248 }
2249 }
2250
uniwill_input_init(struct uniwill_data * data)2251 static int uniwill_input_init(struct uniwill_data *data)
2252 {
2253 int ret;
2254
2255 ret = devm_mutex_init(data->dev, &data->input_lock);
2256 if (ret < 0)
2257 return ret;
2258
2259 data->input_device = devm_input_allocate_device(data->dev);
2260 if (!data->input_device)
2261 return -ENOMEM;
2262
2263 ret = sparse_keymap_setup(data->input_device, uniwill_keymap, NULL);
2264 if (ret < 0)
2265 return ret;
2266
2267 data->input_device->name = "Uniwill WMI hotkeys";
2268 data->input_device->phys = "wmi/input0";
2269 data->input_device->id.bustype = BUS_HOST;
2270 ret = input_register_device(data->input_device);
2271 if (ret < 0)
2272 return ret;
2273
2274 data->nb.notifier_call = uniwill_notifier_call;
2275
2276 return devm_uniwill_wmi_register_notifier(data->dev, &data->nb);
2277 }
2278
uniwill_disable_manual_control(void * context)2279 static void uniwill_disable_manual_control(void *context)
2280 {
2281 struct uniwill_data *data = context;
2282
2283 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
2284 }
2285
uniwill_ec_init(struct uniwill_data * data)2286 static int uniwill_ec_init(struct uniwill_data *data)
2287 {
2288 unsigned int value;
2289 int ret;
2290
2291 ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
2292 if (ret < 0)
2293 return ret;
2294
2295 data->project_id = value;
2296 dev_dbg(data->dev, "Project ID: %u\n", value);
2297
2298 ret = regmap_set_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
2299 if (ret < 0)
2300 return ret;
2301
2302 return devm_add_action_or_reset(data->dev, uniwill_disable_manual_control, data);
2303 }
2304
uniwill_probe(struct platform_device * pdev)2305 static int uniwill_probe(struct platform_device *pdev)
2306 {
2307 struct uniwill_data *data;
2308 struct regmap *regmap;
2309 acpi_handle handle;
2310 int ret;
2311
2312 handle = ACPI_HANDLE(&pdev->dev);
2313 if (!handle)
2314 return -ENODEV;
2315
2316 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
2317 if (!data)
2318 return -ENOMEM;
2319
2320 data->dev = &pdev->dev;
2321 data->handle = handle;
2322 platform_set_drvdata(pdev, data);
2323
2324 regmap = devm_regmap_init(&pdev->dev, &uniwill_ec_bus, data, &uniwill_ec_config);
2325 if (IS_ERR(regmap))
2326 return PTR_ERR(regmap);
2327
2328 data->regmap = regmap;
2329
2330 ret = devm_mutex_init(&pdev->dev, &data->super_key_lock);
2331 if (ret < 0)
2332 return ret;
2333
2334 ret = uniwill_ec_init(data);
2335 if (ret < 0)
2336 return ret;
2337
2338 data->features = device_descriptor.features;
2339 data->kbd_led_single_color = device_descriptor.kbd_led_single_color;
2340 data->kbd_led_max_brightness = device_descriptor.kbd_led_max_brightness;
2341 data->lightbar_max_brightness = device_descriptor.lightbar_max_brightness;
2342
2343 /*
2344 * Some devices might need to perform some device-specific initialization steps
2345 * before the supported features are initialized. Because of this we have to call
2346 * this callback just after the EC itself was initialized.
2347 */
2348 if (device_descriptor.probe) {
2349 ret = device_descriptor.probe(data);
2350 if (ret < 0)
2351 return ret;
2352 }
2353
2354 ret = uniwill_battery_init(data);
2355 if (ret < 0)
2356 return ret;
2357
2358 ret = uniwill_led_init(data);
2359 if (ret < 0)
2360 return ret;
2361
2362 ret = uniwill_kbd_led_init(data);
2363 if (ret < 0)
2364 return ret;
2365
2366 ret = uniwill_hwmon_init(data);
2367 if (ret < 0)
2368 return ret;
2369
2370 ret = uniwill_nvidia_ctgp_init(data);
2371 if (ret < 0)
2372 return ret;
2373
2374 ret = usb_c_power_priority_init(data);
2375 if (ret < 0)
2376 return ret;
2377
2378 return uniwill_input_init(data);
2379 }
2380
uniwill_shutdown(struct platform_device * pdev)2381 static void uniwill_shutdown(struct platform_device *pdev)
2382 {
2383 struct uniwill_data *data = platform_get_drvdata(pdev);
2384
2385 regmap_clear_bits(data->regmap, EC_ADDR_AP_OEM, ENABLE_MANUAL_CTRL);
2386 }
2387
uniwill_suspend_fn_lock(struct uniwill_data * data)2388 static int uniwill_suspend_fn_lock(struct uniwill_data *data)
2389 {
2390 if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
2391 return 0;
2392
2393 /*
2394 * EC_ADDR_BIOS_OEM is marked as volatile, so we have to restore it
2395 * ourselves.
2396 */
2397 return uniwill_read_fn_lock(data, &data->last_fn_lock_state);
2398 }
2399
uniwill_suspend_super_key(struct uniwill_data * data)2400 static int uniwill_suspend_super_key(struct uniwill_data *data)
2401 {
2402 if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
2403 return 0;
2404
2405 /*
2406 * EC_ADDR_SWITCH_STATUS is marked as volatile, so we have to restore it
2407 * ourselves.
2408 */
2409 return uniwill_read_super_key_enable(data, &data->last_super_key_enable_state);
2410 }
2411
uniwill_suspend_touchpad_toggle(struct uniwill_data * data)2412 static int uniwill_suspend_touchpad_toggle(struct uniwill_data *data)
2413 {
2414 if (!uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
2415 return 0;
2416
2417 /*
2418 * EC_ADDR_OEM_4 is marked as volatile, so we have to restore it
2419 * ourselves.
2420 */
2421 return uniwill_read_touchpad_toggle_enable(data, &data->last_touchpad_toggle_enable_state);
2422 }
2423
uniwill_suspend_battery(struct uniwill_data * data)2424 static int uniwill_suspend_battery(struct uniwill_data *data)
2425 {
2426 if (!uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
2427 return 0;
2428
2429 /*
2430 * Save the current charge limit in order to restore it during resume.
2431 * We cannot use the regmap code for that since this register needs to
2432 * be declared as volatile due to CHARGE_CTRL_REACHED.
2433 */
2434 return regmap_read(data->regmap, EC_ADDR_CHARGE_CTRL, &data->last_charge_ctrl);
2435 }
2436
uniwill_suspend_kbd_led(struct uniwill_data * data)2437 static int uniwill_suspend_kbd_led(struct uniwill_data *data)
2438 {
2439 unsigned int regval;
2440 int ret;
2441
2442 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2443 return 0;
2444
2445 ret = regmap_read(data->regmap, EC_ADDR_KBD_STATUS, ®val);
2446 if (ret < 0)
2447 return ret;
2448
2449 /*
2450 * Save the current keyboard backlight settings in order to restore them
2451 * during resume. We cannot use the regmap code for that since this register
2452 * needs to be declared as volatile because the brightness can be changed
2453 * by the EC.
2454 */
2455 data->last_kbd_status = regval;
2456 FIELD_MODIFY(KBD_BRIGHTNESS_MASK, ®val, 0);
2457 regval |= KBD_APPLY | KBD_POWER_OFF;
2458
2459 return regmap_write(data->regmap, EC_ADDR_KBD_STATUS, regval);
2460 }
2461
uniwill_suspend_usb_powershare(struct uniwill_data * data)2462 static int uniwill_suspend_usb_powershare(struct uniwill_data *data)
2463 {
2464 if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_POWERSHARE))
2465 return 0;
2466
2467 /*
2468 * EC_ADDR_TRIGGER is marked as volatile, so we have to restore it
2469 * ourselves.
2470 */
2471 return uniwill_read_usb_powershare_high(data, &data->last_usb_powershare_high_state);
2472 }
2473
uniwill_suspend_nvidia_ctgp(struct uniwill_data * data)2474 static int uniwill_suspend_nvidia_ctgp(struct uniwill_data *data)
2475 {
2476 if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
2477 return 0;
2478
2479 return regmap_clear_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
2480 CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
2481 }
2482
uniwill_suspend(struct device * dev)2483 static int uniwill_suspend(struct device *dev)
2484 {
2485 struct uniwill_data *data = dev_get_drvdata(dev);
2486 int ret;
2487
2488 ret = uniwill_suspend_fn_lock(data);
2489 if (ret < 0)
2490 return ret;
2491
2492 ret = uniwill_suspend_super_key(data);
2493 if (ret < 0)
2494 return ret;
2495
2496 ret = uniwill_suspend_touchpad_toggle(data);
2497 if (ret < 0)
2498 return ret;
2499
2500 ret = uniwill_suspend_battery(data);
2501 if (ret < 0)
2502 return ret;
2503
2504 ret = uniwill_suspend_kbd_led(data);
2505 if (ret < 0)
2506 return ret;
2507
2508 ret = uniwill_suspend_usb_powershare(data);
2509 if (ret < 0)
2510 return ret;
2511
2512 ret = uniwill_suspend_nvidia_ctgp(data);
2513 if (ret < 0)
2514 return ret;
2515
2516 regcache_cache_only(data->regmap, true);
2517 regcache_mark_dirty(data->regmap);
2518
2519 return 0;
2520 }
2521
uniwill_resume_fn_lock(struct uniwill_data * data)2522 static int uniwill_resume_fn_lock(struct uniwill_data *data)
2523 {
2524 if (!uniwill_device_supports(data, UNIWILL_FEATURE_FN_LOCK))
2525 return 0;
2526
2527 return uniwill_write_fn_lock(data, data->last_fn_lock_state);
2528 }
2529
uniwill_resume_super_key(struct uniwill_data * data)2530 static int uniwill_resume_super_key(struct uniwill_data *data)
2531 {
2532 if (!uniwill_device_supports(data, UNIWILL_FEATURE_SUPER_KEY))
2533 return 0;
2534
2535 return uniwill_write_super_key_enable(data, data->last_super_key_enable_state);
2536 }
2537
uniwill_resume_touchpad_toggle(struct uniwill_data * data)2538 static int uniwill_resume_touchpad_toggle(struct uniwill_data *data)
2539 {
2540 if (!uniwill_device_supports(data, UNIWILL_FEATURE_TOUCHPAD_TOGGLE))
2541 return 0;
2542
2543 return uniwill_write_touchpad_toggle_enable(data, data->last_touchpad_toggle_enable_state);
2544 }
2545
uniwill_resume_battery(struct uniwill_data * data)2546 static int uniwill_resume_battery(struct uniwill_data *data)
2547 {
2548 if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_MODES))
2549 return uniwill_restore_charge_type(data);
2550
2551 if (uniwill_device_supports(data, UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT))
2552 return regmap_update_bits(data->regmap, EC_ADDR_CHARGE_CTRL, CHARGE_CTRL_MASK,
2553 data->last_charge_ctrl);
2554
2555 return 0;
2556 }
2557
uniwill_resume_kbd_led(struct uniwill_data * data)2558 static int uniwill_resume_kbd_led(struct uniwill_data *data)
2559 {
2560 int ret;
2561
2562 if (!uniwill_device_supports(data, UNIWILL_FEATURE_KEYBOARD_BACKLIGHT))
2563 return 0;
2564
2565 ret = regmap_write(data->regmap, EC_ADDR_KBD_STATUS, data->last_kbd_status | KBD_APPLY);
2566 if (ret < 0)
2567 return ret;
2568
2569 if (data->kbd_led_single_color)
2570 return 0;
2571
2572 return regmap_write_bits(data->regmap, EC_ADDR_TRIGGER, RGB_APPLY_COLOR, RGB_APPLY_COLOR);
2573 }
2574
uniwill_resume_usb_powershare(struct uniwill_data * data)2575 static int uniwill_resume_usb_powershare(struct uniwill_data *data)
2576 {
2577 if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_POWERSHARE))
2578 return 0;
2579
2580 return uniwill_write_usb_powershare_high(data, data->last_usb_powershare_high_state);
2581 }
2582
uniwill_resume_nvidia_ctgp(struct uniwill_data * data)2583 static int uniwill_resume_nvidia_ctgp(struct uniwill_data *data)
2584 {
2585 if (!uniwill_device_supports(data, UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL))
2586 return 0;
2587
2588 return regmap_set_bits(data->regmap, EC_ADDR_CTGP_DB_CTRL,
2589 CTGP_DB_DB_ENABLE | CTGP_DB_CTGP_ENABLE);
2590 }
2591
uniwill_resume_usb_c_power_priority(struct uniwill_data * data)2592 static int uniwill_resume_usb_c_power_priority(struct uniwill_data *data)
2593 {
2594 if (!uniwill_device_supports(data, UNIWILL_FEATURE_USB_C_POWER_PRIORITY))
2595 return 0;
2596
2597 return usb_c_power_priority_restore(data);
2598 }
2599
uniwill_resume(struct device * dev)2600 static int uniwill_resume(struct device *dev)
2601 {
2602 struct uniwill_data *data = dev_get_drvdata(dev);
2603 int ret;
2604
2605 regcache_cache_only(data->regmap, false);
2606
2607 ret = regcache_sync(data->regmap);
2608 if (ret < 0)
2609 return ret;
2610
2611 ret = uniwill_resume_fn_lock(data);
2612 if (ret < 0)
2613 return ret;
2614
2615 ret = uniwill_resume_super_key(data);
2616 if (ret < 0)
2617 return ret;
2618
2619 ret = uniwill_resume_touchpad_toggle(data);
2620 if (ret < 0)
2621 return ret;
2622
2623 ret = uniwill_resume_battery(data);
2624 if (ret < 0)
2625 return ret;
2626
2627 ret = uniwill_resume_kbd_led(data);
2628 if (ret < 0)
2629 return ret;
2630
2631 ret = uniwill_resume_usb_powershare(data);
2632 if (ret < 0)
2633 return ret;
2634
2635 ret = uniwill_resume_nvidia_ctgp(data);
2636 if (ret < 0)
2637 return ret;
2638
2639 return uniwill_resume_usb_c_power_priority(data);
2640 }
2641
2642 static DEFINE_SIMPLE_DEV_PM_OPS(uniwill_pm_ops, uniwill_suspend, uniwill_resume);
2643
2644 /*
2645 * We only use the DMI table for auoloading because the ACPI device itself
2646 * does not guarantee that the underlying EC implementation is supported.
2647 */
2648 static const struct acpi_device_id uniwill_id_table[] = {
2649 { "INOU0000" },
2650 { },
2651 };
2652
2653 static struct platform_driver uniwill_driver = {
2654 .driver = {
2655 .name = DRIVER_NAME,
2656 .dev_groups = uniwill_groups,
2657 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
2658 .acpi_match_table = uniwill_id_table,
2659 .pm = pm_sleep_ptr(&uniwill_pm_ops),
2660 },
2661 .probe = uniwill_probe,
2662 .shutdown = uniwill_shutdown,
2663 };
2664
2665 static struct uniwill_device_descriptor machenike_l16p_descriptor __initdata = {
2666 .features = UNIWILL_FEATURE_FN_LOCK |
2667 UNIWILL_FEATURE_SUPER_KEY |
2668 UNIWILL_FEATURE_CPU_TEMP |
2669 UNIWILL_FEATURE_GPU_TEMP |
2670 UNIWILL_FEATURE_PRIMARY_FAN |
2671 UNIWILL_FEATURE_SECONDARY_FAN |
2672 UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL |
2673 UNIWILL_FEATURE_KEYBOARD_BACKLIGHT |
2674 UNIWILL_FEATURE_AC_AUTO_BOOT |
2675 UNIWILL_FEATURE_USB_POWERSHARE,
2676 .kbd_led_single_color = false,
2677 .kbd_led_max_brightness = 4,
2678 };
2679
2680 static struct uniwill_device_descriptor lapqc71a_lapqc71b_descriptor __initdata = {
2681 .features = UNIWILL_FEATURE_SUPER_KEY |
2682 UNIWILL_FEATURE_LIGHTBAR |
2683 UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
2684 UNIWILL_FEATURE_CPU_TEMP |
2685 UNIWILL_FEATURE_GPU_TEMP |
2686 UNIWILL_FEATURE_PRIMARY_FAN |
2687 UNIWILL_FEATURE_SECONDARY_FAN,
2688 .lightbar_max_brightness = 36,
2689 };
2690
2691 static struct uniwill_device_descriptor lapac71h_descriptor __initdata = {
2692 .features = UNIWILL_FEATURE_FN_LOCK |
2693 UNIWILL_FEATURE_SUPER_KEY |
2694 UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
2695 UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
2696 UNIWILL_FEATURE_CPU_TEMP |
2697 UNIWILL_FEATURE_GPU_TEMP |
2698 UNIWILL_FEATURE_PRIMARY_FAN |
2699 UNIWILL_FEATURE_SECONDARY_FAN,
2700 };
2701
2702 static struct uniwill_device_descriptor lapkc71f_descriptor __initdata = {
2703 .features = UNIWILL_FEATURE_FN_LOCK |
2704 UNIWILL_FEATURE_SUPER_KEY |
2705 UNIWILL_FEATURE_TOUCHPAD_TOGGLE |
2706 UNIWILL_FEATURE_LIGHTBAR |
2707 UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT |
2708 UNIWILL_FEATURE_CPU_TEMP |
2709 UNIWILL_FEATURE_GPU_TEMP |
2710 UNIWILL_FEATURE_PRIMARY_FAN |
2711 UNIWILL_FEATURE_SECONDARY_FAN,
2712 .lightbar_max_brightness = 200,
2713 };
2714
2715 /*
2716 * The featuresets below reflect somewhat chronological changes:
2717 * 1 -> 2: UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL is added to the EC firmware.
2718 * 2 -> 3: UNIWILL_FEATURE_USB_C_POWER_PRIORITY is removed from the EC firmware.
2719 * Some devices might divert from this timeline.
2720 */
2721
2722 static struct uniwill_device_descriptor tux_featureset_1_descriptor __initdata = {
2723 .features = UNIWILL_FEATURE_FN_LOCK |
2724 UNIWILL_FEATURE_SUPER_KEY |
2725 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2726 UNIWILL_FEATURE_CPU_TEMP |
2727 UNIWILL_FEATURE_PRIMARY_FAN |
2728 UNIWILL_FEATURE_SECONDARY_FAN |
2729 UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
2730 };
2731
2732 static struct uniwill_device_descriptor tux_featureset_1_nvidia_descriptor __initdata = {
2733 .features = UNIWILL_FEATURE_FN_LOCK |
2734 UNIWILL_FEATURE_SUPER_KEY |
2735 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2736 UNIWILL_FEATURE_CPU_TEMP |
2737 UNIWILL_FEATURE_GPU_TEMP |
2738 UNIWILL_FEATURE_PRIMARY_FAN |
2739 UNIWILL_FEATURE_SECONDARY_FAN |
2740 UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
2741 };
2742
2743 static struct uniwill_device_descriptor tux_featureset_2_nvidia_descriptor __initdata = {
2744 .features = UNIWILL_FEATURE_FN_LOCK |
2745 UNIWILL_FEATURE_SUPER_KEY |
2746 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2747 UNIWILL_FEATURE_CPU_TEMP |
2748 UNIWILL_FEATURE_GPU_TEMP |
2749 UNIWILL_FEATURE_PRIMARY_FAN |
2750 UNIWILL_FEATURE_SECONDARY_FAN |
2751 UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL |
2752 UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
2753 };
2754
2755 static struct uniwill_device_descriptor tux_featureset_3_nvidia_descriptor __initdata = {
2756 .features = UNIWILL_FEATURE_FN_LOCK |
2757 UNIWILL_FEATURE_SUPER_KEY |
2758 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2759 UNIWILL_FEATURE_CPU_TEMP |
2760 UNIWILL_FEATURE_GPU_TEMP |
2761 UNIWILL_FEATURE_PRIMARY_FAN |
2762 UNIWILL_FEATURE_SECONDARY_FAN |
2763 UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL,
2764 };
2765
2766 static struct uniwill_device_descriptor tux_featureset_4_descriptor __initdata = {
2767 .features = UNIWILL_FEATURE_FN_LOCK |
2768 UNIWILL_FEATURE_SUPER_KEY |
2769 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2770 UNIWILL_FEATURE_CPU_TEMP |
2771 UNIWILL_FEATURE_PRIMARY_FAN |
2772 UNIWILL_FEATURE_SECONDARY_FAN |
2773 UNIWILL_FEATURE_AC_AUTO_BOOT |
2774 UNIWILL_FEATURE_USB_POWERSHARE,
2775 };
2776
2777 static struct uniwill_device_descriptor tux_featureset_4_nvidia_descriptor __initdata = {
2778 .features = UNIWILL_FEATURE_FN_LOCK |
2779 UNIWILL_FEATURE_SUPER_KEY |
2780 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2781 UNIWILL_FEATURE_CPU_TEMP |
2782 UNIWILL_FEATURE_GPU_TEMP |
2783 UNIWILL_FEATURE_PRIMARY_FAN |
2784 UNIWILL_FEATURE_SECONDARY_FAN |
2785 UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL |
2786 UNIWILL_FEATURE_AC_AUTO_BOOT |
2787 UNIWILL_FEATURE_USB_POWERSHARE,
2788 };
2789
phxtxx1_probe(struct uniwill_data * data)2790 static int phxtxx1_probe(struct uniwill_data *data)
2791 {
2792 unsigned int value;
2793 int ret;
2794
2795 ret = regmap_read(data->regmap, EC_ADDR_PROJECT_ID, &value);
2796 if (ret < 0)
2797 return ret;
2798
2799 if (value == PROJECT_ID_PH4TRX1 || value == PROJECT_ID_PH6TRX1)
2800 data->features |= UNIWILL_FEATURE_SECONDARY_FAN;
2801
2802 return 0;
2803 };
2804
2805 static struct uniwill_device_descriptor phxtxx1_descriptor __initdata = {
2806 .features = UNIWILL_FEATURE_FN_LOCK |
2807 UNIWILL_FEATURE_SUPER_KEY |
2808 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2809 UNIWILL_FEATURE_CPU_TEMP |
2810 UNIWILL_FEATURE_PRIMARY_FAN |
2811 UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
2812 .probe = phxtxx1_probe,
2813 };
2814
phxarx1_phxaqf1_probe(struct uniwill_data * data)2815 static int phxarx1_phxaqf1_probe(struct uniwill_data *data)
2816 {
2817 unsigned int value;
2818 int ret;
2819
2820 ret = regmap_read(data->regmap, EC_ADDR_SYSTEM_ID, &value);
2821 if (ret < 0)
2822 return ret;
2823
2824 if (value & HAS_GPU)
2825 data->features |= UNIWILL_FEATURE_GPU_TEMP |
2826 UNIWILL_FEATURE_NVIDIA_CTGP_CONTROL;
2827
2828 return 0;
2829 };
2830
2831 static struct uniwill_device_descriptor phxarx1_phxaqf1_descriptor __initdata = {
2832 .features = UNIWILL_FEATURE_FN_LOCK |
2833 UNIWILL_FEATURE_SUPER_KEY |
2834 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2835 UNIWILL_FEATURE_CPU_TEMP |
2836 UNIWILL_FEATURE_PRIMARY_FAN |
2837 UNIWILL_FEATURE_SECONDARY_FAN |
2838 UNIWILL_FEATURE_USB_C_POWER_PRIORITY,
2839 .probe = phxarx1_phxaqf1_probe,
2840 };
2841
2842 static struct uniwill_device_descriptor pf5pu1g_descriptor __initdata = {
2843 .features = UNIWILL_FEATURE_FN_LOCK |
2844 UNIWILL_FEATURE_SUPER_KEY |
2845 UNIWILL_FEATURE_CPU_TEMP |
2846 UNIWILL_FEATURE_PRIMARY_FAN,
2847 };
2848
2849 static struct uniwill_device_descriptor x4sp4nal_descriptor __initdata = {
2850 .features = UNIWILL_FEATURE_FN_LOCK |
2851 UNIWILL_FEATURE_SUPER_KEY |
2852 UNIWILL_FEATURE_BATTERY_CHARGE_MODES |
2853 UNIWILL_FEATURE_CPU_TEMP |
2854 UNIWILL_FEATURE_PRIMARY_FAN |
2855 UNIWILL_FEATURE_SECONDARY_FAN |
2856 UNIWILL_FEATURE_KEYBOARD_BACKLIGHT |
2857 UNIWILL_FEATURE_AC_AUTO_BOOT |
2858 UNIWILL_FEATURE_USB_POWERSHARE,
2859 .kbd_led_single_color = true,
2860 .kbd_led_max_brightness = 2,
2861 };
2862
2863 static const struct dmi_system_id uniwill_dmi_table[] __initconst = {
2864 {
2865 .ident = "AiStone X4SP4NAL",
2866 .matches = {
2867 DMI_MATCH(DMI_SYS_VENDOR, "AiStone"),
2868 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X4SP4NAL"),
2869 },
2870 .driver_data = &x4sp4nal_descriptor,
2871 },
2872 {
2873 .ident = "MACHENIKE L16 Pro",
2874 .matches = {
2875 DMI_MATCH(DMI_SYS_VENDOR, "MACHENIKE"),
2876 DMI_EXACT_MATCH(DMI_BOARD_NAME, "L16P"),
2877 },
2878 .driver_data = &machenike_l16p_descriptor,
2879 },
2880 {
2881 .ident = "XMG FUSION 15 (L19)",
2882 .matches = {
2883 DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
2884 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
2885 },
2886 .driver_data = &lapqc71a_lapqc71b_descriptor,
2887 },
2888 {
2889 .ident = "XMG FUSION 15 (L19)",
2890 .matches = {
2891 DMI_MATCH(DMI_SYS_VENDOR, "SchenkerTechnologiesGmbH"),
2892 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
2893 },
2894 .driver_data = &lapqc71a_lapqc71b_descriptor,
2895 },
2896 {
2897 .ident = "XMG FUSION 15 (L19)",
2898 .matches = {
2899 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2900 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
2901 },
2902 .driver_data = &lapqc71a_lapqc71b_descriptor,
2903 },
2904 {
2905 .ident = "XMG FUSION 15 (L19)",
2906 .matches = {
2907 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2908 DMI_EXACT_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
2909 },
2910 .driver_data = &lapqc71a_lapqc71b_descriptor,
2911 },
2912 {
2913 .ident = "Avell A60 MUV",
2914 .matches = {
2915 DMI_MATCH(DMI_PRODUCT_NAME, "A60 MUV"),
2916 },
2917 .driver_data = &lapqc71a_lapqc71b_descriptor,
2918 },
2919 {
2920 .ident = "Intel NUC x15",
2921 .matches = {
2922 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
2923 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPAC71H"),
2924 },
2925 .driver_data = &lapac71h_descriptor,
2926 },
2927 {
2928 .ident = "Intel NUC x15",
2929 .matches = {
2930 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
2931 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LAPKC71F"),
2932 },
2933 .driver_data = &lapkc71f_descriptor,
2934 },
2935 {
2936 .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
2937 .matches = {
2938 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2939 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTxX1"),
2940 },
2941 .driver_data = &phxtxx1_descriptor,
2942 },
2943 {
2944 .ident = "TUXEDO InfinityBook Pro 14 Gen6 Intel",
2945 .matches = {
2946 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2947 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxTQx1"),
2948 },
2949 .driver_data = &tux_featureset_2_nvidia_descriptor,
2950 },
2951 {
2952 .ident = "TUXEDO InfinityBook Pro 14/16 Gen7 Intel",
2953 .matches = {
2954 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2955 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PHxARX1_PHxAQF1"),
2956 },
2957 .driver_data = &phxarx1_phxaqf1_descriptor,
2958 },
2959 {
2960 .ident = "TUXEDO InfinityBook Pro 16 Gen7 Intel/Commodore Omnia-Book Pro Gen 7",
2961 .matches = {
2962 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2963 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6AG01_PH6AQ71_PH6AQI1"),
2964 },
2965 .driver_data = &tux_featureset_2_nvidia_descriptor,
2966 },
2967 {
2968 .ident = "TUXEDO InfinityBook Pro 14/16 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
2969 .matches = {
2970 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2971 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1"),
2972 },
2973 .driver_data = &tux_featureset_1_descriptor,
2974 },
2975 {
2976 .ident = "TUXEDO InfinityBook Pro 14 Gen8 Intel/Commodore Omnia-Book Pro Gen 8",
2977 .matches = {
2978 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2979 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH4PG31"),
2980 },
2981 .driver_data = &tux_featureset_2_nvidia_descriptor,
2982 },
2983 {
2984 .ident = "TUXEDO InfinityBook Pro 16 Gen8 Intel",
2985 .matches = {
2986 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2987 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PH6PG01_PH6PG71"),
2988 },
2989 .driver_data = &tux_featureset_2_nvidia_descriptor,
2990 },
2991 {
2992 .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 AMD",
2993 .matches = {
2994 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
2995 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
2996 },
2997 .driver_data = &tux_featureset_4_descriptor,
2998 },
2999 {
3000 .ident = "TUXEDO InfinityBook Pro 14/15 Gen9 Intel/Commodore Omnia-Book 15 Gen9",
3001 .matches = {
3002 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3003 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GXxMRXx"),
3004 },
3005 .driver_data = &tux_featureset_4_descriptor,
3006 },
3007 {
3008 .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
3009 .matches = {
3010 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3011 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
3012 },
3013 .driver_data = &tux_featureset_4_descriptor,
3014 },
3015 {
3016 .ident = "TUXEDO InfinityBook Pro 14/15 Gen10 AMD",
3017 .matches = {
3018 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3019 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
3020 },
3021 .driver_data = &tux_featureset_4_descriptor,
3022 },
3023 {
3024 .ident = "TUXEDO InfinityBook Pro 15 Gen10 Intel",
3025 .matches = {
3026 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3027 DMI_EXACT_MATCH(DMI_BOARD_NAME, "XxAR4NAx"),
3028 },
3029 .driver_data = &tux_featureset_4_descriptor,
3030 },
3031 {
3032 .ident = "TUXEDO InfinityBook Max 15 Gen10 AMD",
3033 .matches = {
3034 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3035 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5KK45xS_X5SP45xS"),
3036 },
3037 .driver_data = &tux_featureset_4_nvidia_descriptor,
3038 },
3039 {
3040 .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
3041 .matches = {
3042 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3043 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6HP45xU"),
3044 },
3045 .driver_data = &tux_featureset_4_nvidia_descriptor,
3046 },
3047 {
3048 .ident = "TUXEDO InfinityBook Max 16 Gen10 AMD",
3049 .matches = {
3050 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3051 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6KK45xU_X6SP45xU"),
3052 },
3053 .driver_data = &tux_featureset_4_nvidia_descriptor,
3054 },
3055 {
3056 .ident = "TUXEDO InfinityBook Max 15 Gen10 Intel",
3057 .matches = {
3058 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3059 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X5AR45xS"),
3060 },
3061 .driver_data = &tux_featureset_4_nvidia_descriptor,
3062 },
3063 {
3064 .ident = "TUXEDO InfinityBook Max 16 Gen10 Intel",
3065 .matches = {
3066 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3067 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR55xU"),
3068 },
3069 .driver_data = &tux_featureset_4_nvidia_descriptor,
3070 },
3071 {
3072 .ident = "TUXEDO Polaris 15 Gen1 AMD",
3073 .matches = {
3074 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3075 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
3076 },
3077 .driver_data = &tux_featureset_1_nvidia_descriptor,
3078 },
3079 {
3080 .ident = "TUXEDO Polaris 15 Gen1 AMD",
3081 .matches = {
3082 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3083 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
3084 },
3085 .driver_data = &tux_featureset_1_nvidia_descriptor,
3086 },
3087 {
3088 .ident = "TUXEDO Polaris 17 Gen1 AMD",
3089 .matches = {
3090 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3091 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
3092 },
3093 .driver_data = &tux_featureset_1_nvidia_descriptor,
3094 },
3095 {
3096 .ident = "TUXEDO Polaris 17 Gen1 AMD",
3097 .matches = {
3098 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3099 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
3100 },
3101 .driver_data = &tux_featureset_1_nvidia_descriptor,
3102 },
3103 {
3104 .ident = "TUXEDO Polaris 15 Gen1 Intel",
3105 .matches = {
3106 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3107 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I1650TI"),
3108 },
3109 .driver_data = &tux_featureset_1_nvidia_descriptor,
3110 },
3111 {
3112 .ident = "TUXEDO Polaris 15 Gen1 Intel",
3113 .matches = {
3114 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3115 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1501I2060"),
3116 },
3117 .driver_data = &tux_featureset_1_nvidia_descriptor,
3118 },
3119 {
3120 .ident = "TUXEDO Polaris 17 Gen1 Intel",
3121 .matches = {
3122 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3123 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I1650TI"),
3124 },
3125 .driver_data = &tux_featureset_1_nvidia_descriptor,
3126 },
3127 {
3128 .ident = "TUXEDO Polaris 17 Gen1 Intel",
3129 .matches = {
3130 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3131 DMI_EXACT_MATCH(DMI_BOARD_NAME, "POLARIS1701I2060"),
3132 },
3133 .driver_data = &tux_featureset_1_nvidia_descriptor,
3134 },
3135 {
3136 .ident = "TUXEDO Trinity 15 Intel Gen1",
3137 .matches = {
3138 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3139 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1501I"),
3140 },
3141 .driver_data = &tux_featureset_1_nvidia_descriptor,
3142 },
3143 {
3144 .ident = "TUXEDO Trinity 17 Intel Gen1",
3145 .matches = {
3146 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3147 DMI_EXACT_MATCH(DMI_BOARD_NAME, "TRINITY1701I"),
3148 },
3149 .driver_data = &tux_featureset_1_nvidia_descriptor,
3150 },
3151 {
3152 .ident = "TUXEDO Polaris 15/17 Gen2 AMD",
3153 .matches = {
3154 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3155 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxMGxx"),
3156 },
3157 .driver_data = &tux_featureset_2_nvidia_descriptor,
3158 },
3159 {
3160 .ident = "TUXEDO Polaris 15/17 Gen2 Intel",
3161 .matches = {
3162 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3163 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
3164 },
3165 .driver_data = &tux_featureset_2_nvidia_descriptor,
3166 },
3167 {
3168 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 AMD",
3169 .matches = {
3170 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3171 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
3172 },
3173 .driver_data = &tux_featureset_2_nvidia_descriptor,
3174 },
3175 {
3176 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen3 Intel",
3177 .matches = {
3178 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3179 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxTGxx"),
3180 },
3181 .driver_data = &tux_featureset_2_nvidia_descriptor,
3182 },
3183 {
3184 .ident = "TUXEDO Stellaris/Polaris 15/17 Gen4 AMD",
3185 .matches = {
3186 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3187 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
3188 },
3189 .driver_data = &tux_featureset_3_nvidia_descriptor,
3190 },
3191 {
3192 .ident = "TUXEDO Stellaris 15 Gen4 Intel",
3193 .matches = {
3194 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3195 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxAGxx"),
3196 },
3197 .driver_data = &tux_featureset_3_nvidia_descriptor,
3198 },
3199 {
3200 .ident = "TUXEDO Polaris 15/17 Gen5 AMD",
3201 .matches = {
3202 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3203 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
3204 },
3205 .driver_data = &tux_featureset_2_nvidia_descriptor,
3206 },
3207 {
3208 .ident = "TUXEDO Stellaris 16 Gen5 AMD",
3209 .matches = {
3210 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3211 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
3212 },
3213 .driver_data = &tux_featureset_3_nvidia_descriptor,
3214 },
3215 {
3216 .ident = "TUXEDO Stellaris 16/17 Gen5 Intel/Commodore ORION Gen 5",
3217 .matches = {
3218 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3219 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxPXxx"),
3220 },
3221 .driver_data = &tux_featureset_3_nvidia_descriptor,
3222 },
3223 {
3224 .ident = "TUXEDO Stellaris Slim 15 Gen6 AMD",
3225 .matches = {
3226 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3227 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
3228 },
3229 .driver_data = &tux_featureset_4_nvidia_descriptor,
3230 },
3231 {
3232 .ident = "TUXEDO Stellaris Slim 15 Gen6 Intel/Commodore ORION Slim 15 Gen6",
3233 .matches = {
3234 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3235 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM5IXxA"),
3236 },
3237 .driver_data = &tux_featureset_4_nvidia_descriptor,
3238 },
3239 {
3240 .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
3241 .matches = {
3242 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3243 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB1"),
3244 },
3245 .driver_data = &tux_featureset_4_nvidia_descriptor,
3246 },
3247 {
3248 .ident = "TUXEDO Stellaris 16 Gen6 Intel/Commodore ORION 16 Gen6",
3249 .matches = {
3250 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3251 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM6IXxB_MB2"),
3252 },
3253 .driver_data = &tux_featureset_4_nvidia_descriptor,
3254 },
3255 {
3256 .ident = "TUXEDO Stellaris 17 Gen6 Intel/Commodore ORION 17 Gen6",
3257 .matches = {
3258 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3259 DMI_EXACT_MATCH(DMI_BOARD_NAME, "GM7IXxN"),
3260 },
3261 .driver_data = &tux_featureset_4_nvidia_descriptor,
3262 },
3263 {
3264 .ident = "TUXEDO Stellaris 16 Gen7 AMD",
3265 .matches = {
3266 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3267 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6FR5xxY"),
3268 },
3269 .driver_data = &tux_featureset_4_nvidia_descriptor,
3270 },
3271 {
3272 .ident = "TUXEDO Stellaris 16 Gen7 Intel",
3273 .matches = {
3274 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3275 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY"),
3276 },
3277 .driver_data = &tux_featureset_4_nvidia_descriptor,
3278 },
3279 {
3280 .ident = "TUXEDO Stellaris 16 Gen7 Intel",
3281 .matches = {
3282 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3283 DMI_EXACT_MATCH(DMI_BOARD_NAME, "X6AR5xxY_mLED"),
3284 },
3285 .driver_data = &tux_featureset_4_nvidia_descriptor,
3286 },
3287 {
3288 .ident = "TUXEDO Book BA15 Gen10 AMD",
3289 .matches = {
3290 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3291 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
3292 },
3293 .driver_data = &pf5pu1g_descriptor,
3294 },
3295 {
3296 .ident = "TUXEDO Pulse 14 Gen1 AMD",
3297 .matches = {
3298 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3299 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1401"),
3300 },
3301 .driver_data = &tux_featureset_1_descriptor,
3302 },
3303 {
3304 .ident = "TUXEDO Pulse 15 Gen1 AMD",
3305 .matches = {
3306 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3307 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PULSE1501"),
3308 },
3309 .driver_data = &tux_featureset_1_descriptor,
3310 },
3311 {
3312 .ident = "TUXEDO Pulse 15 Gen2 AMD",
3313 .matches = {
3314 DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
3315 DMI_EXACT_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
3316 },
3317 .driver_data = &tux_featureset_1_descriptor,
3318 },
3319 { }
3320 };
3321 MODULE_DEVICE_TABLE(dmi, uniwill_dmi_table);
3322
uniwill_init(void)3323 static int __init uniwill_init(void)
3324 {
3325 const struct uniwill_device_descriptor *descriptor;
3326 const struct dmi_system_id *id;
3327 int ret;
3328
3329 id = dmi_first_match(uniwill_dmi_table);
3330 if (!id) {
3331 if (!force)
3332 return -ENODEV;
3333
3334 pr_warn("Loading on a potentially unsupported device\n");
3335 } else {
3336 /*
3337 * Some devices might support additional features depending on
3338 * the BIOS version/date, so we call this callback to let them
3339 * modify their device descriptor accordingly.
3340 */
3341 if (id->callback) {
3342 ret = id->callback(id);
3343 if (ret < 0)
3344 return ret;
3345 }
3346
3347 descriptor = id->driver_data;
3348 device_descriptor = *descriptor;
3349 }
3350
3351 if (force) {
3352 /* Assume that the device supports all features except the charge limit */
3353 device_descriptor.features = UINT_MAX & ~UNIWILL_FEATURE_BATTERY_CHARGE_LIMIT;
3354 /* Some models only have a (white) single color keyboard backlight */
3355 device_descriptor.kbd_led_single_color = false;
3356 /* Some models only support 3 brightness levels */
3357 device_descriptor.kbd_led_max_brightness = 4;
3358 /* Some models only support 36 brightness levels per color component */
3359 device_descriptor.lightbar_max_brightness = 200;
3360 pr_warn("Enabling potentially unsupported features\n");
3361 }
3362
3363 ret = platform_driver_register(&uniwill_driver);
3364 if (ret < 0)
3365 return ret;
3366
3367 ret = uniwill_wmi_register_driver();
3368 if (ret < 0) {
3369 platform_driver_unregister(&uniwill_driver);
3370 return ret;
3371 }
3372
3373 return 0;
3374 }
3375 module_init(uniwill_init);
3376
uniwill_exit(void)3377 static void __exit uniwill_exit(void)
3378 {
3379 uniwill_wmi_unregister_driver();
3380 platform_driver_unregister(&uniwill_driver);
3381 }
3382 module_exit(uniwill_exit);
3383
3384 MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
3385 MODULE_DESCRIPTION("Uniwill notebook driver");
3386 MODULE_LICENSE("GPL");
3387