blob: 13415b5c51c2becc1d3e8384707f8a6fc5c25e82 [file] [log] [blame]
/* Copyright (c) 2013 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.
*/
/* PWM control module for Chromebook keyboard backlight. */
#include "common.h"
#include "console.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "lid_switch.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 */
static int command_kblight(int argc, char **argv)
{
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));
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)
{
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);
}
}
DECLARE_HOOK(HOOK_INIT, pwm_kblight_init, HOOK_PRIO_DEFAULT);
static void pwm_kblight_preserve_state(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);
}
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_kblight_suspend, HOOK_PRIO_DEFAULT);
static void pwm_kblight_shutdown(void)
{
pwm_set_duty(PWM_CH_KBLIGHT, 0);
}
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);