diff options
author | Corentin Chary <corentincj@iksaif.net> | 2011-02-06 07:28:39 -0500 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2011-03-28 06:05:18 -0400 |
commit | b71872650fe967eb0a38aa0d7dcbe9c60d160032 (patch) | |
tree | efaf18d28433d1cba20352538329c1d9bd8c2306 | |
parent | 54c799a50f58285f5f6a93d87470cba1847943a3 (diff) |
eeepc-wmi: support backlight power (bl_power) attribute
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
-rw-r--r-- | drivers/platform/x86/eeepc-wmi.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 75dd692d31ee..910eb00fb13e 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c | |||
@@ -73,13 +73,16 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID); | |||
73 | #define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013 | 73 | #define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013 |
74 | #define EEEPC_WMI_DEVID_WIMAX 0x00010017 | 74 | #define EEEPC_WMI_DEVID_WIMAX 0x00010017 |
75 | #define EEEPC_WMI_DEVID_WWAN3G 0x00010019 | 75 | #define EEEPC_WMI_DEVID_WWAN3G 0x00010019 |
76 | #define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012 | 76 | #define EEEPC_WMI_DEVID_BACKLIGHT 0x00050011 |
77 | #define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012 | ||
77 | #define EEEPC_WMI_DEVID_CAMERA 0x00060013 | 78 | #define EEEPC_WMI_DEVID_CAMERA 0x00060013 |
78 | #define EEEPC_WMI_DEVID_CARDREADER 0x00080013 | 79 | #define EEEPC_WMI_DEVID_CARDREADER 0x00080013 |
79 | #define EEEPC_WMI_DEVID_TPDLED 0x00100011 | 80 | #define EEEPC_WMI_DEVID_TPDLED 0x00100011 |
80 | 81 | ||
81 | #define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001 | 82 | #define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001 |
82 | #define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000 | 83 | #define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000 |
84 | #define EEEPC_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF | ||
85 | #define EEEPC_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00 | ||
83 | 86 | ||
84 | static bool hotplug_wireless; | 87 | static bool hotplug_wireless; |
85 | 88 | ||
@@ -262,7 +265,7 @@ static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param, | |||
262 | } | 265 | } |
263 | 266 | ||
264 | /* Helper for special devices with magic return codes */ | 267 | /* Helper for special devices with magic return codes */ |
265 | static int eeepc_wmi_get_devstate_simple(u32 dev_id) | 268 | static int eeepc_wmi_get_devstate_bits(u32 dev_id, u32 mask) |
266 | { | 269 | { |
267 | u32 retval = 0; | 270 | u32 retval = 0; |
268 | acpi_status status; | 271 | acpi_status status; |
@@ -275,7 +278,12 @@ static int eeepc_wmi_get_devstate_simple(u32 dev_id) | |||
275 | if (!(retval & EEEPC_WMI_DSTS_PRESENCE_BIT)) | 278 | if (!(retval & EEEPC_WMI_DSTS_PRESENCE_BIT)) |
276 | return -ENODEV; | 279 | return -ENODEV; |
277 | 280 | ||
278 | return retval & EEEPC_WMI_DSTS_STATUS_BIT; | 281 | return retval & mask; |
282 | } | ||
283 | |||
284 | static int eeepc_wmi_get_devstate_simple(u32 dev_id) | ||
285 | { | ||
286 | return eeepc_wmi_get_devstate_bits(dev_id, EEEPC_WMI_DSTS_STATUS_BIT); | ||
279 | } | 287 | } |
280 | 288 | ||
281 | /* | 289 | /* |
@@ -770,34 +778,53 @@ exit: | |||
770 | /* | 778 | /* |
771 | * Backlight | 779 | * Backlight |
772 | */ | 780 | */ |
781 | static int read_backlight_power(void) | ||
782 | { | ||
783 | int ret = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BACKLIGHT); | ||
784 | |||
785 | if (ret < 0) | ||
786 | return ret; | ||
787 | |||
788 | return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; | ||
789 | } | ||
790 | |||
773 | static int read_brightness(struct backlight_device *bd) | 791 | static int read_brightness(struct backlight_device *bd) |
774 | { | 792 | { |
775 | u32 retval; | 793 | u32 retval; |
776 | acpi_status status; | 794 | acpi_status status; |
777 | 795 | ||
778 | status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval); | 796 | status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BRIGHTNESS, &retval); |
779 | 797 | ||
780 | if (ACPI_FAILURE(status)) | 798 | if (ACPI_FAILURE(status)) |
781 | return -1; | 799 | return -EIO; |
782 | else | 800 | else |
783 | return retval & 0xFF; | 801 | return retval & EEEPC_WMI_DSTS_BRIGHTNESS_MASK; |
784 | } | 802 | } |
785 | 803 | ||
786 | static int update_bl_status(struct backlight_device *bd) | 804 | static int update_bl_status(struct backlight_device *bd) |
787 | { | 805 | { |
788 | |||
789 | u32 ctrl_param; | 806 | u32 ctrl_param; |
790 | acpi_status status; | 807 | acpi_status status; |
808 | int power; | ||
791 | 809 | ||
792 | ctrl_param = bd->props.brightness; | 810 | ctrl_param = bd->props.brightness; |
793 | 811 | ||
794 | status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT, | 812 | status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BRIGHTNESS, |
795 | ctrl_param, NULL); | 813 | ctrl_param, NULL); |
796 | 814 | ||
797 | if (ACPI_FAILURE(status)) | 815 | if (ACPI_FAILURE(status)) |
798 | return -1; | 816 | return -EIO; |
799 | else | 817 | |
800 | return 0; | 818 | power = read_backlight_power(); |
819 | if (power != -ENODEV && bd->props.power != power) { | ||
820 | ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK); | ||
821 | status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT, | ||
822 | ctrl_param, NULL); | ||
823 | |||
824 | if (ACPI_FAILURE(status)) | ||
825 | return -EIO; | ||
826 | } | ||
827 | return 0; | ||
801 | } | 828 | } |
802 | 829 | ||
803 | static const struct backlight_ops eeepc_wmi_bl_ops = { | 830 | static const struct backlight_ops eeepc_wmi_bl_ops = { |
@@ -827,9 +854,29 @@ static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc) | |||
827 | { | 854 | { |
828 | struct backlight_device *bd; | 855 | struct backlight_device *bd; |
829 | struct backlight_properties props; | 856 | struct backlight_properties props; |
857 | int max; | ||
858 | int power; | ||
859 | |||
860 | max = eeepc_wmi_get_devstate_bits(EEEPC_WMI_DEVID_BRIGHTNESS, | ||
861 | EEEPC_WMI_DSTS_MAX_BRIGTH_MASK); | ||
862 | power = read_backlight_power(); | ||
863 | |||
864 | if (max < 0 && power < 0) { | ||
865 | /* Try to keep the original error */ | ||
866 | if (max == -ENODEV && power == -ENODEV) | ||
867 | return -ENODEV; | ||
868 | if (max != -ENODEV) | ||
869 | return max; | ||
870 | else | ||
871 | return power; | ||
872 | } | ||
873 | if (max == -ENODEV) | ||
874 | max = 0; | ||
875 | if (power == -ENODEV) | ||
876 | power = FB_BLANK_UNBLANK; | ||
830 | 877 | ||
831 | memset(&props, 0, sizeof(struct backlight_properties)); | 878 | memset(&props, 0, sizeof(struct backlight_properties)); |
832 | props.max_brightness = 15; | 879 | props.max_brightness = max; |
833 | bd = backlight_device_register(EEEPC_WMI_FILE, | 880 | bd = backlight_device_register(EEEPC_WMI_FILE, |
834 | &eeepc->platform_device->dev, eeepc, | 881 | &eeepc->platform_device->dev, eeepc, |
835 | &eeepc_wmi_bl_ops, &props); | 882 | &eeepc_wmi_bl_ops, &props); |
@@ -841,7 +888,7 @@ static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc) | |||
841 | eeepc->backlight_device = bd; | 888 | eeepc->backlight_device = bd; |
842 | 889 | ||
843 | bd->props.brightness = read_brightness(bd); | 890 | bd->props.brightness = read_brightness(bd); |
844 | bd->props.power = FB_BLANK_UNBLANK; | 891 | bd->props.power = power; |
845 | backlight_update_status(bd); | 892 | backlight_update_status(bd); |
846 | 893 | ||
847 | return 0; | 894 | return 0; |
@@ -1202,7 +1249,7 @@ static int __init eeepc_wmi_add(struct platform_device *pdev) | |||
1202 | 1249 | ||
1203 | if (!acpi_video_backlight_support()) { | 1250 | if (!acpi_video_backlight_support()) { |
1204 | err = eeepc_wmi_backlight_init(eeepc); | 1251 | err = eeepc_wmi_backlight_init(eeepc); |
1205 | if (err) | 1252 | if (err && err != -ENODEV) |
1206 | goto fail_backlight; | 1253 | goto fail_backlight; |
1207 | } else | 1254 | } else |
1208 | pr_info("Backlight controlled by ACPI video driver\n"); | 1255 | pr_info("Backlight controlled by ACPI video driver\n"); |