1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (c) 2021, AAEON Ltd.
7 * Author: Kunyang Fan <kunyang_fan@aaeon.com.tw>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 #include <linux/acpi.h>
15 #include <linux/bitops.h>
16 #include <linux/leds.h>
17 #include <linux/module.h>
18 #include <linux/platform_data/x86/asus-wmi.h>
19 #include <linux/platform_device.h>
21 #define DRVNAME "led_aaeon"
22 #define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
23 #define AAEON_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
25 #define GET_LED_NUMBER_ID 0x00060000
26 #define GET_LED_METHOD_ID 0x00060001
27 #define SET_LED_METHOD_ID 0x00060002
28 #define GET_LED_NUMBER_METHOD_ID 0x10
31 struct aaeon_led_data
{
33 struct led_classdev cdev
;
36 static int aaeon_led_get_number(void)
40 err
= asus_wmi_evaluate_method(GET_LED_NUMBER_ID
,
41 GET_LED_NUMBER_METHOD_ID
,
49 static enum led_brightness
aaeon_led_brightness_get(struct led_classdev
53 struct aaeon_led_data
*led
=
54 container_of(cdev
, struct aaeon_led_data
, cdev
);
57 arg0
= (u32
)(led
->id
& 0xF);
58 err
= asus_wmi_evaluate_method(GET_LED_METHOD_ID
, arg0
, 0, &brightness
);
65 static void aaeon_led_brightness_set(struct led_classdev
*cdev
,
66 enum led_brightness brightness
)
69 struct aaeon_led_data
*led
=
70 container_of(cdev
, struct aaeon_led_data
, cdev
);
73 arg0
= (u32
)(led
->id
& 0xF);
74 if (brightness
!= LED_OFF
)
77 err
= asus_wmi_evaluate_method(SET_LED_METHOD_ID
, arg0
, 0, &retval
);
80 static int __init
aaeon_add_led_device(struct platform_device
*pdev
,
83 struct aaeon_led_data
*led
;
85 led
= devm_kzalloc(&pdev
->dev
, sizeof(struct aaeon_led_data
), GFP_KERNEL
);
90 led
->cdev
.brightness_get
= aaeon_led_brightness_get
;
91 led
->cdev
.brightness_set
= aaeon_led_brightness_set
;
92 led
->cdev
.name
= devm_kasprintf(&pdev
->dev
, GFP_KERNEL
, "led:%d:", id
);
97 return devm_led_classdev_register(&pdev
->dev
, &led
->cdev
);
100 static int aaeon_led_probe(struct platform_device
*pdev
)
102 int err
= -ENODEV
, i
;
105 pr_debug("aaeon led device probe!\n");
106 /* Prevent other drivers adding this platfom device */
107 if (!wmi_has_guid(AAEON_WMI_MGMT_GUID
)) {
108 pr_debug("AAEON Management GUID not found\n");
112 /* Query the number of led devices board support */
113 led_number
= aaeon_led_get_number();
116 * If the number is 0 or can't get the number of leds,
117 * no need to register any led device node.
122 for (i
= 0; i
< led_number
; i
++) {
123 err
= aaeon_add_led_device(pdev
, i
);
131 static struct platform_driver aaeon_led_driver
= {
133 .name
= "leds-aaeon",
137 module_platform_driver_probe(aaeon_led_driver
, aaeon_led_probe
);
139 MODULE_ALIAS("platform:leds-aaeon");
140 MODULE_DESCRIPTION("AAEON LED Driver");
141 MODULE_AUTHOR("Kunyang Fan <kunyang_fan@asus.com>");
142 MODULE_LICENSE("GPL v2");