diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2018-04-20 14:29:13 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-04-27 21:27:29 -0700 |
commit | 3fbf2c47ae847112044c529bb54655841e53014a (patch) | |
tree | c362366276e9163595952460b59de2512d1ca0ca | |
parent | 102ad072922da1c510446fb3bb4d14c5eb815cec (diff) | |
download | chrome-ec-3fbf2c47ae847112044c529bb54655841e53014a.tar.gz |
Nami: Add keyboard backlight control
This implements keyboard backlight control for Nami, Vayne, Pantheon,
and Sona. On Sona, GPIOC4 is directly connected to the LED strings.
Thus, we use PWM to control the brightness. On the other variants,
the LED strings are connected to LM3509. Thus, we control the brightness
through I2C.
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
BUG=b:76182445,b:78141647
BRANCH=none
TEST=Verify keyboard backlight brightness changes on Nami.
Verify keyboard backlight turns on/off on lid close/open, sleep/suspend.
on Nami. Verify 'kblight' returns x set by 'kblight x' on Sona.
Change-Id: I400ea2bc7a58a3cc57eb959179d2139a99ac176c
Reviewed-on: https://chromium-review.googlesource.com/1022833
Commit-Ready: Daisuke Nojiri <dnojiri@chromium.org>
Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Aaron Durbin <adurbin@google.com>
-rw-r--r-- | board/nami/board.c | 14 | ||||
-rw-r--r-- | board/nami/board.h | 1 | ||||
-rw-r--r-- | board/nami/build.mk | 1 | ||||
-rw-r--r-- | board/nami/gpio.inc | 1 | ||||
-rw-r--r-- | board/nami/keyboard_backlight.c | 130 | ||||
-rw-r--r-- | driver/led/lm3509.c | 82 | ||||
-rw-r--r-- | driver/led/lm3509.h | 28 |
7 files changed, 223 insertions, 34 deletions
diff --git a/board/nami/board.c b/board/nami/board.c index 5878515149..836e3f978f 100644 --- a/board/nami/board.c +++ b/board/nami/board.c @@ -497,6 +497,7 @@ const struct pwm_t pwm_channels[] = { [PWM_CH_LED1] = { 3, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_LED2] = { 5, PWM_CONFIG_DSLEEP, 100 }, [PWM_CH_FAN] = {4, PWM_CONFIG_OPEN_DRAIN, 25000}, + [PWM_CH_KBLIGHT] = { 2, 0, 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); @@ -650,8 +651,6 @@ void lid_angle_peripheral_enable(int enable) static void board_chipset_resume(void) { gpio_set_level(GPIO_ENABLE_BACKLIGHT_L, 0); - if (lid_is_open()) - lm3509_poweron(); } DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); @@ -659,20 +658,9 @@ DECLARE_HOOK(HOOK_CHIPSET_RESUME, board_chipset_resume, HOOK_PRIO_DEFAULT); static void board_chipset_suspend(void) { gpio_set_level(GPIO_ENABLE_BACKLIGHT_L, 1); - lm3509_poweroff(); } DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, board_chipset_suspend, HOOK_PRIO_DEFAULT); -/* Control keyboard backlight when Lid status change */ -static void lm3509_kblight_lid_change(void) -{ - if (lid_is_open()) - lm3509_poweron(); - else - lm3509_poweroff(); -} -DECLARE_HOOK(HOOK_LID_CHANGE, lm3509_kblight_lid_change, HOOK_PRIO_DEFAULT); - static void board_set_motion_sensor_count(void) { /* There are two possible sensor configurations. diff --git a/board/nami/board.h b/board/nami/board.h index c1ccc4350f..e7ed9e3a44 100644 --- a/board/nami/board.h +++ b/board/nami/board.h @@ -241,6 +241,7 @@ enum pwm_channel { PWM_CH_LED1, PWM_CH_LED2, PWM_CH_FAN, + PWM_CH_KBLIGHT, /* Number of PWM channels */ PWM_CH_COUNT, }; diff --git a/board/nami/build.mk b/board/nami/build.mk index f4bf21113d..3d83e52bfe 100644 --- a/board/nami/build.mk +++ b/board/nami/build.mk @@ -13,3 +13,4 @@ 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/gpio.inc b/board/nami/gpio.inc index ce69db4da9..c12db6dceb 100644 --- a/board/nami/gpio.inc +++ b/board/nami/gpio.inc @@ -109,6 +109,7 @@ ALTERNATE(PIN_MASK(B, 0x40), 1, MODULE_PWM, 0) /* GPIOB6 PWM1 Fan control */ ALTERNATE(PIN_MASK(8, 0x01), 1, MODULE_PWM, 0) /* GPIO80 PWM3 LED White */ ALTERNATE(PIN_MASK(B, 0x80), 1, MODULE_PWM, 0) /* GPIOB7 PWM5 LED Yellow */ ALTERNATE(PIN_MASK(A, 0x40), 1, MODULE_PWM, 0) /* GPIOA6 TA2 */ +ALTERNATE(PIN_MASK(C, 0x10), 1, MODULE_PWM, 0) /* GPIOC4 PWM2 */ /* Keyboard pins */ #define GPIO_KB_INPUT (GPIO_INPUT | GPIO_PULL_UP) diff --git a/board/nami/keyboard_backlight.c b/board/nami/keyboard_backlight.c new file mode 100644 index 0000000000..29f74a8131 --- /dev/null +++ b/board/nami/keyboard_backlight.c @@ -0,0 +1,130 @@ +/* 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 "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 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/driver/led/lm3509.c b/driver/led/lm3509.c index 463627a210..58838e2bbe 100644 --- a/driver/led/lm3509.c +++ b/driver/led/lm3509.c @@ -5,6 +5,7 @@ * TI LM3509 LED driver. */ +#include "compile_time_macros.h" #include "i2c.h" #include "lm3509.h" @@ -13,31 +14,78 @@ inline int lm3509_write(uint8_t reg, uint8_t val) return i2c_write8(I2C_PORT_KBLIGHT, LM3509_I2C_ADDR, reg, val); } -int lm3509_poweron(void) +inline int lm3509_read(uint8_t reg, int *val) { - int ret = 0; + return i2c_read8(I2C_PORT_KBLIGHT, LM3509_I2C_ADDR, reg, val); +} - /* BIT= description - * [2]= set both main and seconfary current same, both control by BMAIN. - * [1]= enable secondary current sink. - * [0]= enable main current sink. - */ - ret |= lm3509_write(LM3509_REG_GP, 0x07); - /* Brigntness register - * 0x00= 0% - * 0x1F= 100% - */ - ret |= lm3509_write(LM3509_REG_BMAIN, 0x1F); +/* Brightness level (0.0 to 100.0%) to brightness register conversion table */ +static const uint16_t lm3509_brightness[32] = { + 0, 1, 6, 10, 11, 13, 16, 20, + 24, 28, 31, 37, 43, 52, 62, 75, + 87, 100, 125, 150, 168, 187, 225, 262, + 312, 375, 437, 525, 612, 700, 875, 1000 +}; - return ret; +static int brightness_to_bmain(int percent) +{ + int i; + int b = percent * 10; + + for (i = 1; i < sizeof(lm3509_brightness); i++) { + int low = lm3509_brightness[i - 1]; + int high = lm3509_brightness[i]; + if (high < b) + continue; + /* rounding to the nearest */ + return (b - low < high - b) ? i - 1 : i; + } + /* Brightness is out of range. Return the highest value. */ + return i - 1; } -int lm3509_poweroff(void) +int lm3509_power(int enable) { int ret = 0; + uint8_t gp = 0, bmain = 0; + + if (enable) { + /* + * [2]= set both main and secondary current same + * both control by BMAIN. + * [1]= enable secondary current sink. + * [0]= enable main current sink. + */ + gp = 0x07; + /* + * Brightness register + * 0x00= 0% + * 0x1F= 100% + */ + bmain = ARRAY_SIZE(lm3509_brightness) - 1; + } - ret |= lm3509_write(LM3509_REG_GP, 0x00); - ret |= lm3509_write(LM3509_REG_BMAIN, 0x00); + ret |= lm3509_write(LM3509_REG_GP, gp); + ret |= lm3509_write(LM3509_REG_BMAIN, bmain); return ret; } + +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. + */ + return lm3509_write(LM3509_REG_BMAIN, brightness_to_bmain(percent)); +} + +int lm3509_get_brightness(int *percent) +{ + int rv, val; + rv = lm3509_read(LM3509_REG_BMAIN, &val); + if (rv) + return rv; + val &= LM3509_BMAIN_MASK; + *percent = lm3509_brightness[val] / 10; + return EC_SUCCESS; +} diff --git a/driver/led/lm3509.h b/driver/led/lm3509.h index ca8c67edbf..12ca480562 100644 --- a/driver/led/lm3509.h +++ b/driver/led/lm3509.h @@ -15,10 +15,30 @@ #define LM3509_REG_BMAIN 0xA0 #define LM3509_REG_BSUB 0xB0 -/* Power on and initialize LM3509. */ -int lm3509_poweron(void); +#define LM3509_BMAIN_MASK 0x1F -/* Power off LM3509. */ -int lm3509_poweroff(void); +/** + * 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); #endif /* __CROS_EC_LM3509_H */ |