diff options
author | Maxim Mikityanskiy <maxtram95@gmail.com> | 2012-12-15 12:31:28 -0500 |
---|---|---|
committer | Matthew Garrett <matthew.garrett@nebula.com> | 2013-02-24 17:49:53 -0500 |
commit | 0de6575ad0a8f19ccf91d6e783b2a1bba0edb7a5 (patch) | |
tree | c0a0de3f282a6f9c9c2b4670bd2db03cd46725ae | |
parent | 0816392b97d45b779c6ab2cfac4e1561d3ef7242 (diff) |
msi-laptop: Add MSI Wind U90/U100 support
Add MSI Wind U90/U100 to DMI table and add some missing EC features
support such as basic fan control, turbo and ECO modes and touchpad
state. Tested on MSI Wind U100.
Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
Signed-off-by: Lee, Chun-Yi <jlee@suse.com>
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
-rw-r--r-- | drivers/platform/x86/msi-laptop.c | 123 |
1 files changed, 121 insertions, 2 deletions
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 0bf94b5c2744..28bcbb21d120 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c | |||
@@ -82,8 +82,19 @@ | |||
82 | #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d | 82 | #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d |
83 | #define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) | 83 | #define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0) |
84 | 84 | ||
85 | #define MSI_STANDARD_EC_TOUCHPAD_ADDRESS 0xe4 | 85 | #define MSI_STANDARD_EC_FUNCTIONS_ADDRESS 0xe4 |
86 | /* Power LED is orange - Turbo mode */ | ||
87 | #define MSI_STANDARD_EC_TURBO_MASK (1 << 1) | ||
88 | /* Power LED is green - ECO mode */ | ||
89 | #define MSI_STANDARD_EC_ECO_MASK (1 << 3) | ||
90 | /* Touchpad is turned on */ | ||
86 | #define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4) | 91 | #define MSI_STANDARD_EC_TOUCHPAD_MASK (1 << 4) |
92 | /* If this bit != bit 1, turbo mode can't be toggled */ | ||
93 | #define MSI_STANDARD_EC_TURBO_COOLDOWN_MASK (1 << 7) | ||
94 | |||
95 | #define MSI_STANDARD_EC_FAN_ADDRESS 0x33 | ||
96 | /* If zero, fan rotates at maximal speed */ | ||
97 | #define MSI_STANDARD_EC_AUTOFAN_MASK (1 << 0) | ||
87 | 98 | ||
88 | #ifdef CONFIG_PM_SLEEP | 99 | #ifdef CONFIG_PM_SLEEP |
89 | static int msi_laptop_resume(struct device *device); | 100 | static int msi_laptop_resume(struct device *device); |
@@ -435,18 +446,115 @@ static ssize_t store_auto_brightness(struct device *dev, | |||
435 | return count; | 446 | return count; |
436 | } | 447 | } |
437 | 448 | ||
449 | static ssize_t show_touchpad(struct device *dev, | ||
450 | struct device_attribute *attr, char *buf) | ||
451 | { | ||
452 | |||
453 | u8 rdata; | ||
454 | int result; | ||
455 | |||
456 | result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); | ||
457 | if (result < 0) | ||
458 | return result; | ||
459 | |||
460 | return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_TOUCHPAD_MASK)); | ||
461 | } | ||
462 | |||
463 | static ssize_t show_turbo(struct device *dev, | ||
464 | struct device_attribute *attr, char *buf) | ||
465 | { | ||
466 | |||
467 | u8 rdata; | ||
468 | int result; | ||
469 | |||
470 | result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); | ||
471 | if (result < 0) | ||
472 | return result; | ||
473 | |||
474 | return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_TURBO_MASK)); | ||
475 | } | ||
476 | |||
477 | static ssize_t show_eco(struct device *dev, | ||
478 | struct device_attribute *attr, char *buf) | ||
479 | { | ||
480 | |||
481 | u8 rdata; | ||
482 | int result; | ||
483 | |||
484 | result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); | ||
485 | if (result < 0) | ||
486 | return result; | ||
487 | |||
488 | return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_ECO_MASK)); | ||
489 | } | ||
490 | |||
491 | static ssize_t show_turbo_cooldown(struct device *dev, | ||
492 | struct device_attribute *attr, char *buf) | ||
493 | { | ||
494 | |||
495 | u8 rdata; | ||
496 | int result; | ||
497 | |||
498 | result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); | ||
499 | if (result < 0) | ||
500 | return result; | ||
501 | |||
502 | return sprintf(buf, "%i\n", (!!(rdata & MSI_STANDARD_EC_TURBO_MASK)) | | ||
503 | (!!(rdata & MSI_STANDARD_EC_TURBO_COOLDOWN_MASK) << 1)); | ||
504 | } | ||
505 | |||
506 | static ssize_t show_auto_fan(struct device *dev, | ||
507 | struct device_attribute *attr, char *buf) | ||
508 | { | ||
509 | |||
510 | u8 rdata; | ||
511 | int result; | ||
512 | |||
513 | result = ec_read(MSI_STANDARD_EC_FAN_ADDRESS, &rdata); | ||
514 | if (result < 0) | ||
515 | return result; | ||
516 | |||
517 | return sprintf(buf, "%i\n", !!(rdata & MSI_STANDARD_EC_AUTOFAN_MASK)); | ||
518 | } | ||
519 | |||
520 | static ssize_t store_auto_fan(struct device *dev, | ||
521 | struct device_attribute *attr, const char *buf, size_t count) | ||
522 | { | ||
523 | |||
524 | int enable, result; | ||
525 | |||
526 | if (sscanf(buf, "%i", &enable) != 1 || (enable != (enable & 1))) | ||
527 | return -EINVAL; | ||
528 | |||
529 | result = ec_write(MSI_STANDARD_EC_FAN_ADDRESS, enable); | ||
530 | if (result < 0) | ||
531 | return result; | ||
532 | |||
533 | return count; | ||
534 | } | ||
535 | |||
438 | static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); | 536 | static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); |
439 | static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, | 537 | static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, |
440 | store_auto_brightness); | 538 | store_auto_brightness); |
441 | static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); | 539 | static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); |
442 | static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); | 540 | static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); |
443 | static DEVICE_ATTR(threeg, 0444, show_threeg, NULL); | 541 | static DEVICE_ATTR(threeg, 0444, show_threeg, NULL); |
542 | static DEVICE_ATTR(touchpad, 0444, show_touchpad, NULL); | ||
543 | static DEVICE_ATTR(turbo_mode, 0444, show_turbo, NULL); | ||
544 | static DEVICE_ATTR(eco_mode, 0444, show_eco, NULL); | ||
545 | static DEVICE_ATTR(turbo_cooldown, 0444, show_turbo_cooldown, NULL); | ||
546 | static DEVICE_ATTR(auto_fan, 0644, show_auto_fan, store_auto_fan); | ||
444 | 547 | ||
445 | static struct attribute *msipf_attributes[] = { | 548 | static struct attribute *msipf_attributes[] = { |
446 | &dev_attr_lcd_level.attr, | 549 | &dev_attr_lcd_level.attr, |
447 | &dev_attr_auto_brightness.attr, | 550 | &dev_attr_auto_brightness.attr, |
448 | &dev_attr_bluetooth.attr, | 551 | &dev_attr_bluetooth.attr, |
449 | &dev_attr_wlan.attr, | 552 | &dev_attr_wlan.attr, |
553 | &dev_attr_touchpad.attr, | ||
554 | &dev_attr_turbo_mode.attr, | ||
555 | &dev_attr_eco_mode.attr, | ||
556 | &dev_attr_turbo_cooldown.attr, | ||
557 | &dev_attr_auto_fan.attr, | ||
450 | NULL | 558 | NULL |
451 | }; | 559 | }; |
452 | 560 | ||
@@ -590,6 +698,16 @@ static struct dmi_system_id __initdata msi_dmi_table[] = { | |||
590 | .driver_data = &quirk_load_scm_model, | 698 | .driver_data = &quirk_load_scm_model, |
591 | .callback = dmi_check_cb | 699 | .callback = dmi_check_cb |
592 | }, | 700 | }, |
701 | { | ||
702 | .ident = "MSI U90/U100", | ||
703 | .matches = { | ||
704 | DMI_MATCH(DMI_SYS_VENDOR, | ||
705 | "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
706 | DMI_MATCH(DMI_PRODUCT_NAME, "U90/U100"), | ||
707 | }, | ||
708 | .driver_data = &quirk_load_scm_ro_model, | ||
709 | .callback = dmi_check_cb | ||
710 | }, | ||
593 | { } | 711 | { } |
594 | }; | 712 | }; |
595 | 713 | ||
@@ -679,7 +797,7 @@ static void msi_send_touchpad_key(struct work_struct *ignored) | |||
679 | u8 rdata; | 797 | u8 rdata; |
680 | int result; | 798 | int result; |
681 | 799 | ||
682 | result = ec_read(MSI_STANDARD_EC_TOUCHPAD_ADDRESS, &rdata); | 800 | result = ec_read(MSI_STANDARD_EC_FUNCTIONS_ADDRESS, &rdata); |
683 | if (result < 0) | 801 | if (result < 0) |
684 | return; | 802 | return; |
685 | 803 | ||
@@ -1069,3 +1187,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N051:*"); | |||
1069 | MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*"); | 1187 | MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N014:*"); |
1070 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*"); | 1188 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnCR620:*"); |
1071 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*"); | 1189 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational*:pnU270series:*"); |
1190 | MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnU90/U100:*"); | ||