1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Linux driver for Bitland notebooks. 4 * 5 * Copyright (C) 2026 2 Mingyou Chen <qby140326@gmail.com> 6 */ 7 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10 #include <linux/acpi.h> 11 #include <linux/array_size.h> 12 #include <linux/bits.h> 13 #include <linux/container_of.h> 14 #include <linux/dev_printk.h> 15 #include <linux/device.h> 16 #include <linux/device/devres.h> 17 #include <linux/err.h> 18 #include <linux/hwmon.h> 19 #include <linux/init.h> 20 #include <linux/input-event-codes.h> 21 #include <linux/input.h> 22 #include <linux/input/sparse-keymap.h> 23 #include <linux/kernel.h> 24 #include <linux/leds.h> 25 #include <linux/module.h> 26 #include <linux/notifier.h> 27 #include <linux/platform_profile.h> 28 #include <linux/pm.h> 29 #include <linux/power_supply.h> 30 #include <linux/stddef.h> 31 #include <linux/string.h> 32 #include <linux/sysfs.h> 33 #include <linux/unaligned.h> 34 #include <linux/units.h> 35 #include <linux/wmi.h> 36 37 #define DRV_NAME "bitland-mifs-wmi" 38 #define BITLAND_MIFS_GUID "B60BFB48-3E5B-49E4-A0E9-8CFFE1B3434B" 39 #define BITLAND_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF" 40 41 enum bitland_mifs_operation { 42 WMI_METHOD_GET = 250, 43 WMI_METHOD_SET = 251, 44 }; 45 46 enum bitland_mifs_function { 47 WMI_FN_SYSTEM_PER_MODE = 8, 48 WMI_FN_GPU_MODE = 9, 49 WMI_FN_KBD_TYPE = 10, 50 WMI_FN_FN_LOCK = 11, 51 WMI_FN_TP_LOCK = 12, 52 WMI_FN_FAN_SPEEDS = 13, 53 WMI_FN_RGB_KB_MODE = 16, 54 WMI_FN_RGB_KB_COLOR = 17, 55 WMI_FN_RGB_KB_BRIGHTNESS = 18, 56 WMI_FN_SYSTEM_AC_TYPE = 19, 57 WMI_FN_MAX_FAN_SWITCH = 20, 58 WMI_FN_MAX_FAN_SPEED = 21, 59 WMI_FN_CPU_THERMOMETER = 22, 60 WMI_FN_CPU_POWER = 23, 61 }; 62 63 enum bitland_system_ac_mode { 64 WMI_SYSTEM_AC_TYPEC = 1, 65 /* Unknown type, this is unused in the original driver */ 66 WMI_SYSTEM_AC_CIRCULARHOLE = 2, 67 }; 68 69 enum bitland_mifs_power_profile { 70 WMI_PP_BALANCED = 0, 71 WMI_PP_PERFORMANCE = 1, 72 WMI_PP_QUIET = 2, 73 WMI_PP_FULL_SPEED = 3, 74 }; 75 76 enum bitland_mifs_event_id { 77 WMI_EVENT_RESERVED_1 = 1, 78 WMI_EVENT_RESERVED_2 = 2, 79 WMI_EVENT_RESERVED_3 = 3, 80 WMI_EVENT_AIRPLANE_MODE = 4, 81 WMI_EVENT_KBD_BRIGHTNESS = 5, 82 WMI_EVENT_TOUCHPAD_STATE = 6, 83 WMI_EVENT_FNLOCK_STATE = 7, 84 WMI_EVENT_KBD_MODE = 8, 85 WMI_EVENT_CAPSLOCK_STATE = 9, 86 WMI_EVENT_CALCULATOR_START = 11, 87 WMI_EVENT_BROWSER_START = 12, 88 WMI_EVENT_NUMLOCK_STATE = 13, 89 WMI_EVENT_SCROLLLOCK_STATE = 14, 90 WMI_EVENT_PERFORMANCE_PLAN = 15, 91 WMI_EVENT_FN_J = 16, 92 WMI_EVENT_FN_F = 17, 93 WMI_EVENT_FN_0 = 18, 94 WMI_EVENT_FN_1 = 19, 95 WMI_EVENT_FN_2 = 20, 96 WMI_EVENT_FN_3 = 21, 97 WMI_EVENT_FN_4 = 22, 98 WMI_EVENT_FN_5 = 24, 99 WMI_EVENT_REFRESH_RATE = 25, 100 WMI_EVENT_CPU_FAN_SPEED = 26, 101 WMI_EVENT_GPU_FAN_SPEED = 32, 102 WMI_EVENT_WIN_KEY_LOCK = 33, 103 WMI_EVENT_RESERVED_23 = 34, 104 WMI_EVENT_OPEN_APP = 35, 105 }; 106 107 enum bitland_mifs_event_type { 108 WMI_EVENT_TYPE_HOTKEY = 1, 109 }; 110 111 enum bitland_wmi_device_type { 112 BITLAND_WMI_CONTROL = 0, 113 BITLAND_WMI_EVENT = 1, 114 }; 115 116 struct bitland_mifs_input { 117 u8 reserved1; 118 u8 operation; 119 u8 reserved2; 120 u8 function; 121 u8 payload[28]; 122 } __packed; 123 124 struct bitland_mifs_output { 125 u8 reserved1; 126 u8 operation; 127 u8 reserved2; 128 u8 function; 129 u8 data[28]; 130 } __packed; 131 132 struct bitland_mifs_event { 133 u8 event_type; 134 u8 event_id; 135 u8 value_low; /* For most events, this is the value */ 136 u8 value_high; /* For fan speed events, combined with value_low */ 137 u8 reserved[4]; 138 } __packed; 139 140 static BLOCKING_NOTIFIER_HEAD(bitland_notifier_list); 141 142 enum bitland_notifier_actions { 143 BITLAND_NOTIFY_KBD_BRIGHTNESS, 144 BITLAND_NOTIFY_PLATFORM_PROFILE, 145 BITLAND_NOTIFY_HWMON, 146 }; 147 148 struct bitland_fan_notify_data { 149 int channel; /* 0 = CPU, 1 = GPU */ 150 u16 speed; 151 }; 152 153 struct bitland_mifs_wmi_data { 154 struct wmi_device *wdev; 155 struct mutex lock; /* Protects WMI calls */ 156 struct led_classdev kbd_led; 157 struct notifier_block notifier; 158 struct input_dev *input_dev; 159 struct device *hwmon_dev; 160 struct device *pp_dev; 161 enum platform_profile_option saved_profile; 162 }; 163 164 static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data, 165 const struct bitland_mifs_input *input, 166 struct bitland_mifs_output *output) 167 { 168 struct wmi_buffer in_buf = { .length = sizeof(*input), .data = (void *)input }; 169 struct wmi_buffer out_buf = { 0 }; 170 int ret; 171 172 guard(mutex)(&data->lock); 173 174 if (!output) 175 return wmidev_invoke_procedure(data->wdev, 0, 1, &in_buf); 176 177 ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output)); 178 if (ret) 179 return ret; 180 181 memcpy(output, out_buf.data, sizeof(*output)); 182 kfree(out_buf.data); 183 184 return 0; 185 } 186 187 static int laptop_profile_get(struct device *dev, 188 enum platform_profile_option *profile) 189 { 190 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 191 struct bitland_mifs_input input = { 192 .reserved1 = 0, 193 .operation = WMI_METHOD_GET, 194 .reserved2 = 0, 195 .function = WMI_FN_SYSTEM_PER_MODE, 196 }; 197 struct bitland_mifs_output result; 198 int ret; 199 200 ret = bitland_mifs_wmi_call(data, &input, &result); 201 if (ret) 202 return ret; 203 204 switch (result.data[0]) { 205 case WMI_PP_BALANCED: 206 *profile = PLATFORM_PROFILE_BALANCED; 207 break; 208 case WMI_PP_PERFORMANCE: 209 *profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE; 210 break; 211 case WMI_PP_QUIET: 212 *profile = PLATFORM_PROFILE_LOW_POWER; 213 break; 214 case WMI_PP_FULL_SPEED: 215 *profile = PLATFORM_PROFILE_PERFORMANCE; 216 break; 217 default: 218 return -EINVAL; 219 } 220 return 0; 221 } 222 223 static int bitland_check_performance_capability(struct bitland_mifs_wmi_data *data) 224 { 225 struct bitland_mifs_input input = { 226 .operation = WMI_METHOD_GET, 227 .function = WMI_FN_SYSTEM_AC_TYPE, 228 }; 229 struct bitland_mifs_output output; 230 int ret; 231 232 /* Full-speed/performance mode requires DC power (not USB-C) */ 233 if (!power_supply_is_system_supplied()) 234 return -EOPNOTSUPP; 235 236 ret = bitland_mifs_wmi_call(data, &input, &output); 237 if (ret) 238 return ret; 239 240 if (output.data[0] != WMI_SYSTEM_AC_CIRCULARHOLE) 241 return -EOPNOTSUPP; 242 243 return 0; 244 } 245 246 static int laptop_profile_set(struct device *dev, 247 enum platform_profile_option profile) 248 { 249 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 250 struct bitland_mifs_input input = { 251 .reserved1 = 0, 252 .operation = WMI_METHOD_SET, 253 .reserved2 = 0, 254 .function = WMI_FN_SYSTEM_PER_MODE, 255 }; 256 int ret; 257 u8 val; 258 259 switch (profile) { 260 case PLATFORM_PROFILE_LOW_POWER: 261 val = WMI_PP_QUIET; 262 break; 263 case PLATFORM_PROFILE_BALANCED: 264 val = WMI_PP_BALANCED; 265 break; 266 case PLATFORM_PROFILE_BALANCED_PERFORMANCE: 267 ret = bitland_check_performance_capability(data); 268 if (ret) 269 return ret; 270 val = WMI_PP_PERFORMANCE; 271 break; 272 case PLATFORM_PROFILE_PERFORMANCE: 273 ret = bitland_check_performance_capability(data); 274 if (ret) 275 return ret; 276 val = WMI_PP_FULL_SPEED; 277 break; 278 default: 279 return -EOPNOTSUPP; 280 } 281 282 input.payload[0] = val; 283 284 return bitland_mifs_wmi_call(data, &input, NULL); 285 } 286 287 static int platform_profile_probe(void *drvdata, unsigned long *choices) 288 { 289 set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 290 set_bit(PLATFORM_PROFILE_BALANCED, choices); 291 set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); 292 set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 293 294 return 0; 295 } 296 297 static int bitland_mifs_wmi_suspend(struct device *dev) 298 { 299 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 300 enum platform_profile_option profile; 301 int ret; 302 303 ret = laptop_profile_get(data->pp_dev, &profile); 304 if (ret == 0) 305 data->saved_profile = profile; 306 307 return ret; 308 } 309 310 static int bitland_mifs_wmi_resume(struct device *dev) 311 { 312 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 313 314 dev_dbg(dev, "Resuming, restoring profile %d\n", data->saved_profile); 315 return laptop_profile_set(dev, data->saved_profile); 316 } 317 318 static DEFINE_SIMPLE_DEV_PM_OPS(bitland_mifs_wmi_pm_ops, 319 bitland_mifs_wmi_suspend, 320 bitland_mifs_wmi_resume); 321 322 static const struct platform_profile_ops laptop_profile_ops = { 323 .probe = platform_profile_probe, 324 .profile_get = laptop_profile_get, 325 .profile_set = laptop_profile_set, 326 }; 327 328 static const char *const fan_labels[] = { 329 "CPU", /* 0 */ 330 "GPU", /* 1 */ 331 "SYS", /* 2 */ 332 }; 333 334 static int laptop_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 335 u32 attr, int channel, long *val) 336 { 337 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 338 struct bitland_mifs_input input = { 339 .reserved1 = 0, 340 .operation = WMI_METHOD_GET, 341 .reserved2 = 0, 342 }; 343 struct bitland_mifs_output res; 344 int ret; 345 346 switch (type) { 347 case hwmon_temp: 348 input.function = WMI_FN_CPU_THERMOMETER; 349 ret = bitland_mifs_wmi_call(data, &input, &res); 350 if (!ret) 351 *val = res.data[0] * MILLIDEGREE_PER_DEGREE; 352 return ret; 353 case hwmon_fan: 354 input.function = WMI_FN_FAN_SPEEDS; 355 ret = bitland_mifs_wmi_call(data, &input, &res); 356 if (ret) 357 return ret; 358 359 switch (channel) { 360 case 0: /* CPU */ 361 *val = get_unaligned_le16(&res.data[0]); 362 return 0; 363 case 1: /* GPU */ 364 *val = get_unaligned_le16(&res.data[2]); 365 return 0; 366 case 2: /* SYS */ 367 *val = get_unaligned_le16(&res.data[6]); 368 return 0; 369 default: 370 return -EINVAL; 371 } 372 default: 373 return -EINVAL; 374 } 375 } 376 377 static int laptop_hwmon_read_string(struct device *dev, 378 enum hwmon_sensor_types type, u32 attr, 379 int channel, const char **str) 380 { 381 if (type == hwmon_fan && attr == hwmon_fan_label) { 382 if (channel >= 0 && channel < ARRAY_SIZE(fan_labels)) { 383 *str = fan_labels[channel]; 384 return 0; 385 } 386 } 387 return -EINVAL; 388 } 389 390 static const struct hwmon_channel_info *laptop_hwmon_info[] = { 391 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 392 HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL, 393 HWMON_F_INPUT | HWMON_F_LABEL, 394 HWMON_F_INPUT | HWMON_F_LABEL), 395 NULL 396 }; 397 398 static const struct hwmon_ops laptop_hwmon_ops = { 399 .visible = 0444, 400 .read = laptop_hwmon_read, 401 .read_string = laptop_hwmon_read_string, 402 }; 403 404 static const struct hwmon_chip_info laptop_chip_info = { 405 .ops = &laptop_hwmon_ops, 406 .info = laptop_hwmon_info, 407 }; 408 409 static int laptop_kbd_led_set(struct led_classdev *led_cdev, 410 enum led_brightness value) 411 { 412 struct bitland_mifs_wmi_data *data = 413 container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led); 414 struct bitland_mifs_input input = { 415 .reserved1 = 0, 416 .operation = WMI_METHOD_SET, 417 .reserved2 = 0, 418 .function = WMI_FN_RGB_KB_BRIGHTNESS, 419 }; 420 421 input.payload[0] = (u8)value; 422 423 return bitland_mifs_wmi_call(data, &input, NULL); 424 } 425 426 static enum led_brightness laptop_kbd_led_get(struct led_classdev *led_cdev) 427 { 428 struct bitland_mifs_wmi_data *data = 429 container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led); 430 struct bitland_mifs_input input = { 431 .reserved1 = 0, 432 .operation = WMI_METHOD_GET, 433 .reserved2 = 0, 434 .function = WMI_FN_RGB_KB_BRIGHTNESS, 435 }; 436 struct bitland_mifs_output res; 437 int ret; 438 439 ret = bitland_mifs_wmi_call(data, &input, &res); 440 if (ret) 441 return ret; 442 443 return res.data[0]; 444 } 445 446 static const char *const gpu_mode_strings[] = { 447 "hybrid", 448 "discrete", 449 "uma", 450 }; 451 452 /* GPU Mode: 0:Hybrid, 1:Discrete, 2:UMA */ 453 static ssize_t gpu_mode_show(struct device *dev, struct device_attribute *attr, 454 char *buf) 455 { 456 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 457 struct bitland_mifs_input input = { 458 .reserved1 = 0, 459 .operation = WMI_METHOD_GET, 460 .reserved2 = 0, 461 .function = WMI_FN_GPU_MODE, 462 }; 463 struct bitland_mifs_output res; 464 u8 mode_val; 465 int ret; 466 467 ret = bitland_mifs_wmi_call(data, &input, &res); 468 if (ret) 469 return ret; 470 471 mode_val = res.data[0]; 472 if (mode_val >= ARRAY_SIZE(gpu_mode_strings)) 473 return -EPROTO; 474 475 return sysfs_emit(buf, "%s\n", gpu_mode_strings[mode_val]); 476 } 477 478 static ssize_t gpu_mode_store(struct device *dev, struct device_attribute *attr, 479 const char *buf, size_t count) 480 { 481 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 482 struct bitland_mifs_input input = { 483 .reserved1 = 0, 484 .operation = WMI_METHOD_SET, 485 .reserved2 = 0, 486 .function = WMI_FN_GPU_MODE, 487 }; 488 int val; 489 int ret; 490 491 val = sysfs_match_string(gpu_mode_strings, buf); 492 if (val < 0) 493 return -EINVAL; 494 495 input.payload[0] = (u8)val; 496 497 ret = bitland_mifs_wmi_call(data, &input, NULL); 498 if (ret) 499 return ret; 500 501 return count; 502 } 503 504 static const char *const kb_mode_strings[] = { 505 "off", /* 0 */ 506 "cyclic", /* 1 */ 507 "fixed", /* 2 */ 508 "custom", /* 3 */ 509 }; 510 511 static ssize_t kb_mode_show(struct device *dev, struct device_attribute *attr, 512 char *buf) 513 { 514 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 515 struct bitland_mifs_input input = { 516 .reserved1 = 0, 517 .operation = WMI_METHOD_GET, 518 .reserved2 = 0, 519 .function = WMI_FN_RGB_KB_MODE, 520 }; 521 struct bitland_mifs_output res; 522 u8 mode_val; 523 int ret; 524 525 ret = bitland_mifs_wmi_call(data, &input, &res); 526 if (ret) 527 return ret; 528 529 mode_val = res.data[0]; 530 if (mode_val >= ARRAY_SIZE(kb_mode_strings)) 531 return -EPROTO; 532 533 return sysfs_emit(buf, "%s\n", kb_mode_strings[mode_val]); 534 } 535 536 static ssize_t kb_mode_store(struct device *dev, struct device_attribute *attr, 537 const char *buf, size_t count) 538 { 539 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 540 struct bitland_mifs_input input = { 541 .reserved1 = 0, 542 .operation = WMI_METHOD_SET, 543 .reserved2 = 0, 544 .function = WMI_FN_RGB_KB_MODE, 545 }; 546 // the wmi value (0, 1, 2 or 3) 547 int val; 548 int ret; 549 550 val = sysfs_match_string(kb_mode_strings, buf); 551 if (val < 0) 552 return -EINVAL; 553 554 input.payload[0] = (u8)val; 555 556 ret = bitland_mifs_wmi_call(data, &input, NULL); 557 if (ret) 558 return ret; 559 560 return count; 561 } 562 563 /* Fan Boost: 0:Normal, 1:Max Speed */ 564 static ssize_t fan_boost_store(struct device *dev, 565 struct device_attribute *attr, const char *buf, 566 size_t count) 567 { 568 struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); 569 struct bitland_mifs_input input = { 570 .reserved1 = 0, 571 .operation = WMI_METHOD_SET, 572 .reserved2 = 0, 573 .function = WMI_FN_MAX_FAN_SWITCH, 574 }; 575 bool val; 576 int ret; 577 578 if (kstrtobool(buf, &val)) 579 return -EINVAL; 580 581 input.payload[0] = 0; /* CPU/GPU Fan */ 582 input.payload[1] = val; 583 584 ret = bitland_mifs_wmi_call(data, &input, NULL); 585 if (ret) 586 return ret; 587 588 return count; 589 } 590 591 static const DEVICE_ATTR_RW(gpu_mode); 592 static const DEVICE_ATTR_RW(kb_mode); 593 static const DEVICE_ATTR_WO(fan_boost); 594 595 static const struct attribute *const laptop_attrs[] = { 596 &dev_attr_gpu_mode.attr, 597 &dev_attr_kb_mode.attr, 598 &dev_attr_fan_boost.attr, 599 NULL, 600 }; 601 ATTRIBUTE_GROUPS(laptop); 602 603 static const struct key_entry bitland_mifs_wmi_keymap[] = { 604 { KE_KEY, WMI_EVENT_OPEN_APP, { KEY_PROG1 } }, 605 { KE_KEY, WMI_EVENT_CALCULATOR_START, { KEY_CALC } }, 606 { KE_KEY, WMI_EVENT_BROWSER_START, { KEY_WWW } }, 607 { KE_IGNORE, WMI_EVENT_FN_J, { KEY_RESERVED } }, 608 { KE_IGNORE, WMI_EVENT_FN_F, { KEY_RESERVED } }, 609 { KE_IGNORE, WMI_EVENT_FN_0, { KEY_RESERVED } }, 610 { KE_IGNORE, WMI_EVENT_FN_1, { KEY_RESERVED } }, 611 { KE_IGNORE, WMI_EVENT_FN_2, { KEY_RESERVED } }, 612 { KE_IGNORE, WMI_EVENT_FN_3, { KEY_RESERVED } }, 613 { KE_IGNORE, WMI_EVENT_FN_4, { KEY_RESERVED } }, 614 { KE_IGNORE, WMI_EVENT_FN_5, { KEY_RESERVED } }, 615 { KE_END, 0 } 616 }; 617 618 static void bitland_notifier_unregister(void *data) 619 { 620 struct notifier_block *nb = data; 621 622 blocking_notifier_chain_unregister(&bitland_notifier_list, nb); 623 } 624 625 static int bitland_notifier_callback(struct notifier_block *nb, 626 unsigned long action, void *data) 627 { 628 struct bitland_mifs_wmi_data *data_ctx = 629 container_of(nb, struct bitland_mifs_wmi_data, notifier); 630 struct bitland_fan_notify_data *fan_info; 631 u8 *brightness; 632 633 switch (action) { 634 case BITLAND_NOTIFY_KBD_BRIGHTNESS: 635 brightness = data; 636 led_classdev_notify_brightness_hw_changed(&data_ctx->kbd_led, 637 *brightness); 638 break; 639 case BITLAND_NOTIFY_PLATFORM_PROFILE: 640 platform_profile_notify(data_ctx->pp_dev); 641 break; 642 case BITLAND_NOTIFY_HWMON: 643 fan_info = data; 644 645 hwmon_notify_event(data_ctx->hwmon_dev, hwmon_fan, 646 hwmon_fan_input, fan_info->channel); 647 break; 648 } 649 650 return NOTIFY_OK; 651 } 652 653 static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context) 654 { 655 struct bitland_mifs_wmi_data *drv_data; 656 enum bitland_wmi_device_type dev_type = 657 (enum bitland_wmi_device_type)(unsigned long)context; 658 struct led_init_data init_data = { 659 .devicename = DRV_NAME, 660 .default_label = ":" LED_FUNCTION_KBD_BACKLIGHT, 661 .devname_mandatory = true, 662 }; 663 int ret; 664 665 drv_data = devm_kzalloc(&wdev->dev, sizeof(*drv_data), GFP_KERNEL); 666 if (!drv_data) 667 return -ENOMEM; 668 669 drv_data->wdev = wdev; 670 671 ret = devm_mutex_init(&wdev->dev, &drv_data->lock); 672 if (ret) 673 return ret; 674 675 dev_set_drvdata(&wdev->dev, drv_data); 676 677 if (dev_type == BITLAND_WMI_EVENT) { 678 /* Register input device for hotkeys */ 679 drv_data->input_dev = devm_input_allocate_device(&wdev->dev); 680 if (!drv_data->input_dev) 681 return -ENOMEM; 682 683 drv_data->input_dev->name = "Bitland MIFS WMI hotkeys"; 684 drv_data->input_dev->phys = "wmi/input0"; 685 drv_data->input_dev->id.bustype = BUS_HOST; 686 drv_data->input_dev->dev.parent = &wdev->dev; 687 688 ret = sparse_keymap_setup(drv_data->input_dev, 689 bitland_mifs_wmi_keymap, NULL); 690 if (ret) 691 return ret; 692 693 return input_register_device(drv_data->input_dev); 694 } 695 696 /* Register platform profile */ 697 drv_data->pp_dev = devm_platform_profile_register(&wdev->dev, DRV_NAME, drv_data, 698 &laptop_profile_ops); 699 if (IS_ERR(drv_data->pp_dev)) 700 return PTR_ERR(drv_data->pp_dev); 701 702 /* Register hwmon */ 703 drv_data->hwmon_dev = devm_hwmon_device_register_with_info(&wdev->dev, 704 "bitland_mifs", 705 drv_data, 706 &laptop_chip_info, 707 NULL); 708 if (IS_ERR(drv_data->hwmon_dev)) 709 return PTR_ERR(drv_data->hwmon_dev); 710 711 /* Register keyboard LED */ 712 drv_data->kbd_led.max_brightness = 3; 713 drv_data->kbd_led.brightness_set_blocking = laptop_kbd_led_set; 714 drv_data->kbd_led.brightness_get = laptop_kbd_led_get; 715 drv_data->kbd_led.brightness = laptop_kbd_led_get(&drv_data->kbd_led); 716 drv_data->kbd_led.flags = LED_CORE_SUSPENDRESUME | 717 LED_BRIGHT_HW_CHANGED | 718 LED_REJECT_NAME_CONFLICT; 719 ret = devm_led_classdev_register_ext(&wdev->dev, &drv_data->kbd_led, &init_data); 720 if (ret) 721 return ret; 722 723 drv_data->notifier.notifier_call = bitland_notifier_callback; 724 ret = blocking_notifier_chain_register(&bitland_notifier_list, &drv_data->notifier); 725 if (ret) 726 return ret; 727 728 return devm_add_action_or_reset(&wdev->dev, 729 bitland_notifier_unregister, 730 &drv_data->notifier); 731 } 732 733 static void bitland_mifs_wmi_notify(struct wmi_device *wdev, 734 const struct wmi_buffer *buffer) 735 { 736 struct bitland_mifs_wmi_data *data = dev_get_drvdata(&wdev->dev); 737 const struct bitland_mifs_event *event = buffer->data; 738 struct bitland_fan_notify_data fan_data; 739 u8 brightness; 740 741 /* Validate event type */ 742 if (event->event_type != WMI_EVENT_TYPE_HOTKEY) 743 return; 744 745 dev_dbg(&wdev->dev, 746 "WMI event: id=0x%02x value_low=0x%02x value_high=0x%02x\n", 747 event->event_id, event->value_low, event->value_high); 748 749 switch (event->event_id) { 750 case WMI_EVENT_KBD_BRIGHTNESS: 751 brightness = event->value_low; 752 blocking_notifier_call_chain(&bitland_notifier_list, 753 BITLAND_NOTIFY_KBD_BRIGHTNESS, 754 &brightness); 755 break; 756 757 case WMI_EVENT_PERFORMANCE_PLAN: 758 blocking_notifier_call_chain(&bitland_notifier_list, 759 BITLAND_NOTIFY_PLATFORM_PROFILE, 760 NULL); 761 break; 762 763 case WMI_EVENT_OPEN_APP: 764 case WMI_EVENT_CALCULATOR_START: 765 case WMI_EVENT_BROWSER_START: { 766 guard(mutex)(&data->lock); 767 if (!sparse_keymap_report_event(data->input_dev, 768 event->event_id, 1, true)) 769 dev_warn(&wdev->dev, "Unknown key pressed: 0x%02x\n", 770 event->event_id); 771 break; 772 } 773 774 /* 775 * The device has 3 fans (CPU, GPU, SYS), 776 * but there are only the CPU and GPU fan has events 777 */ 778 case WMI_EVENT_CPU_FAN_SPEED: 779 case WMI_EVENT_GPU_FAN_SPEED: 780 if (event->event_id == WMI_EVENT_CPU_FAN_SPEED) 781 fan_data.channel = 0; 782 else 783 fan_data.channel = 1; 784 785 /* Fan speed is 16-bit value (value_low is LSB, value_high is MSB) */ 786 fan_data.speed = (event->value_high << 8) | event->value_low; 787 blocking_notifier_call_chain(&bitland_notifier_list, 788 BITLAND_NOTIFY_HWMON, 789 &fan_data); 790 break; 791 792 case WMI_EVENT_AIRPLANE_MODE: 793 case WMI_EVENT_TOUCHPAD_STATE: 794 case WMI_EVENT_FNLOCK_STATE: 795 case WMI_EVENT_KBD_MODE: 796 case WMI_EVENT_CAPSLOCK_STATE: 797 case WMI_EVENT_NUMLOCK_STATE: 798 case WMI_EVENT_SCROLLLOCK_STATE: 799 case WMI_EVENT_REFRESH_RATE: 800 case WMI_EVENT_WIN_KEY_LOCK: 801 /* These events are informational or handled by firmware */ 802 dev_dbg(&wdev->dev, "State change event: id=%d value=%d\n", 803 event->event_id, event->value_low); 804 break; 805 806 default: 807 dev_dbg(&wdev->dev, "Unknown event: id=0x%02x value=0x%02x\n", 808 event->event_id, event->value_low); 809 break; 810 } 811 } 812 813 static const struct wmi_device_id bitland_mifs_wmi_id_table[] = { 814 { BITLAND_MIFS_GUID, (void *)BITLAND_WMI_CONTROL }, 815 { BITLAND_EVENT_GUID, (void *)BITLAND_WMI_EVENT }, 816 {} 817 }; 818 MODULE_DEVICE_TABLE(wmi, bitland_mifs_wmi_id_table); 819 820 static struct wmi_driver bitland_mifs_wmi_driver = { 821 .no_singleton = true, 822 .driver = { 823 .name = DRV_NAME, 824 .dev_groups = laptop_groups, 825 .pm = pm_sleep_ptr(&bitland_mifs_wmi_pm_ops), 826 }, 827 .id_table = bitland_mifs_wmi_id_table, 828 .min_event_size = sizeof(struct bitland_mifs_event), 829 .probe = bitland_mifs_wmi_probe, 830 .notify_new = bitland_mifs_wmi_notify, 831 }; 832 833 module_wmi_driver(bitland_mifs_wmi_driver); 834 835 MODULE_AUTHOR("Mingyou Chen <qby140326@gmail.com>"); 836 MODULE_DESCRIPTION("Bitland MIFS (MiInterface) WMI driver"); 837 MODULE_LICENSE("GPL"); 838