[GIT PULL] Staging/IIO driver fixes for 5.13-rc2
The following changes since commit 6efb943b8616ec53a5e444193dccf1af9ad627b5: Linux 5.13-rc1 (2021-05-09 14:17:44 -0700) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git tags/staging-5.13-rc2 for you to fetch changes up to ba9c25d94dea1a57492a606a1f5dde70d2432583: Merge tag 'iio-fixes-5.13a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus (2021-05-11 15:17:55 +0200) Staging/IIO driver fixes for 5.13-rc2 Here are some small IIO driver fixes and one Staging driver fix for 5.13-rc2. Nothing major, just some resolutions for reported problems: - gcc11 bogus warning fix for rtl8723bs - iio driver tiny fixes All of these have been in linux-next for many days with no reported issues. Signed-off-by: Greg Kroah-Hartman Alexandru Ardelean (2): iio: hid-sensors: select IIO_TRIGGERED_BUFFER under HID_SENSOR_IIO_TRIGGER iio: core: return ENODEV if ioctl is unknown Arnd Bergmann (1): staging: rtl8723bs: avoid bogus gcc warning Colin Ian King (1): iio: tsl2583: Fix division by a zero lux_val Dinghao Liu (2): iio: light: gp2ap002: Fix rumtime PM imbalance on error iio: proximity: pulsedlight: Fix rumtime PM imbalance on error Dmitry Osipenko (1): iio: gyro: mpu3050: Fix reported temperature value Greg Kroah-Hartman (1): Merge tag 'iio-fixes-5.13a' of https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus Tomasz Duszynski (1): iio: core: fix ioctl handlers removal drivers/iio/accel/Kconfig | 1 - drivers/iio/common/hid-sensors/Kconfig| 1 + drivers/iio/gyro/Kconfig | 1 - drivers/iio/gyro/mpu3050-core.c | 13 +++-- drivers/iio/humidity/Kconfig | 1 - drivers/iio/industrialio-core.c | 9 + drivers/iio/light/Kconfig | 2 -- drivers/iio/light/gp2ap002.c | 5 +++-- drivers/iio/light/tsl2583.c | 8 drivers/iio/magnetometer/Kconfig | 1 - drivers/iio/orientation/Kconfig | 2 -- drivers/iio/pressure/Kconfig | 1 - drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 1 + drivers/iio/temperature/Kconfig | 1 - drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 23 +-- drivers/staging/rtl8723bs/os_dep/ioctl_linux.c| 21 - 16 files changed, 50 insertions(+), 41 deletions(-) ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 03/17] staging: nuc-wmi: add support for changing S0 brightness
Now that the core logic is in place, let's add support to adjust the S0 brightness level. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 79 +++ 1 file changed, 79 insertions(+) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index b75ddd47e443..62c2764814dd 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -392,7 +392,85 @@ static ssize_t store_indicator(struct device *dev, return -EINVAL; } +/* Get S0 brightness */ +static ssize_t show_s0_brightness(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 cmd, input[NUM_INPUT_ARGS] = { 0 }; + u8 output[NUM_OUTPUT_ARGS]; + int ret; + + cmd = LED_NEW_GET_STATUS; + input[0] = LED_NEW_GET_CONTROL_ITEM; + input[1] = led->id; + input[2] = led->indicator; + input[3] = 0; + + ret = nuc_nmi_cmd(dev, cmd, input, output); + if (ret) + return ret; + + /* Multicolor uses a scale from 0 to 100 */ + if (led->color_type & (LED_BLUE_AMBER | LED_BLUE_WHITE | LED_RGB)) + return scnprintf(buf, PAGE_SIZE, "%d%%\n", output[0]); + + /* single color uses 0, 50% and 100% */ + return scnprintf(buf, PAGE_SIZE, "%d%%\n", output[0] * 50); +} + +/* Change S0 brightness */ +static ssize_t store_s0_brightness(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 cmd, input[NUM_INPUT_ARGS] = { 0 }; + int ret; + u8 val; + + if (led->indicator == LED_IND_DISABLE) { + dev_dbg(dev, "Led %s is disabled. ignoring it.\n", cdev->name); + return -EACCES; + } + + if (kstrtou8(buf, 0, &val) || val > 100) + return -EINVAL; + + /* +* For single-color LEDs, the value should be between 0 to 2, but, +* in order to have a consistent API, let's always handle it as if +* it is a percentage, for both multicolor and single color LEDs. +* So: +* value == 0 will disable the LED +* value up to 74% will set it the brightness to 50% +* value equal or above 75% will use the maximum brightness. +*/ + if (!(led->color_type & (LED_BLUE_AMBER | LED_BLUE_WHITE | LED_RGB))) { + if (val > 0 && val < 75) + val = 1; + if (val >= 75) + val = 2; + } + + cmd = LED_SET_VALUE; + input[0] = led->id; + input[1] = led->indicator; + input[2] = 0; /* FIXME: replace by an enum */ + input[3] = val; + + ret = nuc_nmi_cmd(dev, cmd, input, NULL); + if (ret) + return ret; + + return len; +} + static LED_ATTR_RW(indicator); +static LED_ATTR_RW(s0_brightness); /* * Attributes for multicolor LEDs @@ -400,6 +478,7 @@ static LED_ATTR_RW(indicator); static struct attribute *nuc_wmi_multicolor_led_attr[] = { &dev_attr_indicator.attr, + &dev_attr_s0_brightness.attr, NULL, }; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 02/17] staging: nuc-wmi: detect WMI API detection
There are currently 3 known API releases: - https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html - https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf - https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf Add a logic to detect between them, preventing the driver to work with an unsupported version. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 30 +++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 15d956ad8556..b75ddd47e443 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -26,6 +26,13 @@ #define NUM_INPUT_ARGS 4 #define NUM_OUTPUT_ARGS3 +enum led_api_rev { + LED_API_UNKNOWN, + LED_API_NUC6, + LED_API_REV_0_64, + LED_API_REV_1_0, +}; + enum led_cmds { LED_QUERY = 0x03, LED_NEW_GET_STATUS = 0x04, @@ -33,6 +40,7 @@ enum led_cmds { LED_SET_VALUE = 0x06, LED_NOTIFICATION= 0x07, LED_SWITCH_TYPE = 0x08, + LED_VERSION_CONTROL = 0x09, }; enum led_query_subcmd { @@ -195,7 +203,7 @@ static int nuc_wmi_query_leds(struct device *dev) struct nuc_wmi *priv = dev_get_drvdata(dev); u8 cmd, input[NUM_INPUT_ARGS] = { 0 }; u8 output[NUM_OUTPUT_ARGS]; - int i, id, ret; + int i, id, ret, ver = LED_API_UNKNOWN; u8 leds; /* @@ -209,12 +217,28 @@ static int nuc_wmi_query_leds(struct device *dev) cmd = LED_QUERY; input[0] = LED_QUERY_LIST_ALL; ret = nuc_nmi_cmd(dev, cmd, input, output); - if (ret) { + if (ret == -ENOENT) { + ver = LED_API_NUC6; + } else if (ret) { dev_warn(dev, "error %d while listing all LEDs\n", ret); return ret; + } else { + leds = output[0]; } - leds = output[0]; + if (ver != LED_API_NUC6) { + ret = nuc_nmi_cmd(dev, LED_VERSION_CONTROL, input, output); + ver = output[0] | output[1] << 16; + if (!ver) + ver = LED_API_REV_0_64; + else if (ver == 0x0126) + ver = LED_API_REV_1_0; + } + + /* Currently, only API Revision 0.64 is supported */ + if (ver != LED_API_REV_0_64) + return -ENODEV; + if (!leds) { dev_warn(dev, "No LEDs found\n"); return -ENODEV; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 10/17] staging: nuc-wmi: get rid of an unused variable
drivers/staging/nuc-led/nuc-wmi.c: In function ‘nuc_nmi_cmd’: drivers/staging/nuc-led/nuc-wmi.c:242:6: warning: variable ‘size’ set but not used [-Wunused-but-set-variable] 242 | int size, ret; | ^~~~ Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 8967c8d54dac..78b0a3279f25 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -239,7 +239,7 @@ static int nuc_nmi_cmd(struct device *dev, struct acpi_buffer input; union acpi_object *obj; acpi_status status; - int size, ret; + int ret; u8 *p; input.length = NUM_INPUT_ARGS; @@ -281,8 +281,6 @@ static int nuc_nmi_cmd(struct device *dev, goto err; } - size = NUM_OUTPUT_ARGS + 1; - if (output_args) { memcpy(output_args, p + 1, NUM_OUTPUT_ARGS); -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 12/17] staging: nuc-wmi: better detect NUC6/NUC7 devices
There's no documented way to detect if the WMI API is valid, as, when it is not valid, it just returns 4 zeros. However, as having a value of 0x00 for the blinking state is not valid, we can check for it at detection time, in order to disable LEDs control on devices that won't support it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 5bc4dcec3ea8..1a6e2b17c888 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -312,6 +312,13 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev) return ret; } + /* +* Detect if NUC6/NUC7 supports the WMI API by checking the +* returned blink state, as valid values range from 0x01 to 0x07. +*/ + if (output[1] == 0x00) + return -ENODEV; + led = &priv->led[priv->num_leds]; led->id = POWER_LED; led->color_type = LED_BLUE_AMBER; @@ -325,6 +332,14 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev) dev_warn(dev, "Get S0 Ring: error %d\n", ret); return ret; } + + /* +* Detect if NUC6/NUC7 supports the WMI API by checking the +* returned blink state, as valid values range from 0x01 to 0x07. +*/ + if (output[1] == 0x00) + return -ENODEV; + led = &priv->led[priv->num_leds]; led->id = RING_LED; led->color_type = LED_BLUE_AMBER; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 00/17] Add an experimental driver for Intel NUC leds
Hi Greg, This series add support for the LEDs found at Intel NUCs since NUC version 6. On several NUC models, the function of the LEDs are programmable, which allow them to indicate several different hardware events. They can even be programmed to represent an userspace-driven event. Some models come with single colored or dual-colored LEDs, but high end models have RGB LEDs. Programming them can ether be done via BIOS or by the OS. There are 3 different API types, and there is already some OOT drivers that were written to support them, using procfs, each one using a different (and IMO confusing) API. After looking at the existing drivers and not liking the uAPI interfaces there, I opted to write a new driver from scratch, unifying support for all different versions and using sysfs via the leds class. It should be noticed that those devices use the Windows Management Interface (WMI). There are actually 3 different implementations for it: - one for NUC6/NUC7, which has limited support for programming just two LEDs; - a complely re-written interface for NUC8, which can program up to seven LEDs, named version 0.64; - an extended version of the NUC8 API, added for NUC10, called version 1.0, with has a few differences from version 0.64. Such WMI APIs are documented at: - https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html - https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf - https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf I wrote this driver mainly for my NUC8 (NUC8i7HNK), but I used a NUC6 in order to double-check if NUC6 support was not crashing. Yet, while the NUC6 model I have accepts the WMI LED API, it doesn't work, as it seems that the BIOS of my NUC6 doesn't let userspace to program the LEDs. I don't have any devices using NUC10 API. Due to the lack of full tests on NUC6 and NUC10, and because I wrote a new uAPI that's different than the procfs-based ones found at the OOT drivers, I'm opting to submit this first to staging. This should allow adjusting the uAPI if needed, and to get feedback from people using it on NUC6, NUC10 and on other NUC models that would be compatible with it. Mauro Carvalho Chehab (17): staging: add support for NUC WMI LEDs staging: nuc-wmi: detect WMI API detection staging: nuc-wmi: add support for changing S0 brightness staging: nuc-wmi: add all types of brightness staging: nuc-wmi: allow changing the LED colors staging: nuc-wmi: add support for WMI API version 1.0 staging: nuc-wmi: add basic support for NUC6 WMI staging: muc-wmi: add brightness and color for NUC6 API staging: nuc-wmi: Add support to blink behavior for NUC8/10 staging: nuc-wmi: get rid of an unused variable staging: nuc-wmi: implement blink control for NUC6 staging: nuc-wmi: better detect NUC6/NUC7 devices staging: nuc-led: add support for HDD activity default staging: nuc-wmi: fix software blink behavior logic staging: nuc-wmi: add support for changing the ethernet type indicator staging: nuc-wmi: add support for changing the power limit scheme staging: nuc-led: update the TODOs MAINTAINERS |6 + drivers/staging/Kconfig |2 + drivers/staging/Makefile |1 + drivers/staging/nuc-led/Kconfig | 11 + drivers/staging/nuc-led/Makefile |3 + drivers/staging/nuc-led/TODO |8 + drivers/staging/nuc-led/nuc-wmi.c | 2100 + 7 files changed, 2131 insertions(+) create mode 100644 drivers/staging/nuc-led/Kconfig create mode 100644 drivers/staging/nuc-led/Makefile create mode 100644 drivers/staging/nuc-led/TODO create mode 100644 drivers/staging/nuc-led/nuc-wmi.c -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 15/17] staging: nuc-wmi: add support for changing the ethernet type indicator
The Ethernet type indicator can be configured to show the status of LAN1, LAN1 or both. Add support for it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 89 +++ 1 file changed, 89 insertions(+) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index fab0094a20e4..9e8164cd77ec 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -1695,12 +1695,100 @@ static ssize_t store_hdd_default(struct device *dev, return len; } +/* Ethernet type */ +static const char * const ethernet_type[] = { + "LAN1", + "LAN2", + "LAN1+LAN2" +}; + +static ssize_t show_ethernet_type(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS] = { 0 }; + u8 output[NUM_OUTPUT_ARGS]; + int ctrl, ret, val, i, n; + int size = PAGE_SIZE; + char *p = buf; + + if (led->indicator != LED_IND_ETHERNET) + return -EINVAL; + + ctrl = led->reg_table[led->indicator][LED_FUNC_ETH_TYPE]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + input[0] = LED_NEW_GET_CONTROL_ITEM; + input[1] = led->id; + input[2] = led->indicator; + input[3] = ctrl; + + ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output); + if (ret) + return ret; + + val = output[0]; + + for (i = 0; i < ARRAY_SIZE(ethernet_type); i++) { + if (i == val) + n = scnprintf(p, size, "[%s] ", ethernet_type[i]); + else + n = scnprintf(p, size, "%s ", ethernet_type[i]); + p += n; + size -= n; + } + size -= scnprintf(p, size, "\n"); + + return PAGE_SIZE - size; +} + +static ssize_t store_ethernet_type(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS] = { 0 }; + int ctrl, val, ret; + const char *tmp; + + if (led->indicator != LED_IND_ETHERNET) + return -EINVAL; + + ctrl = led->reg_table[led->indicator][LED_FUNC_ETH_TYPE]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + for (val = 0; val < ARRAY_SIZE(ethernet_type); val++) + if (!strcasecmp(tmp, ethernet_type[val])) + break; + + if (val >= ARRAY_SIZE(ethernet_type)) + return -EINVAL; + + input[0] = led->id; + input[1] = led->indicator; + input[2] = ctrl; + input[3] = val; + + ret = nuc_nmi_cmd(dev, LED_SET_VALUE, input, NULL); + if (ret) + return ret; + + return len; +} static LED_ATTR_RW(indicator); static LED_ATTR_RW(color); static LED_ATTR_RW(blink_behavior); static LED_ATTR_RW(blink_frequency); static LED_ATTR_RW(hdd_default); +static LED_ATTR_RW(ethernet_type); LED_ATTR_POWER_STATE_RW(s0_brightness, brightness, 0); LED_ATTR_POWER_STATE_RW(s0_blink_behavior, blink_behavior, 0); @@ -1729,6 +1817,7 @@ LED_ATTR_POWER_STATE_RW(standby_blink_frequency, blink_frequency, 2); static struct attribute *nuc_wmi_led_attr[] = { &dev_attr_indicator.attr, &dev_attr_hdd_default.attr, + &dev_attr_ethernet_type.attr, NULL, }; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 13/17] staging: nuc-led: add support for HDD activity default
There are two possible values for HDD activity behavior: - 0 Normally off, ON when active - 1 Normally on, OFF when active Implement a logic to set it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 77 +++ 1 file changed, 77 insertions(+) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 1a6e2b17c888..68143d45c34c 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -1626,10 +1626,86 @@ static umode_t nuc_wmi_led_blink_is_visible(struct kobject *kobj, return 0; } +/* HDD activity behavior */ +static ssize_t show_hdd_default(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS] = { 0 }; + u8 output[NUM_OUTPUT_ARGS]; + int ctrl, ret, val; + + if (led->indicator != LED_IND_HDD_ACTIVITY) + return -EINVAL; + + ctrl = led->reg_table[led->indicator][LED_FUNC_HDD_BEHAVIOR]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + input[0] = LED_NEW_GET_CONTROL_ITEM; + input[1] = led->id; + input[2] = led->indicator; + input[3] = ctrl; + + ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output); + if (ret) + return ret; + + val = output[0]; + + if (val == 0) + return scnprintf(buf, PAGE_SIZE, "off\n"); + + return scnprintf(buf, PAGE_SIZE, "on\n"); +} + +static ssize_t store_hdd_default(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS] = { 0 }; + int ctrl, val, ret; + const char *tmp; + + if (led->indicator != LED_IND_HDD_ACTIVITY) + return -EINVAL; + + ctrl = led->reg_table[led->indicator][LED_FUNC_HDD_BEHAVIOR]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + tmp = strsep((char **)&buf, "\n"); + if (!strcmp(tmp, "on")) + val = 1; + else if (!strcmp(tmp, "off")) + val = 0; + else + return -EINVAL; + + input[0] = led->id; + input[1] = led->indicator; + input[2] = ctrl; + input[3] = val; + + ret = nuc_nmi_cmd(dev, LED_SET_VALUE, input, NULL); + if (ret) + return ret; + + return len; +} + + static LED_ATTR_RW(indicator); static LED_ATTR_RW(color); static LED_ATTR_RW(blink_behavior); static LED_ATTR_RW(blink_frequency); +static LED_ATTR_RW(hdd_default); LED_ATTR_POWER_STATE_RW(s0_brightness, brightness, 0); LED_ATTR_POWER_STATE_RW(s0_blink_behavior, blink_behavior, 0); @@ -1657,6 +1733,7 @@ LED_ATTR_POWER_STATE_RW(standby_blink_frequency, blink_frequency, 2); static struct attribute *nuc_wmi_led_attr[] = { &dev_attr_indicator.attr, + &dev_attr_hdd_default.attr, NULL, }; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 16/17] staging: nuc-wmi: add support for changing the power limit scheme
The power limit indicator may have 2 behaviors: 1. Its color gradually changes from green to red; 2. It displays a single color Add support for it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 93 +++ 1 file changed, 93 insertions(+) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 9e8164cd77ec..2d9c49d72703 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -1764,6 +1764,8 @@ static ssize_t store_ethernet_type(struct device *dev, if (!nuc_wmi_test_control(dev, led, ctrl)) return -ENODEV; + tmp = strsep((char **)&buf, "\n"); + for (val = 0; val < ARRAY_SIZE(ethernet_type); val++) if (!strcasecmp(tmp, ethernet_type[val])) break; @@ -1783,12 +1785,102 @@ static ssize_t store_ethernet_type(struct device *dev, return len; } +/* Power Limit Indication scheme */ +static const char * const power_limit_scheme[] = { + "green to red", + "single color" +}; + +static ssize_t show_power_limit_scheme(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS] = { 0 }; + u8 output[NUM_OUTPUT_ARGS]; + int ctrl, ret, val, i, n; + int size = PAGE_SIZE; + char *p = buf; + + if (led->indicator != LED_IND_POWER_LIMIT) + return -EINVAL; + + ctrl = led->reg_table[led->indicator][LED_FUNC_POWER_STATE_NUM_CTRLS]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + input[0] = LED_NEW_GET_CONTROL_ITEM; + input[1] = led->id; + input[2] = led->indicator; + input[3] = ctrl; + + ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output); + if (ret) + return ret; + + val = output[0]; + + for (i = 0; i < ARRAY_SIZE(power_limit_scheme); i++) { + if (i == val) + n = scnprintf(p, size, "[%s] ", power_limit_scheme[i]); + else + n = scnprintf(p, size, "%s ", power_limit_scheme[i]); + p += n; + size -= n; + } + size -= scnprintf(p, size, "\n"); + + return PAGE_SIZE - size; +} + +static ssize_t store_power_limit_scheme(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS] = { 0 }; + int ctrl, val, ret; + const char *tmp; + + if (led->indicator != LED_IND_POWER_LIMIT) + return -EINVAL; + + ctrl = led->reg_table[led->indicator][LED_FUNC_POWER_STATE_NUM_CTRLS]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + tmp = strsep((char **)&buf, "\n"); + + for (val = 0; val < ARRAY_SIZE(power_limit_scheme); val++) + if (!strcasecmp(tmp, power_limit_scheme[val])) + break; + + if (val >= ARRAY_SIZE(power_limit_scheme)) + return -EINVAL; + + input[0] = led->id; + input[1] = led->indicator; + input[2] = ctrl; + input[3] = val; + + ret = nuc_nmi_cmd(dev, LED_SET_VALUE, input, NULL); + if (ret) + return ret; + + return len; +} + static LED_ATTR_RW(indicator); static LED_ATTR_RW(color); static LED_ATTR_RW(blink_behavior); static LED_ATTR_RW(blink_frequency); static LED_ATTR_RW(hdd_default); static LED_ATTR_RW(ethernet_type); +static LED_ATTR_RW(power_limit_scheme); LED_ATTR_POWER_STATE_RW(s0_brightness, brightness, 0); LED_ATTR_POWER_STATE_RW(s0_blink_behavior, blink_behavior, 0); @@ -1818,6 +1910,7 @@ static struct attribute *nuc_wmi_led_attr[] = { &dev_attr_indicator.attr, &dev_attr_hdd_default.attr, &dev_attr_ethernet_type.attr, + &dev_attr_power_limit_scheme.attr, NULL, }; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 05/17] staging: nuc-wmi: allow changing the LED colors
Add routines to allow seeing and changing the LED colors. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 244 -- 1 file changed, 228 insertions(+), 16 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 711897ba4666..07cf18e6f4c4 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -58,8 +58,6 @@ enum led_new_get_subcmd { enum led_function { LED_FUNC_BRIGHTNESS, LED_FUNC_COLOR1, - LED_FUNC_COLOR_GREEN, - LED_FUNC_COLOR_BLUE, LED_FUNC_BLINK_BEHAVIOR, LED_FUNC_BLINK_FREQ, @@ -92,43 +90,31 @@ static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = { [LED_FUNC_BLINK_BEHAVIOR] = 0x01, [LED_FUNC_BLINK_FREQ] = 0x02, [LED_FUNC_COLOR1] = 0x03, - [LED_FUNC_COLOR_GREEN] = 0x04, - [LED_FUNC_COLOR_BLUE] = 0x05 }, [LED_IND_HDD_ACTIVITY] = { [LED_FUNC_BRIGHTNESS] = 0x00, [LED_FUNC_COLOR1] = 0x01, - [LED_FUNC_COLOR_GREEN] = 0x02, - [LED_FUNC_COLOR_BLUE] = 0x03, [LED_FUNC_HDD_BEHAVIOR] = 0x04 }, [LED_IND_ETHERNET] = { [LED_FUNC_ETH_TYPE] = 0x00, [LED_FUNC_BRIGHTNESS] = 0x01, [LED_FUNC_COLOR1] = 0x02, - [LED_FUNC_COLOR_GREEN] = 0x03, - [LED_FUNC_COLOR_BLUE] = 0x04 }, [LED_IND_WIFI] = { [LED_FUNC_BRIGHTNESS] = 0x00, [LED_FUNC_COLOR1] = 0x01, - [LED_FUNC_COLOR_GREEN] = 0x02, - [LED_FUNC_COLOR_BLUE] = 0x03 }, [LED_IND_SOFTWARE] = { [LED_FUNC_BRIGHTNESS] = 0x00, [LED_FUNC_BLINK_BEHAVIOR] = 0x01, [LED_FUNC_BLINK_FREQ] = 0x02, [LED_FUNC_COLOR1] = 0x03, - [LED_FUNC_COLOR_GREEN] = 0x04, - [LED_FUNC_COLOR_BLUE] = 0x05 }, [LED_IND_POWER_LIMIT] = { [LED_FUNC_POWER_LIMIT_SCHEME] = 0x00, [LED_FUNC_BRIGHTNESS] = 0x01, [LED_FUNC_COLOR1] = 0x02, - [LED_FUNC_COLOR_GREEN] = 0x03, - [LED_FUNC_COLOR_BLUE] = 0x04 }, }; @@ -459,6 +445,8 @@ static ssize_t nuc_wmi_set_brightness_offset(struct device *dev, } \ static DEVICE_ATTR(_name, 0644, show_##_name, store_##_name) +/* Show/change the LED indicator */ + static const char * const led_indicators[] = { "Power State", "HDD Activity", @@ -531,7 +519,220 @@ static ssize_t store_indicator(struct device *dev, return -EINVAL; } -/* Get brightness */ +/* Show/change the LED color */ + +enum led_colors { + LED_COLOR_BLUE, + LED_COLOR_AMBER, + LED_COLOR_WHITE +}; + +struct led_color_name { + const char *name; + u8 r, g, b; +}; + +static const struct led_color_name led_colors[] = { + /* The first colors should match the dual-LED colorset */ + [LED_COLOR_BLUE] = { "blue", 0, 0, 0xff }, + [LED_COLOR_AMBER] = { "amber", 0xff, 0xbf,0 }, + [LED_COLOR_WHITE] = { "white", 0xff, 0xff, 0xff }, + + /* Let's add a couple of common color names as well */ + { "red", 0xff,0,0 }, + { "green", 0, 0xff,0 }, + { "yellow", 0xff, 0xff,0 }, + { "cyan", 0, 0xff, 0xff }, + { "magenta", 0xff,0, 0xff }, +}; + +static ssize_t show_color(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + u8 input[NUM_INPUT_ARGS]; + u8 output[NUM_OUTPUT_ARGS]; + int ret, ctrl; + int size = PAGE_SIZE; + char *p = buf; + int color, r, g, b; + + if (led->indicator == LED_IND_DISABLE) + return -ENODEV; + + ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_COLOR1]; + + if (!nuc_wmi_test_control(dev, led, ctrl)) + return -ENODEV; + + input[0] = LED_NEW_GET_CONTROL_ITEM; + input[1] = led->id; + input[2] = led->indicator; + input[3] = ctrl; + + ret = nuc_nmi_cmd(dev, LED_NEW_GET_STATUS, input, output); + if (ret) + return ret; + + if (led->color_type & LED_RGB) { + r = output[0]; + + input[3]++; +
[PATCH 09/17] staging: nuc-wmi: Add support to blink behavior for NUC8/10
The hardware blink logic works for both Power State and Software controlled LEDs. Just like brightness, there is one different blink behavior per different power state. Due to that, the logic is somewhat more complex than what it would be expected otherwise. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 347 +++--- 1 file changed, 322 insertions(+), 25 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index a365a8603182..8967c8d54dac 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -527,18 +527,30 @@ static ssize_t nuc_wmi_set_brightness_offset(struct device *dev, #define LED_ATTR_RW(_name) \ DEVICE_ATTR(_name, 0644, show_##_name, store_##_name) -#define LED_ATTR_POWER_STATE_RW(_name, offset)\ +#define LED_ATTR_POWER_STATE_RW(_name, _offname, _offset) \ static ssize_t show_##_name(struct device *dev,\ struct device_attribute *attr, \ char *buf) \ { \ - return show_brightness_offset(dev, attr, offset, buf); \ + struct led_classdev *cdev = dev_get_drvdata(dev); \ + struct nuc_nmi_led *led; \ + \ + led = container_of(cdev, struct nuc_nmi_led, cdev);\ + if (led->indicator != LED_IND_POWER_STATE) \ + return -ENODEV;\ + return offset_show_##_offname(dev, attr, _offset, buf);\ } \ static ssize_t store_##_name(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ +struct device_attribute *attr,\ +const char *buf, size_t len) \ { \ - return store_brightness_offset(dev, attr, offset, buf, len); \ + struct led_classdev *cdev = dev_get_drvdata(dev); \ + struct nuc_nmi_led *led; \ + \ + led = container_of(cdev, struct nuc_nmi_led, cdev);\ + if (led->indicator != LED_IND_POWER_STATE) \ + return -ENODEV;\ + return offset_store_##_offname(dev, attr, _offset, buf, len); \ } \ static DEVICE_ATTR(_name, 0644, show_##_name, store_##_name) @@ -681,7 +693,7 @@ static ssize_t nuc6_store_color(struct device *dev, const char *tmp; int ret, color; - tmp = strsep((char **)&buf, ",\n"); + tmp = strsep((char **)&buf, "\n"); if (led->id == POWER_LED) { for (color = ARRAY_SIZE(nuc6_power_colors)+1; color >= 0; color--) @@ -1000,7 +1012,7 @@ static umode_t nuc_wmi_led_color_is_visible(struct kobject *kobj, } /* Show/store brightness */ -static ssize_t show_brightness_offset(struct device *dev, +static ssize_t offset_show_brightness(struct device *dev, struct device_attribute *attr, u8 offset, char *buf) @@ -1009,9 +1021,6 @@ static ssize_t show_brightness_offset(struct device *dev, struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); int ret; - if (led->indicator != LED_IND_POWER_STATE) - return -ENODEV; - offset *= led->reg_table[led->indicator][LED_FUNC_POWER_STATE_NUM_CTRLS]; ret = nuc_wmi_get_brightness_offset(dev, led, offset); @@ -1021,7 +1030,7 @@ static ssize_t show_brightness_offset(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%d\n", ret); } -static ssize_t store_brightness_offset(struct device *dev, +static ssize_t offset_store_brightness(struct device *dev, struct device_attribute *attr, u8 offset, const char *buf, size_t len) @@ -1031,9 +1040,6 @@ static ssize_t store_brightness_offset(struct device *dev,
[PATCH 06/17] staging: nuc-wmi: add support for WMI API version 1.0
The control indicators for WMI version 1.0 (used on NUCi10 and above) are on different locations. The main difference is on single color LEDs. Also, the Power State brightness names are defined on a different way, and there are 3 groups instead of 4. As the driver was written with some tables to map the control option values, it is easy to extend it to support the new definitions: all we need to do is to add the V1.0 tables and ensure that the right table will be used. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 119 +- 1 file changed, 99 insertions(+), 20 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 07cf18e6f4c4..e9c59f656283 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -62,6 +62,7 @@ enum led_function { LED_FUNC_BLINK_BEHAVIOR, LED_FUNC_BLINK_FREQ, + LED_FUNC_POWER_STATE_NUM_CTRLS, LED_FUNC_HDD_BEHAVIOR, LED_FUNC_ETH_TYPE, LED_FUNC_POWER_LIMIT_SCHEME, @@ -84,8 +85,11 @@ enum led_indicators { /* * control items ID for each of the valid indicators on spec Rev 0.64. */ -static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = { - [LED_IND_POWER_STATE] = { /* Offsets for each power state */ +static const u8 led_func_multicolor[MAX_IND][MAX_LED_FUNC] = { + [LED_IND_POWER_STATE] = { + [LED_FUNC_POWER_STATE_NUM_CTRLS] = 0x06, + + /* Offsets for each power state */ [LED_FUNC_BRIGHTNESS] = 0x00, [LED_FUNC_BLINK_BEHAVIOR] = 0x01, [LED_FUNC_BLINK_FREQ] = 0x02, @@ -118,6 +122,24 @@ static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = { }, }; +static const u8 led_func_rev_1_0_singlecolor[MAX_IND][MAX_LED_FUNC] = { + [LED_IND_POWER_STATE] = { + [LED_FUNC_POWER_STATE_NUM_CTRLS] = 0x02, + + /* Offsets for each power state */ + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_BLINK_BEHAVIOR] = 0x01, + }, + [LED_IND_HDD_ACTIVITY] = { + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_HDD_BEHAVIOR] = 0x01 + }, + [LED_IND_SOFTWARE] = { + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_BLINK_BEHAVIOR] = 0x01, + }, +}; + /* LED color indicator */ #define LED_BLUE_AMBER BIT(0) #define LED_BLUE_WHITE BIT(1) @@ -141,6 +163,9 @@ struct nuc_nmi_led { u8 indicator; u32 color_type; u32 avail_indicators; + enum led_api_rev api_rev; + + const u8 (*reg_table)[MAX_LED_FUNC]; }; struct nuc_wmi { @@ -251,7 +276,7 @@ static int nuc_nmi_cmd(struct device *dev, return ret; } -static int nuc_wmi_query_leds(struct device *dev) +static int nuc_wmi_query_leds(struct device *dev, enum led_api_rev *api_rev) { struct nuc_wmi *priv = dev_get_drvdata(dev); u8 input[NUM_INPUT_ARGS] = { 0 }; @@ -288,9 +313,11 @@ static int nuc_wmi_query_leds(struct device *dev) } /* Currently, only API Revision 0.64 is supported */ - if (ver != LED_API_REV_0_64) + if (ver != LED_API_REV_0_64 && ver != LED_API_REV_1_0) return -ENODEV; + *api_rev = ver; + if (!leds) { dev_warn(dev, "No LEDs found\n"); return -ENODEV; @@ -379,7 +406,7 @@ static int nuc_wmi_get_brightness_offset(struct device *dev, if (led->indicator == LED_IND_DISABLE) return -ENODEV; - ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_BRIGHTNESS] + offset; + ctrl = led->reg_table[led->indicator][LED_FUNC_BRIGHTNESS] + offset; if (!nuc_wmi_test_control(dev, led, ctrl)) return -ENODEV; @@ -410,7 +437,7 @@ static ssize_t nuc_wmi_set_brightness_offset(struct device *dev, if (led->indicator == LED_IND_DISABLE) return -ENODEV; - ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_BRIGHTNESS] + offset; + ctrl = led->reg_table[led->indicator][LED_FUNC_BRIGHTNESS] + offset; if (!nuc_wmi_test_control(dev, led, ctrl)) return -ENODEV; @@ -561,7 +588,7 @@ static ssize_t show_color(struct device *dev, if (led->indicator == LED_IND_DISABLE) return -ENODEV; - ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_COLOR1]; + ctrl = led->reg_table[led->indicator][LED_FUNC_COLOR1]; if (!nuc_wmi_test_control(dev, led, ctrl)) return -ENODEV; @@ -658,7 +685,7 @@ static ssize_t store_color(struct device *dev, } } - ctrl = led_func_rev_0_64[led->indicator][LED_FUNC_COLOR1]; + ctrl = led->reg_table[led->indicator][LED_FUNC_COLOR1]; /* Dual color LEDs */ if (!(led->color_type & LED_R
[PATCH 14/17] staging: nuc-wmi: fix software blink behavior logic
The is_visible logic for it is plain wrong: 1. it is used only during devnode creation; 2. it was using the wrong field (id, instead of indicator). Fix it. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 30 -- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 68143d45c34c..fab0094a20e4 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -1476,6 +1476,9 @@ static ssize_t show_blink_behavior(struct device *dev, if (led->api_rev == LED_API_NUC6) return nuc6_show_blink_behavior(dev, attr, buf); + if (led->indicator != LED_IND_SOFTWARE) + return -EINVAL; + return offset_show_blink_behavior(dev, attr, 0, buf); } @@ -1489,6 +1492,9 @@ static ssize_t store_blink_behavior(struct device *dev, if (led->api_rev == LED_API_NUC6) return nuc6_store_blink_behavior(dev, attr, buf, len); + if (led->indicator != LED_IND_SOFTWARE) + return -EINVAL; + return offset_store_blink_behavior(dev, attr, 0, buf, len); } @@ -1593,6 +1599,9 @@ static ssize_t show_blink_frequency(struct device *dev, if (led->api_rev == LED_API_NUC6) return nuc6_show_blink_frequency(dev, attr, buf); + if (led->indicator != LED_IND_SOFTWARE) + return -EINVAL; + return offset_show_blink_frequency(dev, attr, 0, buf); } @@ -1606,26 +1615,12 @@ static ssize_t store_blink_frequency(struct device *dev, if (led->api_rev == LED_API_NUC6) return nuc6_store_blink_frequency(dev, attr, buf, len); + if (led->indicator != LED_IND_SOFTWARE) + return -EINVAL; + return offset_store_blink_frequency(dev, attr, 0, buf, len); } -static umode_t nuc_wmi_led_blink_is_visible(struct kobject *kobj, - struct attribute *attr, int idx) -{ - struct device *dev = kobj_to_dev(kobj); - struct led_classdev *cdev = dev_get_drvdata(dev); - struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); - umode_t mode = attr->mode; - - if (led->api_rev == LED_API_NUC6) - return mode; - - if (led->id == LED_IND_SOFTWARE) - return mode; - - return 0; -} - /* HDD activity behavior */ static ssize_t show_hdd_default(struct device *dev, struct device_attribute *attr, @@ -1785,7 +1780,6 @@ static struct attribute *nuc_wmi_led_blink_behavior_attr[] = { }; static const struct attribute_group nuc_wmi_led_blink_attribute_group = { - .is_visible = nuc_wmi_led_blink_is_visible, .attrs = nuc_wmi_led_blink_behavior_attr, }; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 11/17] staging: nuc-wmi: implement blink control for NUC6
The blink control logic for NUC6 API is somewhat messy, as it uses a single register for controlling both the blink type and the frequency, using a random order. Let's use the same API as defined for other versions, splitting this setting on two different properties. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 269 +- 1 file changed, 267 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 78b0a3279f25..5bc4dcec3ea8 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -713,6 +713,247 @@ static ssize_t nuc6_store_color(struct device *dev, return len; } +enum nuc6_blink_mode_freq { + NUC6_BLINK_MODE_BLINK_1HZ = 0x01, + NUC6_BLINK_MODE_BLINK_0_25HZ= 0x02, + NUC6_BLINK_MODE_FADE_1HZ= 0x03, + NUC6_BLINK_MODE_DONT_BLINK = 0x04, + + /* BIOS equal or upper AY0038 or BN0043 */ + NUC6_BLINK_MODE_BLINK_0_5HZ = 0x05, + NUC6_BLINK_MODE_FADE_0_25HZ = 0x06, + NUC6_BLINK_MODE_FADE_0_5HZ = 0x07 +}; + +enum nuc6_blink_mode { + NUC6_BLINK_MODE_SOLID, + NUC6_BLINK_MODE_BLINK, + NUC6_BLINK_MODE_FADE +}; + +static const char * const nuc6_blink_behavior[] = { + "solid", + "blink", + "fade", +}; + +enum nuc6_blink_freq { + NUC6_BLINK_FREQ_1HZ, + NUC6_BLINK_FREQ_0_5HZ, + NUC6_BLINK_FREQ_0_25HZ, +}; + +static const char * const nuc6_blink_frequency[] = { + "1", + "0.5", + "0.25", +}; + +static int nuc_wmi_nuc6_set_blink(struct device *dev, + struct nuc_nmi_led *led, + int freq, enum nuc6_blink_mode mode) +{ + int val; + + switch(mode) { + case NUC6_BLINK_MODE_SOLID: + val = NUC6_BLINK_MODE_DONT_BLINK; + break; + case NUC6_BLINK_MODE_BLINK: + if (freq == NUC6_BLINK_FREQ_0_25HZ) + val = NUC6_BLINK_MODE_BLINK_0_25HZ; + else if (freq == NUC6_BLINK_FREQ_0_5HZ) + val = NUC6_BLINK_MODE_BLINK_0_5HZ; + else + val = NUC6_BLINK_MODE_BLINK_1HZ; + break; + case NUC6_BLINK_MODE_FADE: + if (freq == NUC6_BLINK_FREQ_0_25HZ) + val = NUC6_BLINK_MODE_FADE_0_25HZ; + else if (freq == NUC6_BLINK_FREQ_0_5HZ) + val = NUC6_BLINK_MODE_FADE_0_5HZ; + else + val = NUC6_BLINK_MODE_FADE_1HZ; + break; + default: + return -EINVAL; + } + + return nuc_wmi_nuc6_led_get_set(dev, led, NULL, &val, NULL); +} + +static ssize_t nuc6_show_blink_behavior(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + int val = -1, mode = -1, ret, i, n; + int size = PAGE_SIZE; + char *p = buf; + + ret = nuc_wmi_nuc6_led_get_set(dev, led, NULL, &val, NULL); + if (ret) + return ret; + + switch (val) { + case NUC6_BLINK_MODE_BLINK_1HZ: + case NUC6_BLINK_MODE_BLINK_0_25HZ: + case NUC6_BLINK_MODE_BLINK_0_5HZ: + mode = NUC6_BLINK_MODE_BLINK; + break; + case NUC6_BLINK_MODE_FADE_1HZ: + case NUC6_BLINK_MODE_FADE_0_25HZ: + case NUC6_BLINK_MODE_FADE_0_5HZ: + mode = NUC6_BLINK_MODE_FADE; + break; + case NUC6_BLINK_MODE_DONT_BLINK: + mode = NUC6_BLINK_MODE_SOLID; + break; + } + + for (i = 0; i < ARRAY_SIZE(nuc6_blink_behavior); i++) { + if (i == mode) + n = scnprintf(p, size, "[%s] ", nuc6_blink_behavior[i]); + else + n = scnprintf(p, size, "%s ", nuc6_blink_behavior[i]); + p += n; + size -= n; + } + size -= scnprintf(p, size, "\n"); + + return PAGE_SIZE - size; + +} + +static ssize_t nuc6_store_blink_behavior(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + int ret, val = -1, freq; + const char *tmp; + + tmp = strsep((char **)&buf, "\n"); + + ret = nuc_wmi_nuc6_led_get_set(dev, led, NULL, &val, NULL); + if (ret) + return ret; + + /* Preserve the frequency */ + switch (val) { + case NUC6_BLINK_MODE_BLINK_0_25HZ: + case NUC6_BLINK_MODE_FADE_0_25HZ: + fr
[PATCH 08/17] staging: muc-wmi: add brightness and color for NUC6 API
The NUC6 WMI API is really simple: it has just 2 messages, that retrieves everything for a LED, and it has just 2 LEDs. Add support for retrieving and set brightness and color. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 198 -- 1 file changed, 191 insertions(+), 7 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index db38c40c223a..a365a8603182 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -302,14 +302,13 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev) { // FIXME: add a check for the specific models that are known to work struct nuc_wmi *priv = dev_get_drvdata(dev); - u8 cmd, input[NUM_INPUT_ARGS] = { 0 }; + u8 input[NUM_INPUT_ARGS] = { 0 }; u8 output[NUM_OUTPUT_ARGS]; struct nuc_nmi_led *led; int ret; - cmd = LED_OLD_GET_STATUS; input[0] = LED_OLD_GET_S0_POWER; - ret = nuc_nmi_cmd(dev, cmd, input, output); + ret = nuc_nmi_cmd(dev, LED_OLD_GET_STATUS, input, output); if (ret) { dev_warn(dev, "Get S0 Power: error %d\n", ret); return ret; @@ -322,9 +321,8 @@ static int nuc_wmi_query_leds_nuc6(struct device *dev) led->indicator = fls(led->avail_indicators); priv->num_leds++; - cmd = LED_OLD_GET_STATUS; input[0] = LED_OLD_GET_S0_RING; - ret = nuc_nmi_cmd(dev, cmd, input, output); + ret = nuc_nmi_cmd(dev, LED_OLD_GET_STATUS, input, output); if (ret) { dev_warn(dev, "Get S0 Ring: error %d\n", ret); return ret; @@ -544,6 +542,167 @@ static ssize_t nuc_wmi_set_brightness_offset(struct device *dev, } \ static DEVICE_ATTR(_name, 0644, show_##_name, store_##_name) +/* + * NUC6 specific logic + */ + +static int nuc_wmi_nuc6_led_get_set(struct device *dev, + struct nuc_nmi_led *led, int *brightness, + int *blink_fade, int *color_state) +{ + u8 input[NUM_INPUT_ARGS] = { 0 }; + u8 output[NUM_OUTPUT_ARGS]; + int ret; + + if (led->id == POWER_LED) + input[0] = LED_OLD_GET_S0_POWER; + else + input[0] = LED_OLD_GET_S0_RING; + + ret = nuc_nmi_cmd(dev, LED_OLD_GET_STATUS, input, output); + if (ret) { + dev_warn(dev, "Get %s: error %d\n", led_names[led->id], ret); + return ret; + } + + if (brightness && *brightness >= 0) + input[1] = *brightness; + else + input[1] = output[0]; + + if (blink_fade && *blink_fade >= 0) + input[2] = *blink_fade; + else + input[2] = output[1]; + + if (color_state && *color_state >= 0) + input[3] = *color_state; + else + input[3] = output[2]; + + ret = nuc_nmi_cmd(dev, LED_OLD_SET_LED, input, output); + if (ret) { + dev_warn(dev, "Get %s: error %d\n", led_names[led->id], ret); + return ret; + } + + if (brightness) + *brightness = output[0]; + if (blink_fade) + *blink_fade = output[1]; + if (color_state) + *color_state = output[2]; + + return 0; +} + +static enum led_brightness nuc_wmi_nuc6_get_brightness(struct led_classdev *cdev) +{ + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + int ret, brightness = -1; + + ret = nuc_wmi_nuc6_led_get_set(cdev->dev, led, &brightness, NULL, NULL); + if (ret) + return ret; + + return brightness; +} + +static int nuc_wmi_nuc6_set_brightness(struct led_classdev *cdev, + enum led_brightness bright) +{ + int brightness = bright; + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + + return nuc_wmi_nuc6_led_get_set(cdev->dev, led, &brightness, + NULL, NULL); +} + +static const char * const nuc6_power_colors[] = { + "disable", + "blue", + "amber" +}; + +static const char * const nuc6_ring_colors[] = { + "disable", + "cyan", + "pink", + "yellow", + "blue", + "red", + "green", + "white" +}; + +static ssize_t nuc6_show_color(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct nuc_nmi_led *led = container_of(cdev, struct nuc_nmi_led, cdev); + int color = -1, ret, arr_size, i, n; + const char * const*color_names; + int size = PAGE_SIZE; + char *p = buf; + + ret = nuc_wmi_nuc6_led_get_set(dev, led, NULL,
[PATCH 04/17] staging: nuc-wmi: add all types of brightness
Improve the logic in order to support not only S0 brightness, but also the brightness for other indicators and for all power states. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 369 -- 1 file changed, 249 insertions(+), 120 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 62c2764814dd..711897ba4666 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -55,21 +55,89 @@ enum led_new_get_subcmd { LED_NEW_GET_CONTROL_ITEM= 0x01, }; +enum led_function { + LED_FUNC_BRIGHTNESS, + LED_FUNC_COLOR1, + LED_FUNC_COLOR_GREEN, + LED_FUNC_COLOR_BLUE, + + LED_FUNC_BLINK_BEHAVIOR, + LED_FUNC_BLINK_FREQ, + + LED_FUNC_HDD_BEHAVIOR, + LED_FUNC_ETH_TYPE, + LED_FUNC_POWER_LIMIT_SCHEME, + + MAX_LED_FUNC +}; + +enum led_indicators { + LED_IND_POWER_STATE, + LED_IND_HDD_ACTIVITY, + LED_IND_ETHERNET, + LED_IND_WIFI, + LED_IND_SOFTWARE, + LED_IND_POWER_LIMIT, + LED_IND_DISABLE, + + MAX_IND = LED_IND_DISABLE +}; + +/* + * control items ID for each of the valid indicators on spec Rev 0.64. + */ +static const u8 led_func_rev_0_64[MAX_IND][MAX_LED_FUNC] = { + [LED_IND_POWER_STATE] = { /* Offsets for each power state */ + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_BLINK_BEHAVIOR] = 0x01, + [LED_FUNC_BLINK_FREQ] = 0x02, + [LED_FUNC_COLOR1] = 0x03, + [LED_FUNC_COLOR_GREEN] = 0x04, + [LED_FUNC_COLOR_BLUE] = 0x05 + }, + [LED_IND_HDD_ACTIVITY] = { + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_COLOR1] = 0x01, + [LED_FUNC_COLOR_GREEN] = 0x02, + [LED_FUNC_COLOR_BLUE] = 0x03, + [LED_FUNC_HDD_BEHAVIOR] = 0x04 + }, + [LED_IND_ETHERNET] = { + [LED_FUNC_ETH_TYPE] = 0x00, + [LED_FUNC_BRIGHTNESS] = 0x01, + [LED_FUNC_COLOR1] = 0x02, + [LED_FUNC_COLOR_GREEN] = 0x03, + [LED_FUNC_COLOR_BLUE] = 0x04 + }, + [LED_IND_WIFI] = { + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_COLOR1] = 0x01, + [LED_FUNC_COLOR_GREEN] = 0x02, + [LED_FUNC_COLOR_BLUE] = 0x03 + }, + [LED_IND_SOFTWARE] = { + [LED_FUNC_BRIGHTNESS] = 0x00, + [LED_FUNC_BLINK_BEHAVIOR] = 0x01, + [LED_FUNC_BLINK_FREQ] = 0x02, + [LED_FUNC_COLOR1] = 0x03, + [LED_FUNC_COLOR_GREEN] = 0x04, + [LED_FUNC_COLOR_BLUE] = 0x05 + }, + [LED_IND_POWER_LIMIT] = { + [LED_FUNC_POWER_LIMIT_SCHEME] = 0x00, + [LED_FUNC_BRIGHTNESS] = 0x01, + [LED_FUNC_COLOR1] = 0x02, + [LED_FUNC_COLOR_GREEN] = 0x03, + [LED_FUNC_COLOR_BLUE] = 0x04 + }, +}; + /* LED color indicator */ #define LED_BLUE_AMBER BIT(0) #define LED_BLUE_WHITE BIT(1) #define LED_RGBBIT(2) #defineLED_SINGLE_COLORBIT(3) -/* LED indicator options */ -#define LED_IND_POWER_STATEBIT(0) -#define LED_IND_HDD_ACTIVITY BIT(1) -#define LED_IND_ETHERNET BIT(2) -#define LED_IND_WIFI BIT(3) -#define LED_IND_SOFTWARE BIT(4) -#define LED_IND_POWER_LIMITBIT(5) -#define LED_IND_DISABLEBIT(6) - static const char * const led_names[] = { "nuc::power", "nuc::hdd", @@ -87,7 +155,6 @@ struct nuc_nmi_led { u8 indicator; u32 color_type; u32 avail_indicators; - u32 control_items; }; struct nuc_wmi { @@ -201,9 +268,9 @@ static int nuc_nmi_cmd(struct device *dev, static int nuc_wmi_query_leds(struct device *dev) { struct nuc_wmi *priv = dev_get_drvdata(dev); - u8 cmd, input[NUM_INPUT_ARGS] = { 0 }; + u8 input[NUM_INPUT_ARGS] = { 0 }; u8 output[NUM_OUTPUT_ARGS]; - int i, id, ret, ver = LED_API_UNKNOWN; + int id, ret, ver = LED_API_UNKNOWN; u8 leds; /* @@ -214,9 +281,8 @@ static int nuc_wmi_query_leds(struct device *dev) * FIXME: Should add a fallback code for it to work with older NUCs, * as LED_QUERY returns an error on older devices like Skull Canyon. */ - cmd = LED_QUERY; input[0] = LED_QUERY_LIST_ALL; - ret = nuc_nmi_cmd(dev, cmd, input, output); + ret = nuc_nmi_cmd(dev, LED_QUERY, input, output); if (ret == -ENOENT) { ve
[PATCH 07/17] staging: nuc-wmi: add basic support for NUC6 WMI
The NUC6 and NUCi7 supports an earlier version of the LEDs WMI, as specified at: https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html Implement the query part of the LED detection for those devices. Weird enough, at least with Skull Canyon (NUC6i7KYB) using the latest firmware release (KYSKLi70 0071), the WMI call return all zeros. It could well be due to a regression at the Intel's firmware, although this model was not announced as supporting this WMI. At the manufacturer's site, only NUC Kits NUC7i[x]BN and NUC6CAY are mentioned. Yet, it sounds to me that this is due to a firmware bug: $ sudo fwts wmi - ... Test 1 of 1: Windows Management Instrumentation test. ... \_SB_.WMTF._WDG (1 of 1) GUID: 86CCFD48-205E-4A77-9C48-2021CBEDE341 WMI Method: Flags : 0x02 (Method) Object ID : TF Instance : 0x01 Driver : intel-wmi-thunderbolt (Intel) FAILED [LOW] WMIMultipleMethod: Test 1, GUID 86CCFD48-205E-4A77-9C48-2021CBEDE341 has multiple associated methods WMTF defined, this is a firmware bug that leads to ambiguous behaviour. ... \AMW0._WDG (1 of 2) GUID: 8C5DA44C-CDC3-46B3-8619-4E26D34390B7 WMI Method: Flags : 0x02 (Method) Object ID : AA Instance : 0x01 PASSED: Test 1, 8C5DA44C-CDC3-46B3-8619-4E26D34390B7 has associated method \AMW0.WMAA ... Low failures: 1 wmi: GUID 86CCFD48-205E-4A77-9C48-2021CBEDE341 has multiple associated methods WMTF defined, this is a firmware bug that leads to ambiguous behaviour. Anyway, this was good enough to test that this patch will be producing exactly the WMI query as the NUC6 OOT driver at: https://github.com/milesp20/intel_nuc_led/ Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/nuc-wmi.c | 134 +++--- 1 file changed, 106 insertions(+), 28 deletions(-) diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index e9c59f656283..db38c40c223a 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -8,12 +8,15 @@ * * Inspired on WMI from https://github.com/nomego/intel_nuc_led * - * It follows this spec: - * https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf + * It follows those specs: + * https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html + * https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf + * https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf */ #include #include +#include #include #include #include @@ -34,12 +37,21 @@ enum led_api_rev { }; enum led_cmds { + /* NUC6-specific cmds */ + LED_OLD_GET_STATUS = 0x01, + LED_OLD_SET_LED = 0x02, + + /* Rev 0.64 and 1.0 cmds */ + LED_QUERY = 0x03, LED_NEW_GET_STATUS = 0x04, LED_SET_INDICATOR = 0x05, LED_SET_VALUE = 0x06, LED_NOTIFICATION= 0x07, LED_SWITCH_TYPE = 0x08, + + /* Rev 1.0 cmds */ + LED_VERSION_CONTROL = 0x09, }; @@ -55,6 +67,11 @@ enum led_new_get_subcmd { LED_NEW_GET_CONTROL_ITEM= 0x01, }; +enum led_old_get_subcmd { + LED_OLD_GET_S0_POWER= 0x01, + LED_OLD_GET_S0_RING = 0x02, +}; + enum led_function { LED_FUNC_BRIGHTNESS, LED_FUNC_COLOR1, @@ -146,14 +163,19 @@ static const u8 led_func_rev_1_0_singlecolor[MAX_IND][MAX_LED_FUNC] = { #define LED_RGBBIT(2) #defineLED_SINGLE_COLORBIT(3) +#define POWER_LED 0 +#define RING_LED (MAX_LEDS + 1) + static const char * const led_names[] = { - "nuc::power", + [POWER_LED] = "nuc::power", "nuc::hdd", "nuc::skull", "nuc::eyes", "nuc::front1", "nuc::front2", "nuc::front3", + + [RING_LED] = "nuc::ring", // NUC6 models }; struct nuc_nmi_led { @@ -276,48 +298,98 @@ static int nuc_nmi_cmd(struct device *dev, return ret; } +static int nuc_wmi_query_leds_nuc6(struct device *dev) +{ + // FIXME: add a check for the specific models that are known to work + struct nuc_wmi *priv = dev_get_drvdata(dev); + u8 cmd, input[NUM_INPUT_ARGS] = { 0 }; + u8 output[NUM_OUTPUT_ARGS]; + struct nuc_nmi_led *led; + int ret; + + cmd = LED_OLD_GET_STATUS; + input[0] = LED_OLD_GET_S0_POWER; + ret = nuc_nmi_cmd(dev, cmd, input, output); + if (ret) { + dev_warn(
[PATCH 01/17] staging: add support for NUC WMI LEDs
Some Intel Next Unit of Computing (NUC) machines have software-configured LEDs that can be used to display a variety of events: - Power State - HDD Activity - Ethernet - WiFi - Power Limit They can even be controlled directly via software, without any hardware-specific indicator connected into them. Some devices have mono-colored LEDs, but the more advanced ones have RGB leds that can show any color. Different color and 4 blink states can be programmed for thee system states: - powered on (S0); - S3; - Standby. The NUC BIOSes allow to partially set them for S0, but doesn't provide any control for the other states, nor does allow changing the blinking logic. They all use a WMI interface using GUID: 8C5DA44C-CDC3-46b3-8619-4E26D34390B7 But there are 3 different revisions of the spec, all using the same GUID, but two different APIs: - the original one, for NUC6 and to NUCi7: - https://www.intel.com/content/www/us/en/support/articles/23426/intel-nuc/intel-nuc-kits.html - a new one, starting with NUCi8, with two revisions: - https://raw.githubusercontent.com/nomego/intel_nuc_led/master/specs/INTEL_WMI_LED_0.64.pdf - https://www.intel.com/content/dam/support/us/en/documents/intel-nuc/WMI-Spec-Intel-NUC-NUC10ixFNx.pdf There are some OOT drivers for them, but they use procfs and use a messy interface to setup it. Also, there are different drivers with the same name, each with support for each NUC family. Let's start a new driver from scratch, using the x86 platform WMI core and the LED class. This initial version is compatible with NUCi8 and above, and it was tested with a Hades Canyon NUC (NUC8i7HNK). Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 6 + drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/nuc-led/Kconfig | 11 + drivers/staging/nuc-led/Makefile | 3 + drivers/staging/nuc-led/TODO | 6 + drivers/staging/nuc-led/nuc-wmi.c | 489 ++ 7 files changed, 518 insertions(+) create mode 100644 drivers/staging/nuc-led/Kconfig create mode 100644 drivers/staging/nuc-led/Makefile create mode 100644 drivers/staging/nuc-led/TODO create mode 100644 drivers/staging/nuc-led/nuc-wmi.c diff --git a/MAINTAINERS b/MAINTAINERS index bd7aff0c120f..50d181e1d745 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13063,6 +13063,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs.git F: Documentation/filesystems/ntfs.rst F: fs/ntfs/ +NUC LED DRIVER +M: Mauro Carvalho Chehab +L: de...@driverdev.osuosl.org +S: Maintained +F: drivers/staging/nuc-led + NUBUS SUBSYSTEM M: Finn Thain L: linux-m...@lists.linux-m68k.org diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index b7ae5bdc4eb5..d1a8e3e08d00 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -84,6 +84,8 @@ source "drivers/staging/greybus/Kconfig" source "drivers/staging/vc04_services/Kconfig" +source "drivers/staging/nuc-led/Kconfig" + source "drivers/staging/pi433/Kconfig" source "drivers/staging/mt7621-pci/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 075c979bfe7c..de937f947edb 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ obj-$(CONFIG_MOST) += most/ +obj-$(CONFIG_LEDS_NUC_WMI) += nuc-led/ obj-$(CONFIG_KS7010) += ks7010/ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_BCM2835_VCHIQ)+= vc04_services/ diff --git a/drivers/staging/nuc-led/Kconfig b/drivers/staging/nuc-led/Kconfig new file mode 100644 index ..0f870f45bf44 --- /dev/null +++ b/drivers/staging/nuc-led/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 + +config LEDS_NUC_WMI + tristate "Intel NUC WMI support for LEDs" + depends on LEDS_CLASS + depends on ACPI_WMI + help + Enable this to support the Intel NUC WMI support for + LEDs, starting from NUCi8 and upper devices. + + To compile this driver as a module, choose M here. diff --git a/drivers/staging/nuc-led/Makefile b/drivers/staging/nuc-led/Makefile new file mode 100644 index ..abba9e305fa1 --- /dev/null +++ b/drivers/staging/nuc-led/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_LEDS_NUC_WMI) += nuc-wmi.o diff --git a/drivers/staging/nuc-led/TODO b/drivers/staging/nuc-led/TODO new file mode 100644 index ..d5296d7186a7 --- /dev/null +++ b/drivers/staging/nuc-led/TODO @@ -0,0 +1,6 @@ +- Add support for 6th gen NUCs, like Skull Canyon +- Improve LED core support to avoid it to try to manage the + LED brightness directly; +- Test
[PATCH 17/17] staging: nuc-led: update the TODOs
Now that most functionality were merged at the driver, update its TODO list, and add a "TODO" comment for the two WMI API commands that are currently not implemented. In summary: - on Rev 0.64, command 0x07 (LED_NOTIFICATION) is meant to store all config settings at EEPROM. That doesn't seem to be needed on Skull Canyon, but tests with different hardware would be nice in order to double-check it. Also, maybe Rev 1.00 would make it mandatory; - Rev 1.00 added command 0x08 to switch the LED type (LED_SWITCH_TYPE at the driver's nomenclature) between single color LED and multi color LED). Not sure how this should be properly implemented (if this is the case); - The tests for NUC6 version were using a Skull Canyon NUC. It allowed to check that the driver's logic runs, but it is not enough to see if everything is really working. Tests on NUC6 or NUC7 are required; - On a suspend test, I noticed that some controls were reset to the default at resume time. It is required to check what's happening there and address it properly. - Need to validate the uAPI and document it before moving this driver out of staging. Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/nuc-led/TODO | 12 +++- drivers/staging/nuc-led/nuc-wmi.c | 6 ++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/nuc-led/TODO b/drivers/staging/nuc-led/TODO index d5296d7186a7..df6f3f653eb0 100644 --- a/drivers/staging/nuc-led/TODO +++ b/drivers/staging/nuc-led/TODO @@ -1,6 +1,8 @@ -- Add support for 6th gen NUCs, like Skull Canyon -- Improve LED core support to avoid it to try to manage the - LED brightness directly; -- Test it with 8th gen NUCs; -- Add more functionality to the driver; +- Test it with 6th gen and 10th NUCs; +- Add support for LED_NOTIFICATION; +- Add support for LED_SWITCH_TYPE; +- Some LED parameters are changing after returning + from suspend. Need to check what's happening there + (hardware bug?) and ensure that the parameters will + be properly restored after resume. - Stabilize and document its sysfs interface. diff --git a/drivers/staging/nuc-led/nuc-wmi.c b/drivers/staging/nuc-led/nuc-wmi.c index 2d9c49d72703..e87e97d56364 100644 --- a/drivers/staging/nuc-led/nuc-wmi.c +++ b/drivers/staging/nuc-led/nuc-wmi.c @@ -42,16 +42,14 @@ enum led_cmds { LED_OLD_SET_LED = 0x02, /* Rev 0.64 and 1.0 cmds */ - LED_QUERY = 0x03, LED_NEW_GET_STATUS = 0x04, LED_SET_INDICATOR = 0x05, LED_SET_VALUE = 0x06, - LED_NOTIFICATION= 0x07, - LED_SWITCH_TYPE = 0x08, + LED_NOTIFICATION= 0x07, // TODO: add support for it /* Rev 1.0 cmds */ - + LED_SWITCH_TYPE = 0x08, // TODO: add support for it LED_VERSION_CONTROL = 0x09, }; -- 2.31.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 01/17] staging: add support for NUC WMI LEDs
Hi Mauro, On 5/16/21 3:53 AM, Mauro Carvalho Chehab wrote: > diff --git a/drivers/staging/nuc-led/Kconfig b/drivers/staging/nuc-led/Kconfig > new file mode 100644 > index ..0f870f45bf44 > --- /dev/null > +++ b/drivers/staging/nuc-led/Kconfig > @@ -0,0 +1,11 @@ > +# SPDX-License-Identifier: GPL-2.0 > + > +config LEDS_NUC_WMI > + tristate "Intel NUC WMI support for LEDs" > + depends on LEDS_CLASS > + depends on ACPI_WMI > + help > + Enable this to support the Intel NUC WMI support for Don't use "support" 2 times. Maybe: Enable this to support the Intel NUC WMI interface for or Enable this to build the Intel NUC WMI support for > + LEDs, starting from NUCi8 and upper devices. Does "upper" mean "later"? Or more advanced? Not clear. > + > + To compile this driver as a module, choose M here. thanks. -- ~Randy ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [GIT PULL] Staging/IIO driver fixes for 5.13-rc2
The pull request you sent on Sun, 16 May 2021 11:00:19 +0200: > git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git > tags/staging-5.13-rc2 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/6942d81a8faa17d44d1286b63ccb7d920b29d065 Thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 17/17] staging: nuc-led: update the TODOs
Hi! > - Need to validate the uAPI and document it before moving >this driver out of staging. > - Stabilize and document its sysfs interface. Would you mind starting with this one? We should have existing APIs for most of functionality described... We really don't want to merge code with bad API, not even to staging. Best regards, Pavel ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v9 03/13] media: hantro: Use syscon instead of 'ctrl' register
Hi Lucas, On Fri, 2021-04-16 at 12:54 +0200, Lucas Stach wrote: > Am Mittwoch, dem 07.04.2021 um 09:35 +0200 schrieb Benjamin Gaignard: > > In order to be able to share the control hardware block between > > VPUs use a syscon instead a ioremap it in the driver. > > To keep the compatibility with older DT if 'nxp,imx8mq-vpu-ctrl' > > phandle is not found look at 'ctrl' reg-name. > > With the method it becomes useless to provide a list of register > > names so remove it. > > Sorry for putting a spoke in the wheel after many iterations of the > series. > > We just discussed a way forward on how to handle the clocks and resets > provided by the blkctl block on i.MX8MM and later and it seems there is > a consensus on trying to provide virtual power domains from a blkctl > driver, controlling clocks and resets for the devices in the power > domain. I would like to avoid introducing yet another way of handling > the blkctl and thus would like to align the i.MX8MQ VPU blkctl with > what we are planning to do on the later chip generations. > > CC'ing Jacky Bai and Peng Fan from NXP, as they were going to give this > virtual power domain thing a shot. > It seems the i.MX8MM BLK-CTL series are moving forward: https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=479175 ... but I'm unable to wrap my head around how this affects the devicetree VPU modelling for i.MX8MQ (and also i.MX8MM, i.MX8MP, ...). Can you clarify that? Thanks, Ezequiel ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v10 6/9] media: uapi: Add a control for HANTRO driver
Hi Hans, On Thu, 2021-05-06 at 14:50 +0200, Hans Verkuil wrote: > On 05/05/2021 17:20, Benjamin Gaignard wrote: > > > > Le 05/05/2021 à 16:55, Hans Verkuil a écrit : > > > On 20/04/2021 14:10, Benjamin Gaignard wrote: > > > > The HEVC HANTRO driver needs to know the number of bits to skip at > > > > the beginning of the slice header. > > > > That is a hardware specific requirement so create a dedicated control > > > > for this purpose. > > > > > > > > Signed-off-by: Benjamin Gaignard > > > > --- > > > > .../userspace-api/media/drivers/hantro.rst | 19 +++ > > > > .../userspace-api/media/drivers/index.rst | 1 + > > > > include/media/hevc-ctrls.h | 13 + > > > > 3 files changed, 33 insertions(+) > > > > create mode 100644 > > > > Documentation/userspace-api/media/drivers/hantro.rst > > > > > > > > diff --git a/Documentation/userspace-api/media/drivers/hantro.rst > > > > b/Documentation/userspace-api/media/drivers/hantro.rst > > > > new file mode 100644 > > > > index ..cd9754b4e005 > > > > --- /dev/null > > > > +++ b/Documentation/userspace-api/media/drivers/hantro.rst > > > > @@ -0,0 +1,19 @@ > > > > +.. SPDX-License-Identifier: GPL-2.0 > > > > + > > > > +Hantro video decoder driver > > > > +=== > > > > + > > > > +The Hantro video decoder driver implements the following > > > > driver-specific controls: > > > > + > > > > +``V4L2_CID_HANTRO_HEVC_SLICE_HEADER_SKIP (integer)`` > > > > + Specifies to Hantro HEVC video decoder driver the number of data > > > > (in bits) to > > > > + skip in the slice segment header. > > > > + If non-IDR, the bits to be skipped go from syntax element > > > > "pic_output_flag" > > > > + to before syntax element "slice_temporal_mvp_enabled_flag". > > > > + If IDR, the skipped bits are just "pic_output_flag" > > > > + (separate_colour_plane_flag is not supported). > > > I'm not very keen on this. Without this information the video data cannot > > > be > > > decoded, or will it just be suboptimal? > > > > Without that information the video can't be decoded. > > > > > > > > The problem is that a generic decoder would have to know that the HW is a > > > hantro, > > > and then call this control. If they don't (and are testing on non-hantro > > > HW), then > > > it won't work, thus defeating the purpose of the HW independent decoder > > > API. > > > > > > Since hantro is widely used, and if there is no other way to do this > > > beside explitely > > > setting this control, then perhaps this should be part of the standard > > > HEVC API. > > > Non-hantro drivers that do not need this can just skip it. > > > > Even if I put this parameter in decode_params structure that would means > > that a generic > > userland decoder will have to know how the compute this value for hantro HW > > since it > > isn't something that could be done on kernel side. > > But since hantro is very common, any userland decoder will need to calculate > this anyway. > So perhaps it is better to have this as part of the decode_params? > > I'd like to know what others think about this. > As you know, I'm not a fan of carrying these "unstable" APIs around. I know it's better than nothing, but I feel they create the illusion of the interface being supported in mainline. Since it's unstable, it's difficult for applications to adopt them. As Nicolas mentioned, this means neither FFmpeg nor GStreamer will adopt these APIs, which worries me, as that means we lose two major user bases. My personal take from this, is that we need to find ways to stabilize our stateless codec APIs in less time and perhaps with less effort. IMO, a less stiff interface could help us here, and that's why I think having hardware-specific controls can be useful. Hardware designers can be so creative :) I'm not against introducing this specific parameter in v4l2_ctrl_hevc_codec_params, arguing that Hantro is widely used, but I'd like us to be open to hardware-specific controls as a way to extend the APIs seamlessly. Applications won't have to _know_ what hardware they are running on, they can just use VIDIOC_QUERYCTRL to find out which controls are needed. Thanks, Ezequiel ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 17/17] staging: nuc-led: update the TODOs
Hi Pavel, Em Sun, 16 May 2021 20:21:50 +0200 Pavel Machek escreveu: > Hi! > > > - Need to validate the uAPI and document it before moving > >this driver out of staging. > > > - Stabilize and document its sysfs interface. > > Would you mind starting with this one? Do you mean writing the ABI document for it? Surely I can do that, but I'm not sure where to put such document while it is on staging. > We should have existing APIs > for most of functionality described... I tried to stay as close as possible to the existing API, but there are some things that required a different one. For instance, with WMI rev 0.64 and 1.0, any LED of the device can be programmed to be a power indicator. When a LED is programmed this way, there are up to 3 (on rev 1.0) or up to 4 (on rev 0.64) different brightness level of the LED, and those are associated with a power status (like S0, S3, S5, "ready mode"). So, the LED API standard "brightness" is meaningless. On the other hand, when the same LED is programmed to monitor, let's say, the WiFi or one of the two Ethernets (or both at the same time), the standard "brightness" level makes sense. > > We really don't want to merge code with bad API, not even to staging. See, this is the API that it is exposed on with a NUC8: $ tree /sys/class/leds/nuc\:\:front1/ /sys/class/leds/nuc::front1/ ├── blink_behavior ├── blink_frequency ├── brightness ├── color ├── device -> ../../../8C5DA44C-CDC3-46B3-8619-4E26D34390B7 ├── ethernet_type ├── hdd_default ├── indicator ├── max_brightness ├── power │ ├── autosuspend_delay_ms │ ├── control │ ├── runtime_active_time │ ├── runtime_status │ └── runtime_suspended_time ├── power_limit_scheme ├── ready_mode_blink_behavior ├── ready_mode_blink_frequency ├── ready_mode_brightness ├── s0_blink_behavior ├── s0_blink_frequency ├── s0_brightness ├── s3_blink_behavior ├── s3_blink_frequency ├── s3_brightness ├── s5_blink_behavior ├── s5_blink_frequency ├── s5_brightness ├── subsystem -> ../../../../../../../../class/leds ├── trigger └── uevent As the behavior of the LEDs can be dynamically changed, each LED expose parameters for all types of hardware event it can deal, but only the ones that are applied to its current indicator type can be seen/changed. On other words, the "indicator" tells what type of hardware event the LED is currently measuring: $ cat /sys/class/leds/nuc\:\:front1/indicator Power State [HDD Activity] Ethernet WiFi Software Power Limit Disable In this case, as it is measuring the HDD activity. If one tries to read/write something to, let's say, the Ethernet type, a -EINVAL is returned: $ cat /sys/class/leds/nuc\:\:front1/ethernet_type cat: '/sys/class/leds/nuc::front1/ethernet_type': Invalid argument So, before being able to use the ethernet_type, the indicator needs to be changed: $ echo Ethernet > /sys/class/leds/nuc\:\:front1/indicator $ cat /sys/class/leds/nuc\:\:front1/ethernet_type LAN1 LAN2 [LAN1+LAN2] Anyway, I suspect that besides a document under ABI, it would make sense to add a .rst file describing it under admin-guide, explaining how to use the ABI. That should likely be easier to discuss if any changes at the ABI would be needed. Before moving it out of staging, I would add another one under Documentation/ABI describing the meaning of each sysfs node. Would that work for you? Thanks, Mauro ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel