summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2018-05-08 14:45:55 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-11 12:10:44 -0700
commit94b4c511a6a5f185bce14d30731f165c4c48d752 (patch)
tree1b26f85d80991d24cf22eb5e123796dd3d48c3cf
parentf21a0681c78e67ccc11f350dc3a455360fc765fb (diff)
downloadchrome-ec-94b4c511a6a5f185bce14d30731f165c4c48d752.tar.gz
kblight: Add keyboard backlight control module
This patch promotes board/nami/keyboard_backlight.c to common directory. Board customization is done via board_kblight_init callback. It currently supports two drivers: direct PWM control and lm3509. Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> BUG=b:78360907,b:78141647 BRANCH=none TEST=On Nami (for lm3509) and Sona (pwm), verify the followings: 1. Alt + brightness up/down works 2. After suspend-resume, brightness is restored 3. Lid close/open 4. After screen is off, keyboard backlight is turned off Change-Id: I584c06e8702fe7b289999698f277311cfd3400bd Reviewed-on: https://chromium-review.googlesource.com/1051027 Commit-Ready: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r--board/nami/board.c18
-rw-r--r--board/nami/board.h1
-rw-r--r--board/nami/build.mk1
-rw-r--r--board/nami/keyboard_backlight.c157
-rw-r--r--common/acpi.c5
-rw-r--r--common/build.mk1
-rw-r--r--common/keyboard_backlight.c149
-rw-r--r--common/pwm_kblight.c121
-rw-r--r--driver/led/lm3509.c22
-rw-r--r--driver/led/lm3509.h24
-rw-r--r--include/config.h7
-rw-r--r--include/keyboard_backlight.h79
12 files changed, 296 insertions, 289 deletions
diff --git a/board/nami/board.c b/board/nami/board.c
index af3a4d36f3..9cc93f913b 100644
--- a/board/nami/board.c
+++ b/board/nami/board.c
@@ -32,6 +32,7 @@
#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
+#include "keyboard_backlight.h"
#include "keyboard_scan.h"
#include "lid_switch.h"
#include "math_util.h"
@@ -741,3 +742,20 @@ int board_is_lid_angle_tablet_mode(void)
/* Boards with no GMR sensor use lid angles to detect tablet mode. */
return oem == PROJECT_NAMI || oem == PROJECT_VAYNE;
}
+
+void board_kblight_init(void)
+{
+ switch (oem) {
+ default:
+ case PROJECT_NAMI:
+ case PROJECT_VAYNE:
+ case PROJECT_PANTHEON:
+ kblight_register(&kblight_lm3509);
+ break;
+ case PROJECT_SONA:
+ if (sku == 0x3AE2)
+ break;
+ kblight_register(&kblight_pwm);
+ break;
+ }
+}
diff --git a/board/nami/board.h b/board/nami/board.h
index a292e32372..2f329e5e42 100644
--- a/board/nami/board.h
+++ b/board/nami/board.h
@@ -53,6 +53,7 @@
#define WIRELESS_GPIO_WLAN_POWER GPIO_PP3300_DX_WLAN
#undef CONFIG_SUPPORT_CHIP_HIBERNATION
#define CONFIG_FANS 1
+#define CONFIG_PWM_KBLIGHT
/* EC console commands */
#define CONFIG_CMD_ACCELS
diff --git a/board/nami/build.mk b/board/nami/build.mk
index 3d83e52bfe..f4bf21113d 100644
--- a/board/nami/build.mk
+++ b/board/nami/build.mk
@@ -13,4 +13,3 @@ board-y=board.o
board-$(CONFIG_BATTERY_SMART)+=battery.o
board-$(CONFIG_LED_COMMON)+=led.o
board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o
-board-y+=keyboard_backlight.o
diff --git a/board/nami/keyboard_backlight.c b/board/nami/keyboard_backlight.c
deleted file mode 100644
index a225f96569..0000000000
--- a/board/nami/keyboard_backlight.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Copyright 2018 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Keyboard backlight control
- */
-
-#include "console.h"
-#include "cros_board_info.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "lid_switch.h"
-#include "lm3509.h"
-#include "pwm.h"
-#include "util.h"
-
-static void (*kblight_set)(int percent);
-static int (*kblight_get)(void);
-static void (*kblight_power)(int enable);
-
-/*
- * PWM routines
- */
-static void kblight_pwm_set(int percent)
-{
- pwm_set_duty(PWM_CH_KBLIGHT, percent);
-}
-
-static int kblight_pwm_get(void)
-{
- return pwm_get_duty(PWM_CH_KBLIGHT);
-}
-
-static void kblight_pwm_power(int enable)
-{
- pwm_enable(PWM_CH_KBLIGHT, enable);
-}
-
-/*
- * I2C routines
- */
-static void kblight_i2c_set(int percent)
-{
- lm3509_set_brightness(percent);
-}
-
-static int kblight_i2c_get(void)
-{
- int percent;
- if (lm3509_get_brightness(&percent))
- percent = 0;
- return percent;
-}
-
-static void kblight_i2c_power(int enable)
-{
- lm3509_power(enable);
-}
-
-static void kblight_init(void)
-{
- uint32_t oem = PROJECT_NAMI;
- uint32_t sku = 0;
-
- cbi_get_oem_id(&oem);
- cbi_get_sku_id(&sku);
-
- switch (oem) {
- default:
- case PROJECT_NAMI:
- case PROJECT_VAYNE:
- case PROJECT_PANTHEON:
- kblight_set = kblight_i2c_set;
- kblight_get = kblight_i2c_get;
- kblight_power = kblight_i2c_power;
- break;
- case PROJECT_SONA:
- if (sku == 0x3AE2)
- break;
- kblight_set = kblight_pwm_set;
- kblight_get = kblight_pwm_get;
- kblight_power = kblight_pwm_power;
- break;
- }
-}
-DECLARE_HOOK(HOOK_INIT, kblight_init, HOOK_PRIO_DEFAULT);
-
-static void kblight_suspend(void)
-{
- if (kblight_power)
- kblight_power(0);
-}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kblight_suspend, HOOK_PRIO_DEFAULT);
-
-static void kblight_resume(void)
-{
- if (kblight_power)
- kblight_power(lid_is_open());
-}
-DECLARE_HOOK(HOOK_CHIPSET_RESUME, kblight_resume, HOOK_PRIO_DEFAULT);
-
-static void kblight_lid_change(void)
-{
- if (kblight_power)
- kblight_power(lid_is_open());
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, kblight_lid_change, HOOK_PRIO_DEFAULT);
-
-static int hc_set_kblight(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_set_keyboard_backlight *p = args->params;
- /* Assume already enabled */
- if (!kblight_set)
- return EC_RES_UNAVAILABLE;
- kblight_set(p->percent);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT,
- hc_set_kblight, EC_VER_MASK(0));
-
-static int hc_get_kblight(struct host_cmd_handler_args *args)
-{
- struct ec_response_pwm_get_keyboard_backlight *r = args->response;
- if (!kblight_get)
- return EC_RES_UNAVAILABLE;
- r->percent = kblight_get();
- /* Assume always enabled */
- r->enabled = 1;
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT,
- hc_get_kblight, EC_VER_MASK(0));
-
-static int cc_kblight(int argc, char **argv)
-{
- int i;
- char *e;
-
- if (argc < 2) {
- if (!kblight_get)
- return EC_ERROR_UNIMPLEMENTED;
- ccprintf("%d\n", kblight_get());
- return EC_SUCCESS;
- }
-
- if (!kblight_set)
- return EC_ERROR_UNIMPLEMENTED;
- i = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
- kblight_set(i);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(kblight, cc_kblight,
- "kblight [percent]",
- "Get/set keyboard backlight brightness");
diff --git a/common/acpi.c b/common/acpi.c
index e21eb93b97..7ef3d81412 100644
--- a/common/acpi.c
+++ b/common/acpi.c
@@ -10,6 +10,7 @@
#include "dptf.h"
#include "hooks.h"
#include "host_command.h"
+#include "keyboard_backlight.h"
#include "lpc.h"
#include "ec_commands.h"
#include "tablet_mode.h"
@@ -147,7 +148,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
break;
#ifdef CONFIG_PWM_KBLIGHT
case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
- result = pwm_get_duty(PWM_CH_KBLIGHT);
+ result = kblight_get();
break;
#endif
#ifdef CONFIG_FANS
@@ -231,7 +232,7 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
* debug console.
*/
CPRINTF("\r[%T ACPI kblight %d]", data);
- pwm_set_duty(PWM_CH_KBLIGHT, data);
+ kblight_set(data);
break;
#endif
#ifdef CONFIG_FANS
diff --git a/common/build.mk b/common/build.mk
index 1dd7801455..1a0f27e5bf 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -87,6 +87,7 @@ common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o
common-$(CONFIG_PSTORE)+=pstore_commands.o
common-$(CONFIG_PWM)+=pwm.o
common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o
+common-$(CONFIG_PWM_KBLIGHT)+=keyboard_backlight.o
common-$(CONFIG_RMA_AUTH)+=rma_auth.o
common-$(CONFIG_RSA)+=rsa.o
common-$(CONFIG_ROLLBACK)+=rollback.o
diff --git a/common/keyboard_backlight.c b/common/keyboard_backlight.c
new file mode 100644
index 0000000000..d17c2bd319
--- /dev/null
+++ b/common/keyboard_backlight.c
@@ -0,0 +1,149 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "console.h"
+#include "ec_commands.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "keyboard_backlight.h"
+#include "lid_switch.h"
+#include "timer.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_KEYBOARD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_KEYBOARD, format, ## args)
+
+static struct kblight_conf kblight;
+static int current_percent;
+
+void __attribute__((weak)) board_kblight_init(void)
+{ }
+
+static int kblight_init(void)
+{
+ if (!kblight.drv || !kblight.drv->init)
+ return EC_ERROR_UNIMPLEMENTED;
+ return kblight.drv->init();
+}
+
+static void kblight_set_deferred(void)
+{
+ if (!kblight.drv || !kblight.drv->set)
+ return;
+ kblight.drv->set(current_percent);
+}
+DECLARE_DEFERRED(kblight_set_deferred);
+
+/*
+ * APIs
+ */
+int kblight_set(int percent)
+{
+ if (current_percent < 0 || 100 < current_percent)
+ return EC_ERROR_INVAL;
+ current_percent = percent;
+ /* Need to defer i2c in case it's called from an interrupt handler. */
+ hook_call_deferred(&kblight_set_deferred_data, 0);
+ return EC_SUCCESS;
+}
+
+int kblight_get(void)
+{
+ return current_percent;
+}
+
+int kblight_enable(int enable)
+{
+ if (!kblight.drv || !kblight.drv->enable)
+ return -1;
+ return kblight.drv->enable(enable);
+}
+
+int kblight_register(const struct kblight_drv *drv)
+{
+ kblight.drv = drv;
+ CPRINTS("kblight registered");
+ return EC_SUCCESS;
+}
+
+/*
+ * Hooks
+ */
+static void keyboard_backlight_init(void)
+{
+ /* Uses PWM by default. Can be customized by board_kblight_init */
+ kblight_register(&kblight_pwm);
+ board_kblight_init();
+ if (kblight_init())
+ CPRINTS("kblight init failed");
+}
+DECLARE_HOOK(HOOK_INIT, keyboard_backlight_init, HOOK_PRIO_DEFAULT);
+
+static void kblight_suspend(void)
+{
+ kblight_enable(0);
+}
+DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, kblight_suspend, HOOK_PRIO_DEFAULT);
+
+static void kblight_resume(void)
+{
+ if (lid_is_open()) {
+ kblight_enable(1);
+ kblight_set(current_percent);
+ }
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, kblight_resume, HOOK_PRIO_DEFAULT);
+
+static void kblight_lid_change(void)
+{
+ kblight_enable(lid_is_open());
+}
+DECLARE_HOOK(HOOK_LID_CHANGE, kblight_lid_change, HOOK_PRIO_DEFAULT);
+
+/*
+ * Console and host commands
+ */
+static int cc_kblight(int argc, char **argv)
+{
+ if (argc >= 2) {
+ char *e;
+ int i = strtoi(argv[1], &e, 0);
+ if (*e)
+ return EC_ERROR_PARAM1;
+ if (kblight_set(i))
+ return EC_ERROR_PARAM1;
+ }
+ ccprintf("Keyboard backlight: %d%%\n", kblight_get());
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(kblight, cc_kblight,
+ "percent",
+ "Get/set keyboard backlight");
+
+int hc_get_keyboard_backlight(struct host_cmd_handler_args *args)
+{
+ struct ec_response_pwm_get_keyboard_backlight *r = args->response;
+
+ r->percent = kblight_get();
+ r->enabled = 1; /* Deprecated */
+ args->response_size = sizeof(*r);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT,
+ hc_get_keyboard_backlight,
+ EC_VER_MASK(0));
+
+int hc_set_keyboard_backlight(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_pwm_set_keyboard_backlight *p = args->params;
+
+ if (kblight_set(p->percent))
+ return EC_RES_ERROR;
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT,
+ hc_set_keyboard_backlight,
+ EC_VER_MASK(0));
diff --git a/common/pwm_kblight.c b/common/pwm_kblight.c
index 13415b5c51..1db5b9e5bd 100644
--- a/common/pwm_kblight.c
+++ b/common/pwm_kblight.c
@@ -3,123 +3,44 @@
* found in the LICENSE file.
*/
-/* PWM control module for Chromebook keyboard backlight. */
+/* PWM control module for keyboard backlight. */
#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "lid_switch.h"
+#include "keyboard_backlight.h"
#include "pwm.h"
#include "system.h"
#include "util.h"
-#define PWMKBD_SYSJUMP_TAG 0x504b /* "PK" */
-#define PWM_HOOK_VERSION 1
-/* Saved PWM state across sysjumps */
-struct pwm_kbd_state {
- uint8_t kblight_en;
- uint8_t kblight_percent;
-};
-
-/*****************************************************************************/
-/* Console commands */
+const enum pwm_channel kblight_pwm_ch = PWM_CH_KBLIGHT;
-static int command_kblight(int argc, char **argv)
+static int kblight_pwm_set(int percent)
{
- if (argc >= 2) {
- char *e;
- int i = strtoi(argv[1], &e, 0);
- if (*e)
- return EC_ERROR_PARAM1;
- pwm_set_duty(PWM_CH_KBLIGHT, i);
- }
-
- ccprintf("Keyboard backlight: %d%%\n", pwm_get_duty(PWM_CH_KBLIGHT));
+ pwm_set_duty(kblight_pwm_ch, percent);
return EC_SUCCESS;
}
-DECLARE_CONSOLE_COMMAND(kblight, command_kblight,
- "percent",
- "Set keyboard backlight");
-
-/*****************************************************************************/
-/* Host commands */
-
-int pwm_command_get_keyboard_backlight(struct host_cmd_handler_args *args)
-{
- struct ec_response_pwm_get_keyboard_backlight *r = args->response;
-
- r->percent = pwm_get_duty(PWM_CH_KBLIGHT);
- r->enabled = pwm_get_enabled(PWM_CH_KBLIGHT);
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT,
- pwm_command_get_keyboard_backlight,
- EC_VER_MASK(0));
-
-int pwm_command_set_keyboard_backlight(struct host_cmd_handler_args *args)
-{
- const struct ec_params_pwm_set_keyboard_backlight *p = args->params;
-
- pwm_set_duty(PWM_CH_KBLIGHT, p->percent);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT,
- pwm_command_set_keyboard_backlight,
- EC_VER_MASK(0));
-
-/*****************************************************************************/
-/* Hooks */
-static void pwm_kblight_init(void)
+static int kblight_pwm_get(void)
{
- const struct pwm_kbd_state *prev;
- int version, size;
-
- prev = (const struct pwm_kbd_state *)
- system_get_jump_tag(PWMKBD_SYSJUMP_TAG, &version, &size);
- if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) {
- /* Restore previous state. */
- pwm_enable(PWM_CH_KBLIGHT, prev->kblight_en);
- pwm_set_duty(PWM_CH_KBLIGHT, prev->kblight_percent);
- } else {
- /* Enable keyboard backlight control, turned down */
- pwm_set_duty(PWM_CH_KBLIGHT, 0);
- pwm_enable(PWM_CH_KBLIGHT, 1);
- }
+ return pwm_get_duty(kblight_pwm_ch);
}
-DECLARE_HOOK(HOOK_INIT, pwm_kblight_init, HOOK_PRIO_DEFAULT);
-static void pwm_kblight_preserve_state(void)
+static int kblight_pwm_init(void)
{
- struct pwm_kbd_state state;
-
- state.kblight_en = pwm_get_enabled(PWM_CH_KBLIGHT);
- state.kblight_percent = pwm_get_duty(PWM_CH_KBLIGHT);
-
- system_add_jump_tag(PWMKBD_SYSJUMP_TAG, PWM_HOOK_VERSION,
- sizeof(state), &state);
-}
-DECLARE_HOOK(HOOK_SYSJUMP, pwm_kblight_preserve_state, HOOK_PRIO_DEFAULT);
-
-static void pwm_kblight_suspend(void)
-{
- pwm_set_duty(PWM_CH_KBLIGHT, 0);
+ /* dnojiri: Why do we need save/restore setting over sysjump? */
+ kblight_pwm_set(0);
+ pwm_enable(kblight_pwm_ch, 1);
+ return EC_SUCCESS;
}
-DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_kblight_suspend, HOOK_PRIO_DEFAULT);
-static void pwm_kblight_shutdown(void)
+static int kblight_pwm_enable(int enable)
{
- pwm_set_duty(PWM_CH_KBLIGHT, 0);
+ pwm_enable(kblight_pwm_ch, enable);
+ return EC_SUCCESS;
}
-DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pwm_kblight_shutdown, HOOK_PRIO_DEFAULT);
-static void pwm_kblight_lid_change(void)
-{
- pwm_enable(PWM_CH_KBLIGHT, lid_is_open());
-}
-DECLARE_HOOK(HOOK_LID_CHANGE, pwm_kblight_lid_change, HOOK_PRIO_DEFAULT);
+const struct kblight_drv kblight_pwm = {
+ .init = kblight_pwm_init,
+ .set = kblight_pwm_set,
+ .get = kblight_pwm_get,
+ .enable = kblight_pwm_enable,
+};
diff --git a/driver/led/lm3509.c b/driver/led/lm3509.c
index 58838e2bbe..4f5a911da4 100644
--- a/driver/led/lm3509.c
+++ b/driver/led/lm3509.c
@@ -7,6 +7,7 @@
#include "compile_time_macros.h"
#include "i2c.h"
+#include "keyboard_backlight.h"
#include "lm3509.h"
inline int lm3509_write(uint8_t reg, uint8_t val)
@@ -44,7 +45,7 @@ static int brightness_to_bmain(int percent)
return i - 1;
}
-int lm3509_power(int enable)
+static int lm3509_power(int enable)
{
int ret = 0;
uint8_t gp = 0, bmain = 0;
@@ -71,7 +72,7 @@ int lm3509_power(int enable)
return ret;
}
-int lm3509_set_brightness(int percent)
+static int lm3509_set_brightness(int percent)
{
/* We don't need to read/mask/write BMAIN because bit6 and 7 are non
* functional read only bits.
@@ -79,13 +80,24 @@ int lm3509_set_brightness(int percent)
return lm3509_write(LM3509_REG_BMAIN, brightness_to_bmain(percent));
}
-int lm3509_get_brightness(int *percent)
+static int lm3509_get_brightness(void)
{
int rv, val;
rv = lm3509_read(LM3509_REG_BMAIN, &val);
if (rv)
- return rv;
+ return -1;
val &= LM3509_BMAIN_MASK;
- *percent = lm3509_brightness[val] / 10;
+ return lm3509_brightness[val] / 10;
+}
+
+static int lm3509_init(void)
+{
return EC_SUCCESS;
}
+
+const struct kblight_drv kblight_lm3509 = {
+ .init = lm3509_init,
+ .set = lm3509_set_brightness,
+ .get = lm3509_get_brightness,
+ .enable = lm3509_power,
+};
diff --git a/driver/led/lm3509.h b/driver/led/lm3509.h
index 12ca480562..f1fbd6b3d4 100644
--- a/driver/led/lm3509.h
+++ b/driver/led/lm3509.h
@@ -17,28 +17,6 @@
#define LM3509_BMAIN_MASK 0x1F
-/**
- * Power on/off and initialize LM3509.
- *
- * @param enable: 1 to enable or 0 to disable.
- * @return EC_SUCCESS or EC_ERROR_* on error.
- */
-int lm3509_power(int enable);
-
-/**
- * Set brightness level
- *
- * @param percent: Brightness level: 0 - 100%
- * @return EC_SUCCESS or EC_ERROR_* on error.
- */
-int lm3509_set_brightness(int percent);
-
-/**
- * Get current brightness level
- *
- * @param percent: Current brightness level.
- * @return EC_SUCCESS or EC_ERROR_* on error.
- */
-int lm3509_get_brightness(int *percent);
+extern const struct kblight_drv kblight_lm3509;
#endif /* __CROS_EC_LM3509_H */
diff --git a/include/config.h b/include/config.h
index 6abf748912..2a7a3128cc 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2268,7 +2268,12 @@
/* Support PWM output to display backlight */
#undef CONFIG_PWM_DISPLIGHT
-/* Support PWM output to keyboard backlight */
+/*
+ * Support PWM output to keyboard backlight
+ *
+ * Optionally, lm3509 can be used as a keyboard backlight controller.
+ * TODO: Create CONFIG_KEYBOARD_BACKLIGHT to allow lm3509 is used without PWM.
+ */
#undef CONFIG_PWM_KBLIGHT
/* Base address of RAM for the chip */
diff --git a/include/keyboard_backlight.h b/include/keyboard_backlight.h
new file mode 100644
index 0000000000..2389b3dfe0
--- /dev/null
+++ b/include/keyboard_backlight.h
@@ -0,0 +1,79 @@
+/* Copyright 2018 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_KEYBOARD_BACKLIGHT_H
+#define __CROS_EC_KEYBOARD_BACKLIGHT_H
+
+struct kblight_conf {
+ const struct kblight_drv *drv;
+};
+
+struct kblight_drv {
+ /**
+ * Initialize the keyboard backlight controller
+ * @return EC_SUCCESS or EC_ERROR_*
+ */
+ int (*init)(void);
+
+ /**
+ * Set the brightness
+ * @param percent
+ * @return EC_SUCCESS or EC_ERROR_*
+ */
+ int (*set)(int percent);
+
+ /**
+ * Get the current brightness
+ * @return Brightness in percentage
+ */
+ int (*get)(void);
+
+ /**
+ * Enable or disable keyboard backlight
+ * @param enable: 1=Enable, 0=Disable.
+ * @return EC_SUCCESS or EC_ERROR_*
+ */
+ int (*enable)(int enable);
+};
+
+/**
+ * Initialize keyboard backlight per board
+ */
+void board_kblight_init(void);
+
+/**
+ * Set keyboard backlight brightness
+ *
+ * @param percent Brightness in percentage
+ * @return EC_SUCCESS or EC_ERROR_*
+ */
+int kblight_set(int percent);
+
+/**
+ * Get keyboard backlight brightness
+ *
+ * @return Brightness in percentage
+ */
+int kblight_get(void);
+
+/**
+ * Enable or disable keyboard backlight
+ *
+ * @param enable: 1=Enable, 0=Disable.
+ * @return EC_SUCCESS or EC_ERROR_*
+ */
+int kblight_enable(int enable);
+
+/**
+ * Register keyboard backlight controller
+ *
+ * @param drv: Driver of keyboard backlight controller
+ * @return EC_SUCCESS or EC_ERROR_*
+ */
+int kblight_register(const struct kblight_drv *drv);
+
+extern const struct kblight_drv kblight_pwm;
+
+#endif /* __CROS_EC_KEYBOARD_BACKLIGHT_H */