From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7B9513939C6; Fri, 27 Feb 2026 19:06:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219212; cv=pass; b=U3JwwuRPWDqGkCdk7QUfoAWl2cYaOFou4QY0Wp98aNV53fQr+tEn6cou9C3mQ3jZ8kJ9HpU3OqWDyTrlDeEweGT5T3VdisCTd1CA2TlnXCCHTW0Z+nnUxPaf8/ToVBL5dm2rBVel2JUXnUXOpJOT6vw1AXGQLsQax+dFcXRt4rY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219212; c=relaxed/simple; bh=O2znY7UBCkJ8aEJ+L9ZRaextBNOgb8dQOc90g9PZI84=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sgRk5btC29XoN4RR/KbnislHfAWuyZnuOoy6Q/YpG8aX+kXVb4Kf1Vb8yHT9tVuVkxYONWLZMX7GjP/LKFEdKNqhqZWh+TrPRDTha+AhmJgTAqJWaypAc0wYhSZtnimP6zAq5C92KtgMZAHro6GV5IhFp6oykMACC7GjM4I2riA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=pncNjs/a; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="pncNjs/a" ARC-Seal: i=1; a=rsa-sha256; t=1772219191; cv=none; d=zohomail.com; s=zohoarc; b=lUlOq3fd4RDRixkqVJvDfE/qkERa8ctVCI8ddq8bGTo4/6Nb4Q+v+ojT6J2MuJ7ww8mW3hXVuoWO2rAg96L6Wg+2hi3CR492teVONT8sjd+S77RL9KOsrUVBTedTXiF+u4FobNZ1y0K5aaNg6elgLQG9H5k2Q/NdYlV7CAGOMDw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219191; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=agLqAxnBrM1AWo0wht9pO0RhZJja5s7YuQDGBSPClV4=; b=g7Br1xigaP0uwED+0Iu9iGb/mJzrBFyLDsBqI2FsbIqUBiUqSXmXtgCEta7IDkIUfXf5gaoboDX0y52cW2OsrBLfPXoISU4Sen0gZKAU/LBtQSEUhfLVRWoMEZCfQpbyxI17mH4oLr4Uiax/6YZdf9gzdbaGGEWe5O9ept3FkcQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219191; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=agLqAxnBrM1AWo0wht9pO0RhZJja5s7YuQDGBSPClV4=; b=pncNjs/aMloR+ChccepObwWaxO/36IIsOuRpDx23UKlRLp0dFP5L/ApMi5krhjgv dni7A9MjjpiliGX3MYgsEmMSrQSku+ObpkRAxhDgAyY39+VhdVczEkHA5/cYx1hSQTn SRymJfIwlL1C2Ae/UygLJOjMHwySHzWCM/PtmKLTvXq+88uUvxnWT754Dn+c9kI8ZUl TzIZL7+S5gvg0fyJSyrwHjqqV9SnxhoxpKg/iMJpmEMavHINHXx4MTWRfhlCesiP+NI KBNj9RyciQSbWc3o2UQVJCv52DZCaKrkMsMBvqmKqUmSzOXCPOsSAcvVSm8A6+FkTNb eyYpu8wTeA== Received: by mx.zohomail.com with SMTPS id 1772219188704827.658173429945; Fri, 27 Feb 2026 11:06:28 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 1/9] leds: Load trigger modules on-demand if used as hw control trigger Date: Sat, 28 Feb 2026 03:05:58 +0800 Message-ID: <20260227190617.271388-2-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" In the following patches, we are about to support hardware initiated trigger transitions to/from the device's hw control trigger. In case the LED hardware switches itself to hw control mode, hw control trigger must be loaded before so that the transition can be processed. Load the trigger module specified by hw_control_trigger, so that hardware initiated trigger transitions can be processed when the hw control trigger is compiled as a module. Signed-off-by: Rong Zhang --- drivers/leds/led-class.c | 1 + drivers/leds/led-triggers.c | 33 +++++++++++++++++++++++++++++++++ drivers/leds/leds.h | 1 + 3 files changed, 35 insertions(+) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index d34a194535604..0fa45f22246e3 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -576,6 +576,7 @@ int led_classdev_register_ext(struct device *parent, =20 #ifdef CONFIG_LEDS_TRIGGERS led_trigger_set_default(led_cdev); + led_load_hw_control_trigger(led_cdev); #endif =20 mutex_unlock(&led_cdev->led_access); diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index b1223218bda11..3066bc91a5f94 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -313,6 +313,39 @@ void led_trigger_set_default(struct led_classdev *led_= cdev) } EXPORT_SYMBOL_GPL(led_trigger_set_default); =20 +static inline bool led_match_hw_control_trigger(struct led_classdev *led_c= dev, + struct led_trigger *trig) +{ + return (!strcmp(led_cdev->hw_control_trigger, trig->name) && + trigger_relevant(led_cdev, trig)); +} + +void led_load_hw_control_trigger(struct led_classdev *led_cdev) +{ + struct led_trigger *trig; + bool found =3D false; + + if (!led_cdev->hw_control_trigger) + return; + + /* default_trigger is handled by led_trigger_set_default(). */ + if (led_cdev->default_trigger && + !strcmp(led_cdev->default_trigger, led_cdev->hw_control_trigger)) + return; + + down_read(&triggers_list_lock); + list_for_each_entry(trig, &trigger_list, next_trig) { + found =3D led_match_hw_control_trigger(led_cdev, trig); + if (found) + break; + } + up_read(&triggers_list_lock); + + if (!found) + request_module_nowait("ledtrig:%s", led_cdev->hw_control_trigger); +} +EXPORT_SYMBOL_GPL(led_load_hw_control_trigger); + /* LED Trigger Interface */ =20 int led_trigger_register(struct led_trigger *trig) diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index bee46651e068f..e85afd4d04fd0 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -21,6 +21,7 @@ void led_init_core(struct led_classdev *led_cdev); void led_stop_software_blink(struct led_classdev *led_cdev); void led_set_brightness_nopm(struct led_classdev *led_cdev, unsigned int v= alue); void led_set_brightness_nosleep(struct led_classdev *led_cdev, unsigned in= t value); +void led_load_hw_control_trigger(struct led_classdev *led_cdev); ssize_t led_trigger_read(struct file *filp, struct kobject *kobj, const struct bin_attribute *attr, char *buf, loff_t pos, size_t count); --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D772A35A3B2; Fri, 27 Feb 2026 19:06:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219216; cv=pass; b=hPgFDSdx13xHEIVzASuInKaPOWHBkcAdJ7XE8NnfXM4KnsskWagiQhQEgzPyYih4XhyqJs7C4j0bK6E1PbhDoL03r6XxxEKrFpRuUjnNhDHHXeoKJlybiTqYUnUErHP0qfsKaD7YsCnI8jX+/ZNBnT4pyetzyM8p0dxUL/35vZ8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219216; c=relaxed/simple; bh=YlEq2gwnQExHgAJN223Fj4oRWgQXFbjuRJlvwVDO+sE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=X+rdF4xprKvno2Kt9K8zO5gc80qAeFq0fU5SmLV9559/yXoXHa8pLM5cwGiMMlLzwZl/V1rod3GPYFzuo5u0fSju8KaX0avgCynL8jxd4B22Yv4r4kxpc7fnhHj8aqKJU6U7+pWOz3iZUbIn8Li6q/AXlaa15U/cQQuL1o2JCwM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=K8vWew11; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="K8vWew11" ARC-Seal: i=1; a=rsa-sha256; t=1772219195; cv=none; d=zohomail.com; s=zohoarc; b=DBQFXqgoqmH0Hjf+7cV+4COaPLJgcm0FEM+KFPO1l0eG6l2fkc+VjAAM5Rk3hkmbvlxnqdTOslDThyEYjfI2BXpGNvyBgqAEG9pVIJY+afMeLP7+lIx5vXk2R/XqZxVqTMzj59b9Afs8N/4jqiNrvRL7QT/CECfuCLpJZBqemcw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219195; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=6HEv3x4ZyKN5PaiaRJ/PoMhUs2rC1x9QoWDYooM08oo=; b=D3UW4hrbEN8Z93q8Zx7d4dzqNbf+APPhqW4bgDwB9YcD1z940wFQ0luN1+RFTd3rfmDjQYgXk89moDcQUQUioBkZg4+aXjEMPSr4njNVXw2i21HZmUWwYcHX8eScB1GVDJSFQZlTjQfTyfuUrMLFXWImmoZTrL7vupcQfNS6znw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219195; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=6HEv3x4ZyKN5PaiaRJ/PoMhUs2rC1x9QoWDYooM08oo=; b=K8vWew11Ta1NHc3j/HfZ1KgfmdNPB21BX6TwjuXHb6KQ20t5mEywHvc3eLvWzTai SiyOZSw1iMJGcJCASGxwkUWizNmQ/K/vaFaPHTOCIUGhSgdlU7UxdFXY/Eth3AJKIwj HXGtD2TWTkxjHe89B+4TcXholtmItBv6lmGyZeo5mDFZk6Y5lApQtBM7HNkh/pCAscW 2KozBy+Eu9dspTuBneGyL/AAKlWRhCZfX/kbjx0lhxDeQvf6HAV9PwO3/6fTlohgwj5 i0zEnNMlzY5C9ML37eBMRuWny66V16l3ezDaPcmk/EeVUzjROteu1H++rnUCBwdtJ4E 5PtRPsNitQ== Received: by mx.zohomail.com with SMTPS id 1772219193143580.9193529328054; Fri, 27 Feb 2026 11:06:33 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 2/9] leds: Add callback offloaded() to query the state of hw control trigger Date: Sat, 28 Feb 2026 03:05:59 +0800 Message-ID: <20260227190617.271388-3-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Currently, we have multiple triggers implementing hw control. However, the LED core doesn't really know the hw control state since the coordination is done directly between the hw control trigger and the LED device. In the following patches, we are about to support hardware initiated trigger transitions to/from hw control trigger. The hw control state is a fundamental factor of determining if a transition should be permitted. Add a callback offloaded() so that the LED core can query the hw control state and use it to make decisions in hw initiated trigger transitions. Signed-off-by: Rong Zhang --- Documentation/leds/leds-class.rst | 5 +++++ include/linux/leds.h | 1 + 2 files changed, 6 insertions(+) diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-cl= ass.rst index 5db620ed27aa2..84665200a88dc 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -235,6 +235,11 @@ LED driver must implement the following API to support= hw control: Returns a pointer to a struct device or NULL if nothing is currently attached. =20 +LED trigger must implement the following API to support hw control: + - offloaded: + return a boolean indicating if the trigger is offloaded to + hardware. + LED driver can activate additional modes by default to workaround the impossibility of supporting each different mode on the supported trigger. Examples are hardcoding the blink speed to a set interval, enable special diff --git a/include/linux/leds.h b/include/linux/leds.h index b16b803cc1ac5..7332034a43c85 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -485,6 +485,7 @@ struct led_trigger { const char *name; int (*activate)(struct led_classdev *led_cdev); void (*deactivate)(struct led_classdev *led_cdev); + bool (*offloaded)(struct led_classdev *led_cdev); =20 /* Brightness set by led_trigger_event */ enum led_brightness brightness; --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DB9A3859D5; Fri, 27 Feb 2026 19:06:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219217; cv=pass; b=m7nodvEaIKHRM5SO1ssser7S9vVQ3XHfHJEU3smKbpA7xT0gXnq0bfPIua2IZHWIgQoBe+L4Sg42mF1aYccL6KUnGIE1i1aqgJPaoRPNubqVOdD7frrroL+gU2VJhjROV3bY4v1mGpU8EOjFVnoB/F87VX1lPn9RC6y/1pNDa7k= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219217; c=relaxed/simple; bh=T5OAaNmXzloJNopVsTbfdx+Ep2VacjxPhw8ZgNFSOs8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VoLz29E+erecIEFqmPGTCb0LcbZBOX+thNamZAsgd+vL5CJmNsDauYYoLeXxVinz0/P5zLX+BY/aEH5qtRakz5trOSspVCuhsnD7Il8JycBtp4AdG9T4uo59c6Kay25X/hPkYprElGYKZawvqjtDR/PtJwRST6GN9NQ85DIJ6y8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=Ps2O1zd0; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="Ps2O1zd0" ARC-Seal: i=1; a=rsa-sha256; t=1772219199; cv=none; d=zohomail.com; s=zohoarc; b=UxTZkdwztUkzj50bvT/+ffkqthW9DnGhso/nRWKwlDdMWou9FLwK8ij9lTt2vl2xu058wCtVscpZqFpGqvUtJKGL2lTTbhUZsVelX37AuVKjB6z6CZlpygJNBBfKPk92xdwCToTYPvebOi0t7Tt/X1mrd9x3QGrL3E35TdmrCSQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219199; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=HdicsRgarBX2PfmY3asMS9OdeY/On83EX0uOcpVMG4o=; b=K7jBJ8Kbb6ilHDA4sKJyNS8MV3Xe42eXiFZzrUAIRSjPtQzWKETQTRrWmkSq6iuU7rN016i4f9q7vxdlJDW4x9WxizyP1U6RXX1ccrVJgk84CXAyyFZf0AZL4vfWyaphOnUlGQfkpCqg7DBLuyTYVhBLuBQtBVlGMjyTfCV/+YY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219199; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=HdicsRgarBX2PfmY3asMS9OdeY/On83EX0uOcpVMG4o=; b=Ps2O1zd0Z50EgYZf7nIJ+98l1g4O5lWAI5iGy8ZANPh69YU2n4vWDMpCXqDDaLcS yKrLNnvNLu2Nhv5CMslRJg7o/D650s75DgslS0jsK/mm6qSedHYYVKx/gckuLSaG8ML fwB+0CILAj5a9M8Pjd/voQFJ/vehlj+VRWW4NcN+VihU86JPFMmwfpITgxbCq/KhdQO /wDkl0qQh+u0Npi7NgsUXnlKxpkgG2tZoo9hcKC8FbuaDXwusuqeQD5HLMXZj5kON7L ZtC34wDNuXYv97TLgDaPlJ8o/mDpB/8Ozwkk7F+SqCjSoHUSoKtzl3Vhy6lo63b+sOA 7ZD8iwCWvA== Received: by mx.zohomail.com with SMTPS id 177221919767957.845525955720746; Fri, 27 Feb 2026 11:06:37 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 3/9] leds: cros_ec: Implement offloaded() callback for trigger Date: Sat, 28 Feb 2026 03:06:00 +0800 Message-ID: <20260227190617.271388-4-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" "chromeos-auto" is a private hw control trigger which always stays in hw control mode. Implement offloaded() callback with its return value to be always true to reflect this. Signed-off-by: Rong Zhang --- drivers/leds/leds-cros_ec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/leds/leds-cros_ec.c b/drivers/leds/leds-cros_ec.c index bea3cc3fbfd2d..f48e3cf6ccf68 100644 --- a/drivers/leds/leds-cros_ec.c +++ b/drivers/leds/leds-cros_ec.c @@ -86,12 +86,18 @@ static int cros_ec_led_trigger_activate(struct led_clas= sdev *led_cdev) return cros_ec_led_send_cmd(priv->cros_ec, &arg); } =20 +static bool cros_ec_led_trigger_offloaded(struct led_classdev *led_cdev) +{ + return true; +} + static struct led_hw_trigger_type cros_ec_led_trigger_type; =20 static struct led_trigger cros_ec_led_trigger =3D { .name =3D "chromeos-auto", .trigger_type =3D &cros_ec_led_trigger_type, .activate =3D cros_ec_led_trigger_activate, + .offloaded =3D cros_ec_led_trigger_offloaded, }; =20 static int cros_ec_led_brightness_set_blocking(struct led_classdev *led_cd= ev, --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3FACC394474; Fri, 27 Feb 2026 19:07:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219223; cv=pass; b=SeDMq5mwF/47CySV6DposYj83L6mFq4yeGJ3Z6UXcFOwolZ2JCnajFGdE6+AVc+c4wm27eI11LVH3ABbVKPfR/OZkLZIzEX2d1xu5kImnmuoTVbdb10WW/Q8BxnHEqJobYio02wY6ER6oWqiKqqq07cwP3WS8iflcinGKtYZitw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219223; c=relaxed/simple; bh=4G9jj6Svg18/nMlvvboYLFlnTkufwv+NKjjxvrg/res=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f2imS35TuX3u8P3yBBjfk/HdiUrzzhJQBrDeYbYFWaf4wSMg0xo/aJ5FkHzmUaixqoBo4nj36sZprEgWS0S3pftbX3bEDzTf+5JRgaAzN39vJsFfURDfzsGFbNYGp9P3/om7qu2O2FoacKmCV6KjDa0GmxHVOYrHzkQTk/oi9rs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=DMTdmVsZ; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="DMTdmVsZ" ARC-Seal: i=1; a=rsa-sha256; t=1772219203; cv=none; d=zohomail.com; s=zohoarc; b=fpAm+z4U/ZQg1QnNnT0AEL/kRqxI2J+coIVG0up5iAqzygO6RxHvotWsqhEBSrIJ99g5J/5rRMKM2c6TtEFjQ1ehzfzta/P5/WCyB2pOVIMArz6KRaGQiDVIBf+cSB5ll0Hc6v+WTxpEdqkga/RWoDGR8+wRg4V5eietLwInzbQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219203; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=05z1dKWZxE0N/dh7NI8s6YbOHwuenxDNxo6cynRRIMI=; b=PxC8U9tE4O4iGCfQQWUxGV4ihds36go02bgq7LHB1CEfpKhCXduGuvvo+VTd6WxGEcuPi6OgHctpo7VXS4XWLBhxD/p686CqoAUq3AabItBh7+287wqlxdCRUx3ZItOj4wv+m5HYVheNhHuVXLJKQDKLg2e/2CVsOf0HoyyMZcI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219203; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=05z1dKWZxE0N/dh7NI8s6YbOHwuenxDNxo6cynRRIMI=; b=DMTdmVsZCYMrUPzXDJgVYKDtjTWQnFYLFzj1+sVwMKlyUOuyZ13PyrpwyY1SsG4F 1DZ5TIAanKUReJm1/xZ6DMVGDJO1Jp/ziA8TbQ2d1EDgyUd5KyoAqYSIHyaQNQkawTD zRBZ1LHvB0bqFGzj+N9XzZ2pHV/8vR5TO5O65azvdtAg5zI6Iza7+wvk+Ox0XSVfeLf Nz19gYKPvf5aYr3qhTKDL55Z696gu5e+SlMcrU2s9kXYhfOU7U4D28SP9LwL0Lwoo1k uebHPe/eGpLE0IrzoetWoLnbWc4tmNeEG6A7ncAX+DlfMnjorVCpR8qDA4M75x1620G tj9BzN8aIQ== Received: by mx.zohomail.com with SMTPS id 1772219202265523.2673967176976; Fri, 27 Feb 2026 11:06:42 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 4/9] leds: turris-omnia: Implement offloaded() callback for trigger Date: Sat, 28 Feb 2026 03:06:01 +0800 Message-ID: <20260227190617.271388-5-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" "omnia-mcu" is a private hw control trigger which always stays in hw control mode. Implement offloaded() callback with its return value to be always true to reflect this. Meanwhile, declare it as a hw control trigger as it's forgotten before. Signed-off-by: Rong Zhang --- drivers/leds/leds-turris-omnia.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-om= nia.c index 25ee5c1eb820b..8e016ca864030 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -195,10 +195,16 @@ static void omnia_hwtrig_deactivate(struct led_classd= ev *cdev) err); } =20 +static bool omnia_hwtrig_offloaded(struct led_classdev *cdev) +{ + return true; +} + static struct led_trigger omnia_hw_trigger =3D { .name =3D "omnia-mcu", .activate =3D omnia_hwtrig_activate, .deactivate =3D omnia_hwtrig_deactivate, + .offloaded =3D omnia_hwtrig_offloaded, .trigger_type =3D &omnia_hw_trigger_type, }; =20 @@ -251,6 +257,7 @@ static int omnia_led_register(struct i2c_client *client= , struct omnia_led *led, * by LED class from the linux,default-trigger property. */ cdev->default_trigger =3D omnia_hw_trigger.name; + cdev->hw_control_trigger =3D omnia_hw_trigger.name; =20 /* Put the LED into software mode */ ret =3D omnia_cmd_write_u8(client, OMNIA_CMD_LED_MODE, OMNIA_CMD_LED_MODE= _LED(led->reg) | --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26AA33859D5; Fri, 27 Feb 2026 19:07:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219229; cv=pass; b=ZuO9fcf0lMCAPG/jWhzlOue//WZmUKHbhHVPPLVu0r02mubILLQ/nkW7ubhyCD6lAxJ0+6unoN9UteristCsqrfpADnxbplktRcpTczSh6t4VQJTOht2M/4KQkpVa4EwqTtSZqPvDREDA0DqhDkWuClQdNhRBgQqVN5zBRG3WeM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219229; c=relaxed/simple; bh=PdOtx5vwFQKhHRytYzJ8DJbXPF7wk/uFhWbuT+OCtcQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GQ64xeyD6tiWuqqcrxYu2O0EXdrZZpaDDMVTME1PKg0rLX3HhfYwdqb3q4BNKLxtzNrFjWGOYVm5HeEqJUIdebJuN0IgCm4qhbPO9Ukqw5b45z2SRIpnGkfTedkVvIaGjM/hLgiPy+1VAm8SQSLRv/z3v40bv/8SmcuP67VWY6E= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=lE+yJ9kB; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="lE+yJ9kB" ARC-Seal: i=1; a=rsa-sha256; t=1772219209; cv=none; d=zohomail.com; s=zohoarc; b=Ma8HUPGS+WtqDIi31SVcRzMciLpPjdT2P3L6oHRYXp809Oyl/HL2fzewLfxZl1QU49UG4E9CQyQl5WtmKH7lxkCLfbA6Z+qk24TNsoWYAHA6jZuZG/bz/SITS8dCISA5mXvfNYIIZQ8GD7rbVcDccMIMOCxsNxn7lOgRhH5DiD8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219209; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=KTmVnBecFELsZ8QmsLB9wUAB9VOz3rEcL65GpIWR/Cw=; b=VTCOnsAjIO2qCWVWJUMWtBGjsutsw/FtG9HZClpPRfY7P8RMwXu1FGi9OS05yL14I8oPG+J/K1ZY6RfIUtTo4pwdlxC2zgUbtWnfoOmW6tr5TQvbs1VpsYq26k3zZG1MVWj6M0oWTgx1TOPGOytG931Y1hkVZsmczMxfO1iPB8s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219209; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=KTmVnBecFELsZ8QmsLB9wUAB9VOz3rEcL65GpIWR/Cw=; b=lE+yJ9kBHBVdWdRMs0zryMQPxBImcWW/D4Vxiq6gNgxnERUEC3MyG/BvvD7Rbigu cYISrQKeIIhpiuCgIaEOFHXN/jshZ/UPjfrtV+c0vQuhMi3fp1wN1Yabhu0OgyW6Say RJiJGtoz3OdlA2CuA/i+tni+D9XgXq5gygi96cFBC4CtpkOOv4QKjOkHmpcqsvfNGQN y9W3dnb7Eb625g/RDx7DWbZsnXCVe9PlBxTMpLL7RjXOikq1B8Y5XiZHK8iPx/q9FfF fEtIaZM+IB8XZBuD1zrCNWGyjyRma34/ukz7ckbfx+zB7koKazK78fys7Y8Rrogpnjb 9+9yM/rqIQ== Received: by mx.zohomail.com with SMTPS id 1772219206878348.8161742144895; Fri, 27 Feb 2026 11:06:46 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 5/9] leds: trigger: netdev: Implement offloaded() callback Date: Sat, 28 Feb 2026 03:06:02 +0800 Message-ID: <20260227190617.271388-6-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" "netdev" can run in hw control mode according to hw capabilities and trigger options. Implement offloaded() callback to provide its hw control state. Signed-off-by: Rong Zhang --- drivers/leds/trigger/ledtrig-netdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/l= edtrig-netdev.c index 12cb3311ea220..edde167b60a54 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -749,10 +749,18 @@ static void netdev_trig_deactivate(struct led_classde= v *led_cdev) kfree(trigger_data); } =20 +static bool netdev_trig_offloaded(struct led_classdev *led_cdev) +{ + struct led_netdev_data *trigger_data =3D led_get_trigger_data(led_cdev); + + return trigger_data->hw_control; +} + static struct led_trigger netdev_led_trigger =3D { .name =3D "netdev", .activate =3D netdev_trig_activate, .deactivate =3D netdev_trig_deactivate, + .offloaded =3D netdev_trig_offloaded, .groups =3D netdev_trig_groups, }; =20 --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3298C3A7F7C; Fri, 27 Feb 2026 19:07:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219234; cv=pass; b=L6W8wXck5mRGfA1VH+PAZcHJ+x6nizFphSOfERPSCGq4KW/crIMpdJVc689uSH2/IgikBSZuZaPkLDbG7SjvglAbqxBxSBjIPLbNXnBflLs86vZ/f3MmAhD/XXD0AAmJTv4BVApbKDt06I9D7+gYbsJ/nR9b4wmQG0m2tIeDxpM= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219234; c=relaxed/simple; bh=46xabc43SVTjpm9Q+KwpSamKHyJ2Sblrwkh97QbKtM8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hfcl+4e4OnHFbSMGNC8nC7KLxCCH1uO4pZc7IxtPjKSP44NtwGqRb73joUCcwRTYDfs2E3YDj4lQK48uVctANDB0xSB5zR92e6RmAw37ohs0iDAMZi1qc3ZngNWydGmhgYhWqRINYjFftJKwsXzFzjnDpG2UXgkeKgXvxI2qYRo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=oomNm/RS; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="oomNm/RS" ARC-Seal: i=1; a=rsa-sha256; t=1772219213; cv=none; d=zohomail.com; s=zohoarc; b=oCpvEpLSb3cvYqLbUIHlOwM7+3RqTg8JV1GMGx8QfCWMkGCctWIFB+KV9czW/cE8vs5c3vU+eSjWfTQtjDM3RYbyy3nYTKmVjZ4DX08CuUczbK6y+DHmdS8fdfV2P4qhj/DSIHhz3Fv9bIm4avPxl9Uhbpbz76TFDi5LL3IU+aY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219213; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=pfwFChO4XxRiKzeQdXTZAod9r1Evqeqe/sBBTyscmDQ=; b=Jf7bGwwhS8epU3L70GP3sF3Ae7YnFOMNwdAhTvaEjZLGpkEb1lzRUi1QsRyEfiJNX1uw34C+n0Y+eKVqJCP7nEcFFPvKaTDT+30oh0opwTGi+BrL6nsZPHNfH0jnnuTZqvLOsEDtbSlnt+UCcqk74tbxtgMmwkUlkYoaSeLcrKY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219213; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=pfwFChO4XxRiKzeQdXTZAod9r1Evqeqe/sBBTyscmDQ=; b=oomNm/RSgyfAVcstKvTaZrPxu4Qu4UNp2dz2qlq5EN/EB+1Oz6i+pFCrSrQLYfe+ MkSgoGafQajZCZAcv/3PyeyJZCneyqFNTgHnM4CFMEMK5Bc81yq6P2qKpSIZKn3v08J sSSbplrXTZBQGMF7FdNzvUGIX9ul+L0HNmSPjxgn4mOVQbDKBnnsRvJ5Tz4wyXjf4ib l4FtPn+lgY63jGq6Oca5f/3y4xGs4PCUCD9DebpTqHUqTG16KiER/rUVKDnndwPH6Vi uvOwb4HDoLjoin8ckkKBgj8VQ8n+t81M1FDlcGB5nFmDb59q2tRHhw6kh6hBDfMz3H6 boJ9Vjzdlg== Received: by mx.zohomail.com with SMTPS id 177221921233793.75743679643915; Fri, 27 Feb 2026 11:06:52 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 6/9] leds: Add trigger_may_offload attribute Date: Sat, 28 Feb 2026 03:06:03 +0800 Message-ID: <20260227190617.271388-7-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Currently, we have multiple triggers implementing hw control. Only "netdev" provides a custom attribute to determine if it's offloaded to hardware (i.e., in hw control mode). For other triggers, there is no obvious way userspace can determine the hw control state programmatically. Moreover, userspace can't even query if an LED device supports hw control and the name of hw control trigger. Add a new attribute "trigger_may_offload" to the LED core, so that userspace can determine: - if the LED device supports hw control (supported =3D> visible) - which trigger is the hw control trigger - if the hw control trigger is selected - if the hw control trigger is in hw control Signed-off-by: Rong Zhang --- .../obsolete/sysfs-class-led-trigger-netdev | 15 +++++++ Documentation/ABI/testing/sysfs-class-led | 22 ++++++++++ .../testing/sysfs-class-led-trigger-netdev | 13 ------ Documentation/leds/leds-class.rst | 4 +- drivers/leds/led-class.c | 22 ++++++++++ drivers/leds/led-triggers.c | 42 +++++++++++++++++++ drivers/leds/leds.h | 2 + drivers/leds/trigger/ledtrig-netdev.c | 2 + 8 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 Documentation/ABI/obsolete/sysfs-class-led-trigger-netd= ev diff --git a/Documentation/ABI/obsolete/sysfs-class-led-trigger-netdev b/Do= cumentation/ABI/obsolete/sysfs-class-led-trigger-netdev new file mode 100644 index 0000000000000..d1a7713d45700 --- /dev/null +++ b/Documentation/ABI/obsolete/sysfs-class-led-trigger-netdev @@ -0,0 +1,15 @@ +What: /sys/class/leds//offloaded +Date: March 2026 +Contact: linux-leds@vger.kernel.org +Description: + Communicate whether the LED trigger modes are offloaded to + hardware or whether software fallback is used. + + If 0, the LED is using software fallback to blink. + + If 1, the LED blinking in requested mode is offloaded to + hardware. + + Since 7.1, /sys/class/leds//trigger_may_offload provides + a generic method to query the offloaded state of supported + trigger, so this has been deprecated. diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/= testing/sysfs-class-led index 0313b82644f24..403f411b09036 100644 --- a/Documentation/ABI/testing/sysfs-class-led +++ b/Documentation/ABI/testing/sysfs-class-led @@ -78,6 +78,28 @@ Description: (which would often be configured in the device tree for the hardware). =20 +What: /sys/class/leds//trigger_may_offload +Date: March 2026 +KernelVersion: 7.1 +Contact: linux-leds@vger.kernel.org +Description: + Names and states of triggers that may be offloaded to hardware. + Such triggers are also called "hw control trigger" in some + context. + + Only exists when the LED supports trigger offload. + + Returns a list of hw control triggers on read. The optional + brackets around the trigger name indicate the state of the + current trigger: + + - `foo_trigger`: the trigger is not selected. + - ``: the trigger is selected, but falls back to + software blink for some reason (e.g., incompatible trigger + parameters) + - `[foo_trigger]`: the trigger is selected and offloaded to + hardware. + What: /sys/class/leds//inverted Date: January 2011 KernelVersion: 2.6.38 diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev b/Doc= umentation/ABI/testing/sysfs-class-led-trigger-netdev index ed46b37ab8a28..396d37a4b820d 100644 --- a/Documentation/ABI/testing/sysfs-class-led-trigger-netdev +++ b/Documentation/ABI/testing/sysfs-class-led-trigger-netdev @@ -62,19 +62,6 @@ Description: When offloaded is true, the blink interval is controlled by hardware and won't reflect the value set in interval. =20 -What: /sys/class/leds//offloaded -Date: Jun 2023 -KernelVersion: 6.5 -Contact: linux-leds@vger.kernel.org -Description: - Communicate whether the LED trigger modes are offloaded to - hardware or whether software fallback is used. - - If 0, the LED is using software fallback to blink. - - If 1, the LED blinking in requested mode is offloaded to - hardware. - What: /sys/class/leds//link_10 Date: Jun 2023 KernelVersion: 6.5 diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-cl= ass.rst index 84665200a88dc..cf7733e30bace 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -177,7 +177,9 @@ limited to blink but also to turn off or on autonomousl= y. To support this feature, a LED needs to implement various additional ops and needs to declare specific support for the supported triggers. =20 -With hw control we refer to the LED driven by hardware. +With hw control we refer to the LED driven by hardware. In hw control mode, +the current trigger is offloaded to hardware. The `trigger_may_offload` +attribute can be used to query supported triggers and their states. =20 LED driver must define the following value to support hw control: =20 diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 0fa45f22246e3..8a661e2616f06 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -90,8 +90,30 @@ static const struct bin_attribute *const led_trigger_bin= _attrs[] =3D { &bin_attr_trigger, NULL, }; + +static DEVICE_ATTR(trigger_may_offload, 0644, led_trigger_may_offload_show= , NULL); +static struct attribute *led_trigger_attrs[] =3D { + &dev_attr_trigger_may_offload.attr, + NULL, +}; +static umode_t led_trigger_is_visible(struct kobject *kobj, + struct attribute *attr, + int idx) +{ + struct device *dev =3D kobj_to_dev(kobj); + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + + if (attr =3D=3D &dev_attr_trigger_may_offload.attr && + !led_cdev->hw_control_trigger) + return 0; + + return attr->mode; +} + static const struct attribute_group led_trigger_group =3D { .bin_attrs =3D led_trigger_bin_attrs, + .attrs =3D led_trigger_attrs, + .is_visible =3D led_trigger_is_visible, }; #endif =20 diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 3066bc91a5f94..f8100381fc684 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -346,6 +346,48 @@ void led_load_hw_control_trigger(struct led_classdev *= led_cdev) } EXPORT_SYMBOL_GPL(led_load_hw_control_trigger); =20 +/* + * Caller must ensure led_cdev->trigger_lock held, + * and led_cdev->trigger->name must match led_cdev->hw_control_trigger. + */ +static bool led_trigger_get_offloaded(struct led_classdev *led_cdev) +{ + if (likely(led_cdev->trigger->offloaded)) + return led_cdev->trigger->offloaded(led_cdev); + + dev_err_once(led_cdev->dev, + "hw control trigger %s doesn't implement offloaded(), this is a bug= \n", + led_cdev->trigger->name); + return false; +} + +ssize_t led_trigger_may_offload_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + bool hit, offloaded =3D false; + int len; + + mutex_lock(&led_cdev->led_access); + down_read(&led_cdev->trigger_lock); + + hit =3D led_cdev->trigger && led_match_hw_control_trigger(led_cdev, led_c= dev->trigger); + if (hit) + offloaded =3D led_trigger_get_offloaded(led_cdev); + + /* [offloaded] inactive */ + len =3D led_trigger_snprintf(buf, PAGE_SIZE, + hit ? (offloaded ? "[%s]\n" : "<%s>\n") + : "%s\n", + led_cdev->hw_control_trigger); + + up_read(&led_cdev->trigger_lock); + mutex_unlock(&led_cdev->led_access); + + return len; +} +EXPORT_SYMBOL_GPL(led_trigger_may_offload_show); + /* LED Trigger Interface */ =20 int led_trigger_register(struct led_trigger *trig) diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index e85afd4d04fd0..ee0dbddd411ec 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -28,6 +28,8 @@ ssize_t led_trigger_read(struct file *filp, struct kobjec= t *kobj, ssize_t led_trigger_write(struct file *filp, struct kobject *kobj, const struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count); +ssize_t led_trigger_may_offload_show(struct device *dev, + struct device_attribute *attr, char *buf); =20 extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/l= edtrig-netdev.c index edde167b60a54..0a4f4469ff9b0 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -482,6 +482,8 @@ static ssize_t offloaded_show(struct device *dev, { struct led_netdev_data *trigger_data =3D led_trigger_get_drvdata(dev); =20 + dev_warn_once(dev, "offloaded attribute has been deprecated, see trigger_= may_offload.\n"); + return sprintf(buf, "%d\n", trigger_data->hw_control); } =20 --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A81483ACA73; Fri, 27 Feb 2026 19:07:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219245; cv=pass; b=Dcc52LaUsd8bEonxnrCBfoamEAu6+Df83lYsdGX3YIBBDZpjXeGmJWnktwg0n6AIDZj2/xWhYBs4TEdoThCL0YkrIGdBzEs6KZ+CNz5pSzPRhCAXWrye/fl+IqJp+ES/V2/SBWqEhNiLqzZB6GSl2d2zYVzYQ2ePAfP7bN5LODo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219245; c=relaxed/simple; bh=HwNejliywsHlXhuGsV4JjiX3+KM2IljuRgrnHkLZ7J0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DAuC0V+nGR5haIls3aGMaBGNI+Iws4a5lCt9wWSQbsCk8p5jLrgfZILL8A3Wdgo4OB1zYqSObYxFgaWIzHOWIbEQRzoiyW+FHKjFpwi3jmXcgCXRWlZssiRwSPvq4y5ZcLnJmrkluhN0KHsxDPEncJYpD+EjjlaGAwHWr939C74= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=Qm2Va7gO; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="Qm2Va7gO" ARC-Seal: i=1; a=rsa-sha256; t=1772219219; cv=none; d=zohomail.com; s=zohoarc; b=aZNzVU6ywwly+ZPDD+ljyX2DpC6U9BlUeTu++unjibm2gCsp3Cl/g/KR9bh55CYi7+UrUX9BWFR3+iP5G4uGd/UZLmWfR6LhMitf+Ej8b6JhnB3DtSBBxd4bD6HZg4npwx9RD7XMx/VI3OnNnK5FJjx8uEoAPg06c26tIOjyHI8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219219; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=h2BOgFH2gPijir1j9omklUnXSHfedWRVRfcdDkPTnMA=; b=Q4LiH+3HmhhM0gcMlqbDAJrTgldhCDr4R0wU7IrT8MmY+7x7JRlF5whIit2sV4F4HvhabHBs6UrlsB3OmE9ppMLU7l0GfdLpHuKGu4QPU47u4XCFSX5x6VTXrxjGL/ZVDLBzwM4BGEQP9N0qS8p/JBRPf2jjnJG+abBVi8TcW+8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219219; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=h2BOgFH2gPijir1j9omklUnXSHfedWRVRfcdDkPTnMA=; b=Qm2Va7gOGqKjUw2uSseeOfbEVMZ9KP/9M9uI8gpfHrboA6JuqMvfTm0ElScCiwP1 /BpoijLrJ3m8Mvx6Uo76pxtwAXy343Xv5PBYrnMJe86SJ26tdIfk2aEmqBgP72XCAgm vDveCrx7F+2DBeiHRQ/XZWUn25ZiD5j8YQbc1UkCuRxEGu7lw1/iFoNIqUzy7q55eib /2HDAnK7QiwCA7/jZrXWeiuBMWv/Ali900LGWGX0s+KW9kZi9g7EFioBG710LyLm76L SeZYVt5iS9CfSdKo1ck0nm3GjO/NqGoaZXqPJ1kvuyZoAe0l0jH32E7xh5ebwtuEITY gO0yJ60uIg== Received: by mx.zohomail.com with SMTPS id 1772219217707786.9061803165303; Fri, 27 Feb 2026 11:06:57 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 7/9] leds: trigger: Add led_trigger_notify_hw_control_changed() interface Date: Sat, 28 Feb 2026 03:06:04 +0800 Message-ID: <20260227190617.271388-8-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Some LED devices can autonomously activate/deactivate hw control mode. Currently, we have no mechanism for LED drivers to notify the LED core about such events and initiate a trigger transition to reflect the hardware state. Add a new interface called led_trigger_notify_hw_control_changed(), so that LED drivers can call it to notify the LED core about the transition. The interface only allows two transitions: 1. "none" =3D> hw control trigger (offloaded) 2. hw control trigger (offloaded) =3D> "none" If the current trigger is neither hw control trigger nor "none", or if hw control trigger is not offloaded, no trigger transition will be made. This protects selected sw triggers. Note that LED_OFF won't be emitted during the #2 transition, as some hardware may have selected a new brightness level during its hardware state transition (e.g., laptop keyboards with a shortcut cycling through different backlight brightnesses and auto mode). The interface is designed as a void function as any failure should be non-fatal and the result of transition should not have any impact on the LED drivers' event handling procedures. Signed-off-by: Rong Zhang --- Documentation/leds/leds-class.rst | 63 +++++++++++++++++++ drivers/leds/led-triggers.c | 101 +++++++++++++++++++++++++++++- include/linux/leds.h | 5 ++ 3 files changed, 166 insertions(+), 3 deletions(-) diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-cl= ass.rst index cf7733e30bace..4d84db1067b43 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -255,9 +255,72 @@ the end use hw_control_set to activate hw control. A trigger can use hw_control_get to check if a LED is already in hw control and init their flags. =20 +Alternatively, a private trigger can be implemented along with the LED dri= ver +if the hw control mode of the LED doesn't fit any generic trigger. To asso= ciate +the private trigger with the LED classdev, their `trigger_type` must be th= e same. +The name of the private trigger must be the same as `hw_control_trigger`. = Since +both the LED classdev and the private trigger are in the same LED driver, = it's not +necessary for them to coordinate via `hw_control_*` callbacks. + When the LED is in hw control, no software blink is possible and doing so will effectively disable hw control. =20 +Hardware initiated hw control mode transition +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Some hardware can autonomously activate/deactivate hw control mode. After = the +mode transition, the LED hardware notifies the LED driver. To update the c= urrent +trigger accordingly, call `led_trigger_notify_hw_control_changed` on the +classdev. The driver must set `hw_control_trigger` before registering, or = else +calling this is a bug and will trigger a WARN_ON. An LED driver that imple= ments +a private trigger can pass a pointer to the private trigger as the last +parameter, otherwise NULL should be passed. The private trigger must have = been +properly registered (see above) and named after `hw_control_trigger`, or e= lse a +WARN_ON will be triggered. + +For convenience, `hw_control_trigger` refers to a trigger name defined in = LED +classdev, while "hw control trigger" refers to a unique trigger with the +same name as the former. + +Only two transitions are defined: + +- "none" =3D> hw control trigger (offloaded): + This happens when the hardware autonomously activates hw control m= ode + and when "none" (i.e., no trigger) is currently active. If the hw + control trigger is already active and offloaded during the hw cont= rol + mode transition, this is essentially a no-op. + + The activation sequence for the hw control trigger will be execute= d as + normal. After switching to the hw control trigger, its offloaded s= tatus + is checked and must be true. Failing to set the offloaded status + appropriately will trigger a WARN_ON. + + The LED driver must be able to handle the activation sequence even= if + the hardware is currently under hw control mode. If the hardware c= an + handle hw control mode transition idempotently, the LED driver pro= bably + already has this capability. Otherwise, the LED driver should take= extra + care to handle the transition. + + If error occurs in the activation sequence, the LED Trigger core r= everts + the effective trigger to "none". + +- hw control trigger (offloaded) =3D> "none" + This happens when the hardware autonomously deactivates hw control= mode + and when the hw control trigger is currently active and offloaded.= If + "none" (i.e., no trigger) is active during the hw control mode + transition, this is essentially a no-op. + + The deactivation sequence for the hw control trigger will be execu= ted as + normal, except that the current LED brightness is retained. The re= ason + for keeping the brightness unchanged is that some hardware may cho= ose a + specific brightness instead of simply turning off the LED during i= ts hw + control mode transition. + + The idempotence rule also applies. + +If the current trigger is neither hw control trigger nor "none", or if hw +control trigger is not offloaded, no transition will be made. + Known Issues =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index f8100381fc684..0d0279ac8291b 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -7,6 +7,7 @@ * Author: Richard Purdie */ =20 +#include #include #include #include @@ -162,8 +163,8 @@ ssize_t led_trigger_read(struct file *filp, struct kobj= ect *kobj, } EXPORT_SYMBOL_GPL(led_trigger_read); =20 -/* Caller must ensure led_cdev->trigger_lock held */ -int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *tri= g) +static int __led_trigger_set(struct led_classdev *led_cdev, struct led_tri= gger *trig, + bool hw_triggered) { char *event =3D NULL; char *envp[2]; @@ -194,7 +195,15 @@ int led_trigger_set(struct led_classdev *led_cdev, str= uct led_trigger *trig) led_cdev->trigger_data =3D NULL; led_cdev->activated =3D false; led_cdev->flags &=3D ~LED_INIT_DEFAULT_TRIGGER; - led_set_brightness(led_cdev, LED_OFF); + + /* + * Hardware may have select a new brightness level during its + * hw control mode transition, so only reset brightness if we + * are switching to another trigger or if the switching is not + * hardware triggered. + */ + if (trig || !hw_triggered) + led_set_brightness(led_cdev, LED_OFF); } if (trig) { spin_lock(&trig->leddev_list_lock); @@ -258,6 +267,12 @@ int led_trigger_set(struct led_classdev *led_cdev, str= uct led_trigger *trig) =20 return ret; } + +/* Caller must ensure led_cdev->trigger_lock held */ +int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *tri= g) +{ + return __led_trigger_set(led_cdev, trig, false); +} EXPORT_SYMBOL_GPL(led_trigger_set); =20 void led_trigger_remove(struct led_classdev *led_cdev) @@ -478,6 +493,86 @@ int devm_led_trigger_register(struct device *dev, } EXPORT_SYMBOL_GPL(devm_led_trigger_register); =20 +static void led_trigger_do_hw_control_transition(struct led_classdev *led_= cdev, bool activate, + struct led_trigger *hc_trig) +{ + int err =3D 0; + + if (!led_cdev->trigger) { + /* "none" =3D> hw control trigger (offloaded). */ + if (activate) { + err =3D __led_trigger_set(led_cdev, hc_trig, true); + + /* + * hw control trigger must recognize the current hw state during + * its activation and mark itself as offloaded. + */ + WARN_ON(!err && !led_trigger_get_offloaded(led_cdev)); + } + } else if (led_cdev->trigger =3D=3D hc_trig && led_trigger_get_offloaded(= led_cdev)) { + /* hw control trigger (offloaded) =3D> "none". */ + if (!activate) + err =3D __led_trigger_set(led_cdev, NULL, true); + } else { + /* Other trigger is active, or hw control trigger is not offloaded. */ + dev_dbg(led_cdev->dev, + "Do not %s hw control trigger %s while %s is active", + activate ? "activate" : "deactivate", hc_trig->name, + led_cdev->trigger->name); + + return; + } + + if (err) + dev_warn(led_cdev->dev, "Failed to %s hw control trigger %s: %d", + activate ? "activate" : "deactivate", hc_trig->name, err); +} + +/* Caller must ensure led_cdev->led_access held */ +void led_trigger_notify_hw_control_changed(struct led_classdev *led_cdev, = bool activate, + struct led_trigger *priv_trig) +{ + struct led_trigger *trig; + + down_write(&led_cdev->trigger_lock); + + if (WARN_ON(!led_cdev->hw_control_trigger)) + goto out; + + /* Fast path: hw control trigger is a private trigger. */ + if (priv_trig) { + if (WARN_ON(!led_match_hw_control_trigger(led_cdev, priv_trig))) + goto out; + + led_trigger_do_hw_control_transition(led_cdev, activate, priv_trig); + goto out; + } + + /* Fast path: hw control trigger is the current trigger. */ + if (led_cdev->trigger && led_match_hw_control_trigger(led_cdev, led_cdev-= >trigger)) { + led_trigger_do_hw_control_transition(led_cdev, activate, led_cdev->trigg= er); + goto out; + } + + down_read(&triggers_list_lock); + list_for_each_entry(trig, &trigger_list, next_trig) { + if (led_match_hw_control_trigger(led_cdev, trig)) { + led_trigger_do_hw_control_transition(led_cdev, activate, trig); + + up_read(&triggers_list_lock); + goto out; + } + } + up_read(&triggers_list_lock); + + dev_dbg(led_cdev->dev, "hw control trigger not found: %s", + led_cdev->hw_control_trigger); + +out: + up_write(&led_cdev->trigger_lock); +} +EXPORT_SYMBOL_GPL(led_trigger_notify_hw_control_changed); + /* Simple LED Trigger Interface */ =20 void led_trigger_event(struct led_trigger *trig, diff --git a/include/linux/leds.h b/include/linux/leds.h index 7332034a43c85..82578724fd60c 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -533,6 +533,8 @@ void led_trigger_blink_oneshot(struct led_trigger *trig= ger, int invert); void led_trigger_set_default(struct led_classdev *led_cdev); int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *tri= gger); +void led_trigger_notify_hw_control_changed(struct led_classdev *led_cdev, = bool activate, + struct led_trigger *priv_trig); void led_trigger_remove(struct led_classdev *led_cdev); =20 static inline void led_set_trigger_data(struct led_classdev *led_cdev, @@ -583,6 +585,9 @@ static inline int led_trigger_set(struct led_classdev *= led_cdev, { return 0; } +static inline void led_trigger_notify_hw_control_changed(struct led_classd= ev *led_cdev, + bool activate, + struct led_trigger *priv_trig) {} =20 static inline void led_trigger_remove(struct led_classdev *led_cdev) {} static inline void led_set_trigger_data(struct led_classdev *led_cdev) {} --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34CD63859CB; Fri, 27 Feb 2026 19:07:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219241; cv=pass; b=SuXpp5GzAsTIkfkG/CFF4bargoaznwOCaYQWBU2WlExRHRv/s/C4ouMW9Q/t86YFvTf+UU9J0wwRWR/O/7cVpwa6U3mQUnrVDR52n1ssvgzUWJwVZWIW7Aye6Y+OLkm68rAon1aHoaZ7UPiidD1idVD+3sjLAc4RAXpRnLmNh0E= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219241; c=relaxed/simple; bh=eQs8UtEW4GMqtNXX/FhanPTQXPpVEotyg/qfpWuDQOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qGbFD/4QohuZuEIOVL6ZDjcEk/oGeZs/aYWNrQnFQSFFiMER2gHW3WMycIIvG1oRSkPk3wR38skg8NgWM8EdjVeq+1/Ezv916FGTlHOLO6xd+a/bTUgmorw4a+NYteupm8A80QROIi6Pr8/FppGgx0tfkPHephcgsWW3DKcHJ1c= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=k16FLxJ3; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="k16FLxJ3" ARC-Seal: i=1; a=rsa-sha256; t=1772219223; cv=none; d=zohomail.com; s=zohoarc; b=HnG2q/yS6tFJL4dj04owLkpugAaRjNNPuMOdzgSG5p+xIrLVMVxlpBPYnZiq9UOheY2qb03fcnkQgfjJM18YeowZBg+l17Cy0E+WaTXTpqZTaZ40du3FkOITqNdGU6UrxZIwTbp9LRSOpvcm3k9J5sd9TFbX83ejmz5b+SNQzRo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219223; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=GBopvb0XLYM5a5cYSz2Hjnrp4LOHHlYa0YRcHewmDc0=; b=H0AP+gTTbhODpzG9Kc/rBDG3f4nRIQAdpIEaxqPK8a6kS3U1u+Fq3JVQQbKRV32XOQstCzCYFFiMQPHmic6PIGMQPHrSHxFfG0j7y6uaUXL1Pv/lgvGptI+xIiB8K7I3RrAs1t5EVmGlBqtfHn8ZVQz6fjWULNYvgOcN4zgb8oA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219223; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=GBopvb0XLYM5a5cYSz2Hjnrp4LOHHlYa0YRcHewmDc0=; b=k16FLxJ3V4lraSO9m45g6elJrcK7ai1ECN73M9+noQq9qg4zCdLcpH1wMVyaq2PF Rii66RSjHklDVImNKtc9dTA44AhIbjHG7UGdkt1UXtvJHH8oiOzCotiDgNMEyTfLpde npP4BEK8q3t1jCu+zeaTHfx4BGWplky0p6ZX+Njyt09oMKeKRJrNJn0jJ7FOyrV/A8E M9KY/OojsSsiMZBe1k2BrtfseFUir6nUAey/SE5lTylT6WqjCSKwL0MAwYmdMN4qx4o yiV5pM7EPVgZLtMu1UPmFyXjHe/DrS5LmQv8+TEe0cGgH6tbrvuG1EDXX+9y07mTMp4 73i3OQh/5g== Received: by mx.zohomail.com with SMTPS id 1772219222496341.97858049630565; Fri, 27 Feb 2026 11:07:02 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 8/9] platform/x86: ideapad-laptop: Decouple HW & cdev brightness for kbd backlight Date: Sat, 28 Feb 2026 03:06:05 +0800 Message-ID: <20260227190617.271388-9-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Some recent models come with an ambient light sensor (ALS). On these models, their EC will automatically set the keyboard backlight to an appropriate brightness when the effective "HW brightness" is 3. "HW brightness" can't be perfectly mapped to an LED classdev brightness, but the EC does use this predefined brightness value to represent auto mode. Currently, the code processing keyboard backlight is coupled with LED classdev, making it hard to expose the auto brightness (ALS) mode to the userspace. As the first step toward the goal, decouple HW brightness from LED classdev brightness, and update comments about corresponding backlight modes. Signed-off-by: Rong Zhang --- drivers/platform/x86/lenovo/ideapad-laptop.c | 114 +++++++++++++------ 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/drivers/platform/x86/lenovo/ideapad-laptop.c b/drivers/platfor= m/x86/lenovo/ideapad-laptop.c index ae1ebb071fab0..b9af0294fc933 100644 --- a/drivers/platform/x86/lenovo/ideapad-laptop.c +++ b/drivers/platform/x86/lenovo/ideapad-laptop.c @@ -134,10 +134,31 @@ enum { }; =20 /* - * These correspond to the number of supported states - 1 - * Future keyboard types may need a new system, if there's a collision - * KBD_BL_TRISTATE_AUTO has no way to report or set the auto state - * so it effectively has 3 states, but needs to handle 4 + * The enumeration has two purposes: + * - as an internal identifier for all known types of keyboard backlight + * - as a mandatory parameter of the KBLC command + * + * For each type, the HW brightness values are defined as follows: + * +--------------------------+----------+-----+------+------+ + * | HW brightness | 0 | 1 | 2 | 3 | + * | Type | | | | | + * +--------------------------+----------+-----+------+------+ + * | KBD_BL_STANDARD | off | on | N/A | N/A | + * +--------------------------+----------+-----+------+------+ + * | KBD_BL_TRISTATE | off | low | high | N/A | + * +--------------------------+----------+-----+------+------+ + * | KBD_BL_TRISTATE_AUTO | off | low | high | auto | + * +--------------------------+----------+-----+------+------+ + * + * We map LED classdev brightness for KBD_BL_TRISTATE_AUTO as follows: + * +--------------------------+----------+-----+------+ + * | LED classdev brightness | 0 | 1 | 2 | + * | Operation | | | | + * +--------------------------+----------+-----+------+ + * | Read | off/auto | low | high | + * +--------------------------+----------+-----+------+ + * | Write | off | low | high | + * +--------------------------+----------+-----+------+ */ enum { KBD_BL_STANDARD =3D 1, @@ -1592,7 +1613,24 @@ static int ideapad_kbd_bl_check_tristate(int type) return (type =3D=3D KBD_BL_TRISTATE) || (type =3D=3D KBD_BL_TRISTATE_AUTO= ); } =20 -static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv) +static int ideapad_kbd_bl_brightness_parse(struct ideapad_private *priv, + unsigned int hw_brightness) +{ + /* Off, low or high */ + if (hw_brightness <=3D priv->kbd_bl.led.max_brightness) + return hw_brightness; + + /* Auto, report as off */ + if (hw_brightness =3D=3D priv->kbd_bl.led.max_brightness + 1) + return 0; + + /* Unknown value */ + dev_warn(&priv->platform_device->dev, + "Unknown keyboard backlight value: %u", hw_brightness); + return -EINVAL; +} + +static int ideapad_kbd_bl_hw_brightness_get(struct ideapad_private *priv) { unsigned long value; int err; @@ -1606,21 +1644,7 @@ static int ideapad_kbd_bl_brightness_get(struct idea= pad_private *priv) if (err) return err; =20 - /* Convert returned value to brightness level */ - value =3D FIELD_GET(KBD_BL_GET_BRIGHTNESS, value); - - /* Off, low or high */ - if (value <=3D priv->kbd_bl.led.max_brightness) - return value; - - /* Auto, report as off */ - if (value =3D=3D priv->kbd_bl.led.max_brightness + 1) - return 0; - - /* Unknown value */ - dev_warn(&priv->platform_device->dev, - "Unknown keyboard backlight value: %lu", value); - return -EINVAL; + return FIELD_GET(KBD_BL_GET_BRIGHTNESS, value); } =20 err =3D eval_hals(priv->adev->handle, &value); @@ -1630,6 +1654,16 @@ static int ideapad_kbd_bl_brightness_get(struct idea= pad_private *priv) return !!test_bit(HALS_KBD_BL_STATE_BIT, &value); } =20 +static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv) +{ + int hw_brightness =3D ideapad_kbd_bl_hw_brightness_get(priv); + + if (hw_brightness < 0) + return hw_brightness; + + return ideapad_kbd_bl_brightness_parse(priv, hw_brightness); +} + static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct l= ed_classdev *led_cdev) { struct ideapad_private *priv =3D container_of(led_cdev, struct ideapad_pr= ivate, kbd_bl.led); @@ -1637,24 +1671,31 @@ static enum led_brightness ideapad_kbd_bl_led_cdev_= brightness_get(struct led_cla return ideapad_kbd_bl_brightness_get(priv); } =20 -static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, uns= igned int brightness) +static int ideapad_kbd_bl_hw_brightness_set(struct ideapad_private *priv, + unsigned int hw_brightness) { - int err; unsigned long value; int type =3D priv->kbd_bl.type; =20 if (ideapad_kbd_bl_check_tristate(type)) { - if (brightness > priv->kbd_bl.led.max_brightness) - return -EINVAL; - - value =3D FIELD_PREP(KBD_BL_SET_BRIGHTNESS, brightness) | + value =3D FIELD_PREP(KBD_BL_SET_BRIGHTNESS, hw_brightness) | FIELD_PREP(KBD_BL_COMMAND_TYPE, type) | KBD_BL_COMMAND_SET; - err =3D exec_kblc(priv->adev->handle, value); + return exec_kblc(priv->adev->handle, value); } else { - err =3D exec_sals(priv->adev->handle, brightness ? SALS_KBD_BL_ON : SALS= _KBD_BL_OFF); + value =3D hw_brightness ? SALS_KBD_BL_ON : SALS_KBD_BL_OFF; + return exec_sals(priv->adev->handle, value); } +} + +static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, uns= igned int brightness) +{ + int err; =20 + if (brightness > priv->kbd_bl.led.max_brightness) + return -EINVAL; + + err =3D ideapad_kbd_bl_hw_brightness_set(priv, brightness); if (err) return err; =20 @@ -1671,6 +1712,16 @@ static int ideapad_kbd_bl_led_cdev_brightness_set(st= ruct led_classdev *led_cdev, return ideapad_kbd_bl_brightness_set(priv, brightness); } =20 +static void ideapad_kbd_bl_notify_known(struct ideapad_private *priv, unsi= gned int brightness) +{ + if (brightness =3D=3D priv->kbd_bl.last_brightness) + return; + + priv->kbd_bl.last_brightness =3D brightness; + + led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness); +} + static void ideapad_kbd_bl_notify(struct ideapad_private *priv) { int brightness; @@ -1682,12 +1733,7 @@ static void ideapad_kbd_bl_notify(struct ideapad_pri= vate *priv) if (brightness < 0) return; =20 - if (brightness =3D=3D priv->kbd_bl.last_brightness) - return; - - priv->kbd_bl.last_brightness =3D brightness; - - led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness); + ideapad_kbd_bl_notify_known(priv, brightness); } =20 static int ideapad_kbd_bl_init(struct ideapad_private *priv) --=20 2.51.0 From nobody Thu Apr 16 12:32:25 2026 Received: from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com [136.143.188.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D459E3ACA75; Fri, 27 Feb 2026 19:07:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219249; cv=pass; b=NT8byINMMGUmkgJO/AV9uc3EyelT3MeNAD+KAFIHBJmpCjV+7Rqsc6KbEo70L0LLBYlyQ0uHFW++Gg1XCQNDTLB5KKphgW11H8iGJm40IwJfT5e694NpD82dG0B+jmKpRv7/PJEDklyI3VgLfLgc5RqapaLcQ2l/2Lybr6bEyCo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772219249; c=relaxed/simple; bh=LHdlgbZdlT4nP6fQoLCZOUarUM7jZ8R1s47iOhbszmY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mdMkNRmfhMLdFpxZ9T7AZFR9coD/0C8qjPVYBFGiF3L147tcIMuIecuhCM4tHu700WcZKxQJttkytXriKJ6H4WahZghjHrDA3LbazkFa1oj4q3ueccamto4Cd+dbok8HIskA/T0dDmirmUFu7GnBT6pfWiTgrrfi5y4eu+4ix8I= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe; spf=pass smtp.mailfrom=rong.moe; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b=iMVRizpU; arc=pass smtp.client-ip=136.143.188.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rong.moe Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rong.moe Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=rong.moe header.i=i@rong.moe header.b="iMVRizpU" ARC-Seal: i=1; a=rsa-sha256; t=1772219229; cv=none; d=zohomail.com; s=zohoarc; b=bypRroFizliXTlL+3DwxNDvTi+uaA/T627nGOVuWCEXjaV6DLS7E9xdHXEgfuoskeBgLtRV1aAJhrk1dHAJwWAVYZPvkU/uLAsi8tVd4fCsG0ZAlQKug9opc0cg0GfSAOrVQjqoXsVwyiwsxbE9LUtwN+ZNptu7wBqrEumdQK4E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1772219229; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=8wOh/AymQVXYTDItmjH7CdiSiuTr2WE8bT2ZCK9KUvk=; b=fjNdjaow6ZQVAbBJOPVtRR8krApYC693HnPV4p8Uf//fhR92qID/UOv72yMdv5IBoLVw3KcZeqXMEykft+GPj/6p73f+5sODllZ13jji637f3Z47RVdRdjoXGpxbYlSOTLlbCgn251h4alLOb9AOL52woFcA5Cevjg40OVnJJIU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=rong.moe; spf=pass smtp.mailfrom=i@rong.moe; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1772219229; s=zmail2048; d=rong.moe; i=i@rong.moe; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=8wOh/AymQVXYTDItmjH7CdiSiuTr2WE8bT2ZCK9KUvk=; b=iMVRizpURyijzScdidaH3jeC5uqhkd6dDRb8NDDZf9M3zmLvMEvc5IgzD0GZpKgt nJv4f1jGI/u6n17pCb/6umcf9/FfcW5pwghoVt2vmBJVWWUwYKWMUesMcROdRrMLSuU 0lWABWXOyKR0+Zh64d72F38zFlk8KNKllMQPZUvoP/6bCfxmNJRYq7o7gtCc9PvGL6Y v+HDXTVJbEFjAdb1vjbYicHngaw8fZxFRWZy2H+jVnbcXVrEPAqCTVXQV+PiP8NOtA0 ETTriz5gWKTn6xyOR9bQkBeUeJ/ww/aH0wT/m/EFocY4LrOg+Uvk36p0q4TWWtYjLOr Q3vy2BUykw== Received: by mx.zohomail.com with SMTPS id 1772219227158191.8325362377376; Fri, 27 Feb 2026 11:07:07 -0800 (PST) From: Rong Zhang To: Lee Jones , Pavel Machek , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Benson Leung , Guenter Roeck , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Mark Pearson , "Derek J. Clark" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Ike Panhc Cc: Rong Zhang , Vishnu Sankar , vsankar@lenovo.com, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org, chrome-platform@lists.linux.dev, platform-driver-x86@vger.kernel.org Subject: [RFC PATCH 9/9] platform/x86: ideapad-laptop: Fully support auto kbd backlight Date: Sat, 28 Feb 2026 03:06:06 +0800 Message-ID: <20260227190617.271388-10-i@rong.moe> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260227190617.271388-1-i@rong.moe> References: <20260227190617.271388-1-i@rong.moe> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Currently, the auto brightness mode of keyboard backlight maps to brightness=3D0 in LED classdev. The only method to switch to such a mode is by pressing the manufacturer-defined shortcut (Fn+Space). However, 0 is a multiplexed brightness value; writing 0 simply results in the backlight being turned off. With brightness processing code decoupled from LED classdev, we can now fully support the auto brightness mode. In this mode, the keyboard backlight is controlled by the EC according to the ambient light sensor (ALS). To utilize this, a private hw control trigger "ideapad-auto" is added, with the event handling procedure calling the led_trigger_notify_hw_control_changed() interface to activate/deactivate the private trigger according to the current LED trigger state. Meanwhile, block brightness changes on exit to prevent the side effect of LED device unregistration when the private trigger is active from resetting the brightness to zero, so that we can retain the state of auto mode among boots. Signed-off-by: Rong Zhang --- drivers/platform/x86/lenovo/Kconfig | 1 + drivers/platform/x86/lenovo/ideapad-laptop.c | 86 ++++++++++++++++++-- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/len= ovo/Kconfig index f885127b007f1..626180370add4 100644 --- a/drivers/platform/x86/lenovo/Kconfig +++ b/drivers/platform/x86/lenovo/Kconfig @@ -16,6 +16,7 @@ config IDEAPAD_LAPTOP select INPUT_SPARSEKMAP select NEW_LEDS select LEDS_CLASS + select LEDS_TRIGGERS help This is a driver for Lenovo IdeaPad netbooks contains drivers for rfkill switch, hotkey, fan control and backlight control. diff --git a/drivers/platform/x86/lenovo/ideapad-laptop.c b/drivers/platfor= m/x86/lenovo/ideapad-laptop.c index b9af0294fc933..99cdd18cc1a5d 100644 --- a/drivers/platform/x86/lenovo/ideapad-laptop.c +++ b/drivers/platform/x86/lenovo/ideapad-laptop.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -166,6 +167,8 @@ enum { KBD_BL_TRISTATE_AUTO =3D 3, }; =20 +#define KBD_BL_AUTO_MODE_HW_BRIGHTNESS 3 + #define KBD_BL_QUERY_TYPE 0x1 #define KBD_BL_TRISTATE_TYPE 0x5 #define KBD_BL_TRISTATE_AUTO_TYPE 0x7 @@ -1620,8 +1623,9 @@ static int ideapad_kbd_bl_brightness_parse(struct ide= apad_private *priv, if (hw_brightness <=3D priv->kbd_bl.led.max_brightness) return hw_brightness; =20 - /* Auto, report as off */ - if (hw_brightness =3D=3D priv->kbd_bl.led.max_brightness + 1) + /* Auto (controlled by EC according to ALS), report as off */ + if (priv->kbd_bl.type =3D=3D KBD_BL_TRISTATE_AUTO && + hw_brightness =3D=3D KBD_BL_AUTO_MODE_HW_BRIGHTNESS) return 0; =20 /* Unknown value */ @@ -1709,9 +1713,39 @@ static int ideapad_kbd_bl_led_cdev_brightness_set(st= ruct led_classdev *led_cdev, { struct ideapad_private *priv =3D container_of(led_cdev, struct ideapad_pr= ivate, kbd_bl.led); =20 + /* + * When deinitializing: It must be the side effect of led_cdev + * unregistration when our private trigger is active. We've set + * LED_RETAIN_AT_SHUTDOWN to retain led_cdev brightness level. To do the + * same for auto mode, gate changes and return early. + */ + if (unlikely(!priv->kbd_bl.initialized)) + return 0; + return ideapad_kbd_bl_brightness_set(priv, brightness); } =20 +static int ideapad_kbd_bl_auto_trigger_activate(struct led_classdev *led_c= dev) +{ + struct ideapad_private *priv =3D container_of(led_cdev, struct ideapad_pr= ivate, kbd_bl.led); + + return ideapad_kbd_bl_hw_brightness_set(priv, KBD_BL_AUTO_MODE_HW_BRIGHTN= ESS); +} + +static bool ideapad_kbd_bl_auto_trigger_offloaded(struct led_classdev *led= _cdev) +{ + return true; +} + +static struct led_hw_trigger_type ideapad_kbd_bl_auto_trigger_type; + +static struct led_trigger ideapad_kbd_bl_auto_trigger =3D { + .name =3D "ideapad-auto", + .trigger_type =3D &ideapad_kbd_bl_auto_trigger_type, + .activate =3D ideapad_kbd_bl_auto_trigger_activate, + .offloaded =3D ideapad_kbd_bl_auto_trigger_offloaded, +}; + static void ideapad_kbd_bl_notify_known(struct ideapad_private *priv, unsi= gned int brightness) { if (brightness =3D=3D priv->kbd_bl.last_brightness) @@ -1724,12 +1758,23 @@ static void ideapad_kbd_bl_notify_known(struct idea= pad_private *priv, unsigned i =20 static void ideapad_kbd_bl_notify(struct ideapad_private *priv) { - int brightness; + int hw_brightness, brightness; =20 if (!priv->kbd_bl.initialized) return; =20 - brightness =3D ideapad_kbd_bl_brightness_get(priv); + hw_brightness =3D ideapad_kbd_bl_hw_brightness_get(priv); + if (hw_brightness < 0) + return; + + if (priv->kbd_bl.type =3D=3D KBD_BL_TRISTATE_AUTO) { + bool activate =3D hw_brightness =3D=3D KBD_BL_AUTO_MODE_HW_BRIGHTNESS; + + led_trigger_notify_hw_control_changed(&priv->kbd_bl.led, activate, + &ideapad_kbd_bl_auto_trigger); + } + + brightness =3D ideapad_kbd_bl_brightness_parse(priv, hw_brightness); if (brightness < 0) return; =20 @@ -1738,7 +1783,7 @@ static void ideapad_kbd_bl_notify(struct ideapad_priv= ate *priv) =20 static int ideapad_kbd_bl_init(struct ideapad_private *priv) { - int brightness, err; + int hw_brightness, brightness, err; =20 if (!priv->features.kbd_bl) return -ENODEV; @@ -1746,12 +1791,37 @@ static int ideapad_kbd_bl_init(struct ideapad_priva= te *priv) if (WARN_ON(priv->kbd_bl.initialized)) return -EEXIST; =20 - if (ideapad_kbd_bl_check_tristate(priv->kbd_bl.type)) + hw_brightness =3D ideapad_kbd_bl_hw_brightness_get(priv); + if (hw_brightness < 0) + return hw_brightness; + + switch (priv->kbd_bl.type) { + case KBD_BL_TRISTATE_AUTO: + err =3D devm_led_trigger_register(&priv->platform_device->dev, + &ideapad_kbd_bl_auto_trigger); + if (err) + return err; + + priv->kbd_bl.led.trigger_type =3D &ideapad_kbd_bl_auto_trigger_typ= e; + priv->kbd_bl.led.hw_control_trigger =3D ideapad_kbd_bl_auto_trigger.name; + + /* HW remembers the last brightness level, including auto mode. */ + if (hw_brightness =3D=3D KBD_BL_AUTO_MODE_HW_BRIGHTNESS) + priv->kbd_bl.led.default_trigger =3D ideapad_kbd_bl_auto_trigger.name; + + fallthrough; + case KBD_BL_TRISTATE: priv->kbd_bl.led.max_brightness =3D 2; - else + break; + case KBD_BL_STANDARD: priv->kbd_bl.led.max_brightness =3D 1; + break; + default: + /* This has already been validated by ideapad_check_features(). */ + unreachable(); + } =20 - brightness =3D ideapad_kbd_bl_brightness_get(priv); + brightness =3D ideapad_kbd_bl_brightness_parse(priv, hw_brightness); if (brightness < 0) return brightness; =20 --=20 2.51.0