Add hw_control_configure helper to configure how the LED should work in hardware mode. The function require to support the particular trigger and will use the passed flag to elaborate the data and apply the correct configuration. This function will then be used by the trigger to request and update hardware configuration. Signed-off-by: Christian Marangi <ansuelsmth@xxxxxxxxx> --- Documentation/leds/leds-class.rst | 60 +++++++++++++++++++++++++++++++ include/linux/leds.h | 43 ++++++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-class.rst index 984d73499d83..8a23589e9fca 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -200,10 +200,70 @@ The LED must implement 3 main API: It's advised to the driver to put the LED in the old state but this is not enforcerd and putting the LED off is also accepted. +- hw_control_configure(): + This will be used to configure the various blink modes LED support + in hardware mode. + With LED_BLINK_HW_CONTROLLED blink_mode hw_control_status/start/stop is optional and any software only trigger will reject activation as the LED supports only hardware mode. +Where a trigger has support for hardware controlled blink modes, +hw_control_configure() will be used to check whether a particular blink mode +is supported and configure the blink mode using various specific command. + +hw_control_configure() takes 3 arguments: + +- struct led_classdev *led_cdev + +- unsigned long flag: + This can be used for multiple purpose based on passed command + in the 3rd argument of this function. + It may be NULL if the 3rd argument doesn't require them. + + The unsigned long flag is specific to the trigger and its meaning + change across different triggers. + For this exact reason LED driver needs to declare explicit support + for the trigger supporting hardware blink mode. + The driver should return -EOPNOTSUPP if asked to enter in hardware + blink mode with an unsupported trigger. + + The LED driver may also report -EOPNOTSUPP if the requested flag + are rejected and can't be handled in hw blink mode by the LED. + + Flag can both be a single blink mode or a set of multiple blink + mode. LED driver must be able to handle both cases. + +- enum led_blink_hw_cmd cmd: + This is used to request to the LED driver various operation. + + They may return -EOPNOTSUPP or -EINVAL based on the provided flags. + +hw_control_configure() supports the following cmd: + +- LED_BLINK_HW_ENABLE: + enable the blink mode requested in flag. Returns 0 or a negative + error. + +- LED_BLINK_HW_DISABLE: + disable the blink mode requested in flag. Returns 0 or a negative + error. + +- LED_BLINK_HW_STATUS: + read the status of the blink mode requested in flag. Return a mask + of the enabled blink mode requested in flag or a negative error. + +- LED_BLINK_HW_SUPPORTED: + ask the LED driver if the blink mode requested in flag is supported. + Return 1 if supported or a negative error in any other case. + +- LED_BLINK_HW_RESET: + reset any blink mode currently active. Value in flag are ignored. + Return 0 or a negative error. + + LED driver can set the blink mode to a default state or keep everything + disabled. + Known Issues ============ diff --git a/include/linux/leds.h b/include/linux/leds.h index 5c360fba9ccf..c25558ca5f85 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -94,6 +94,14 @@ enum led_blink_modes { LED_BLINK_SWHW_CONTROLLED, }; +enum led_blink_hw_cmd { + LED_BLINK_HW_ENABLE, /* Enable the hardware blink mode */ + LED_BLINK_HW_DISABLE, /* Disable the hardware blink mode */ + LED_BLINK_HW_STATUS, /* Read the status of the hardware blink mode */ + LED_BLINK_HW_SUPPORTED, /* Ask the driver if the hardware blink mode is supported */ + LED_BLINK_HW_RESET, /* Reset any hardware blink active */ +}; + struct led_classdev { const char *name; unsigned int brightness; @@ -199,6 +207,17 @@ struct led_classdev { * the old status but that is not mandatory and also putting it off is accepted. */ int (*hw_control_stop)(struct led_classdev *led_cdev); + /* This will be used to configure the various blink modes LED support in hardware + * mode. + * The LED driver require to support the active trigger and will elaborate the + * unsigned long flag and do the operation based on the provided cmd. + * Current operation are enable,disable,supported and status. + * A trigger will use this to enable or disable the asked blink mode, check the + * status of the blink mode or ask if the blink mode can run in hardware mode. + */ + int (*hw_control_configure)(struct led_classdev *led_cdev, + unsigned long flag, + enum led_blink_hw_cmd cmd); #endif #ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED @@ -473,6 +492,30 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev) return led_cdev->trigger_data; } +#ifdef CONFIG_LEDS_HARDWARE_CONTROL +static inline bool led_trigger_blink_mode_is_supported(struct led_classdev *led_cdev, + unsigned long flag) +{ + int ret; + + /* Sanity check: make sure led support hw mode */ + if (led_cdev->blink_mode == LED_BLINK_SW_CONTROLLED) + return false; + + ret = led_cdev->hw_control_configure(led_cdev, flag, LED_BLINK_HW_SUPPORTED); + if (ret > 0) + return true; + + return false; +} +#else +static inline bool led_trigger_blink_mode_is_supported(struct led_classdev *led_cdev, + unsigned long flag) +{ + return false; +} +#endif + /** * led_trigger_rename_static - rename a trigger * @name: the new trigger name -- 2.38.1