diff options
-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 */ |