Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/i8042.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define CLEVO_MAIL_LED_OFF		0x0084
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #define CLEVO_MAIL_LED_BLINK_1HZ	0x008A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define CLEVO_MAIL_LED_BLINK_0_5HZ	0x0083
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) MODULE_DESCRIPTION("Clevo mail LED driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) static bool nodetect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) module_param_named(nodetect, nodetect, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) MODULE_PARM_DESC(nodetect, "Skip DMI hardware detection");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	pr_info("'%s' found\n", id->ident);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * struct clevo_mail_led_dmi_table - List of known good models
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * Contains the known good models this driver is compatible with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * When adding a new model try to be as strict as possible. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * makes it possible to keep the false positives (the model is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * detected as working, but in reality it is not) as low as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * possible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static const struct dmi_system_id clevo_mail_led_dmi_table[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		.callback = clevo_mail_led_dmi_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		.ident = "Clevo D410J",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		.matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			DMI_MATCH(DMI_SYS_VENDOR, "VIA"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 			DMI_MATCH(DMI_PRODUCT_NAME, "K8N800"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			DMI_MATCH(DMI_PRODUCT_VERSION, "VT8204B")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		.callback = clevo_mail_led_dmi_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		.ident = "Clevo M5x0N",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		.matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			DMI_MATCH(DMI_PRODUCT_NAME, "M5x0N")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		.callback = clevo_mail_led_dmi_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		.ident = "Clevo M5x0V",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		.matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 			DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		.callback = clevo_mail_led_dmi_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		.ident = "Clevo D400P",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		.matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			DMI_MATCH(DMI_BOARD_VENDOR, "Clevo"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 			DMI_MATCH(DMI_BOARD_NAME, "D400P"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			DMI_MATCH(DMI_BOARD_VERSION, "Rev.A"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			DMI_MATCH(DMI_PRODUCT_VERSION, "0106")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		.callback = clevo_mail_led_dmi_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		.ident = "Clevo D410V",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		.matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			DMI_MATCH(DMI_BOARD_VENDOR, "Clevo, Co."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			DMI_MATCH(DMI_BOARD_NAME, "D400V/D470V"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			DMI_MATCH(DMI_BOARD_VERSION, "SS78B"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev. A1")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) MODULE_DEVICE_TABLE(dmi, clevo_mail_led_dmi_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static void clevo_mail_led_set(struct led_classdev *led_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 				enum led_brightness value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	i8042_lock_chip();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (value == LED_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		i8042_command(NULL, CLEVO_MAIL_LED_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	else if (value <= LED_HALF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	i8042_unlock_chip();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int clevo_mail_led_blink(struct led_classdev *led_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				unsigned long *delay_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 				unsigned long *delay_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	int status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	i8042_lock_chip();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		/* Special case: the leds subsystem requested us to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		 * chose one user friendly blinking of the LED, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		 * start it. Let's blink the led slowly (0.5Hz).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		*delay_on = 1000; /* ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		*delay_off = 1000; /* ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	} else if (*delay_on == 500 /* ms */ && *delay_off == 500 /* ms */) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		/* blink the led with 1Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	} else if (*delay_on == 1000 /* ms */ && *delay_off == 1000 /* ms */) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		/* blink the led with 0.5Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		i8042_command(NULL, CLEVO_MAIL_LED_BLINK_0_5HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		pr_debug("clevo_mail_led_blink(..., %lu, %lu),"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		       " returning -EINVAL (unsupported)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		       *delay_on, *delay_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	i8042_unlock_chip();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static struct led_classdev clevo_mail_led = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	.name			= "clevo::mail",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	.brightness_set		= clevo_mail_led_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	.blink_set		= clevo_mail_led_blink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	.flags			= LED_CORE_SUSPENDRESUME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int __init clevo_mail_led_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	return led_classdev_register(&pdev->dev, &clevo_mail_led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int clevo_mail_led_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	led_classdev_unregister(&clevo_mail_led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static struct platform_driver clevo_mail_led_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	.remove		= clevo_mail_led_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	.driver		= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		.name		= KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int __init clevo_mail_led_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	/* Check with the help of DMI if we are running on supported hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (!nodetect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		count = dmi_check_system(clevo_mail_led_dmi_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		pr_err("Skipping DMI detection. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		       "If the driver works on your hardware please "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		       "report model and the output of dmidecode in tracker "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		       "at http://sourceforge.net/projects/clevo-mailled/\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	if (!IS_ERR(pdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		error = platform_driver_probe(&clevo_mail_led_driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 					      clevo_mail_led_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			pr_err("Can't probe platform driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 			platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		error = PTR_ERR(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void __exit clevo_mail_led_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	platform_driver_unregister(&clevo_mail_led_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	clevo_mail_led_set(NULL, LED_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) module_init(clevo_mail_led_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) module_exit(clevo_mail_led_exit);