mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-15 00:56:22 +00:00
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>
This commit is contained in:
committed by
chrome-bot
parent
102ad07292
commit
3fbf2c47ae
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
130
board/nami/keyboard_backlight.c
Normal file
130
board/nami/keyboard_backlight.c
Normal file
@@ -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");
|
||||
@@ -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)
|
||||
{
|
||||
return i2c_read8(I2C_PORT_KBLIGHT, LM3509_I2C_ADDR, reg, val);
|
||||
}
|
||||
|
||||
/* 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
|
||||
};
|
||||
|
||||
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_power(int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t gp = 0, bmain = 0;
|
||||
|
||||
/* 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);
|
||||
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, gp);
|
||||
ret |= lm3509_write(LM3509_REG_BMAIN, bmain);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lm3509_poweroff(void)
|
||||
int lm3509_set_brightness(int percent)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret |= lm3509_write(LM3509_REG_GP, 0x00);
|
||||
ret |= lm3509_write(LM3509_REG_BMAIN, 0x00);
|
||||
|
||||
return ret;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user