diff options
-rw-r--r-- | board/cyan/board.c | 49 | ||||
-rw-r--r-- | board/cyan/board.h | 1 | ||||
-rw-r--r-- | common/build.mk | 2 | ||||
-rw-r--r-- | common/lid_angle.c | 161 | ||||
-rw-r--r-- | common/motion_lid.c | 10 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/lid_angle.h | 23 |
7 files changed, 134 insertions, 118 deletions
diff --git a/board/cyan/board.c b/board/cyan/board.c index 0f23707016..568c32e765 100644 --- a/board/cyan/board.c +++ b/board/cyan/board.c @@ -14,6 +14,7 @@ #include "hooks.h" #include "host_command.h" #include "i2c.h" +#include "keyboard_scan.h" #include "lid_switch.h" #include "math_util.h" #include "motion_lid.h" @@ -116,7 +117,7 @@ const matrix_3x3_t lid_standard_ref = { struct motion_sensor_t motion_sensors[] = { {.name = "Base", - .active_mask = SENSOR_ACTIVE_S0, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_KXCJ9, .type = MOTIONSENSE_TYPE_ACCEL, .location = MOTIONSENSE_LOC_BASE, @@ -132,7 +133,7 @@ struct motion_sensor_t motion_sensors[] = { } }, {.name = "Lid", - .active_mask = SENSOR_ACTIVE_S0, + .active_mask = SENSOR_ACTIVE_S0_S3, .chip = MOTIONSENSE_CHIP_KXCJ9, .type = MOTIONSENSE_TYPE_ACCEL, .location = MOTIONSENSE_LOC_LID, @@ -166,24 +167,34 @@ const struct accel_orientation acc_orient = { .hinge_axis = {1, 0, 0}, }; -/* - * In S3, power rail for sensors (+V3p3S) goes down asynchronous to EC. We need - * to execute this routine first and set the sensor state to "Not Initialized". - * This prevents the motion_sense_suspend hook routine from communicating with - * the sensor. - */ -static void motion_sensors_pre_init(void) +#ifdef CONFIG_LID_ANGLE_UPDATE +static void track_pad_enable(int enable) { - struct motion_sensor_t *sensor; - int i; - - for (i = 0; i < motion_sensor_count; ++i) { - sensor = &motion_sensors[i]; - sensor->state = SENSOR_NOT_INITIALIZED; + if (enable) + gpio_set_level(GPIO_TP_INT_DISABLE, 0); + else + gpio_set_level(GPIO_TP_INT_DISABLE, 1); +} - sensor->runtime_config.odr = sensor->default_config.odr; - sensor->runtime_config.range = sensor->default_config.range; +void lid_angle_peripheral_enable(int enable) +{ + if (enable) { + keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + track_pad_enable(1); + } else { + /* + * Ensure chipset is off before disabling keyboard. When chipset + * is on, EC keeps keyboard enabled and the AP decides when to + * ignore keys based on its more accurate lid angle calculation. + * + * TODO(crosbug.com/p/43695): Remove this check once we have a + * host command that can inform EC when we are entering or + * exiting tablet mode in S0. Also, add this check back to the + * function lid_angle_update in lid_angle.c + */ + if (!chipset_in_state(CHIPSET_STATE_ON)) + keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + track_pad_enable(0); } } -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, motion_sensors_pre_init, - MOTION_SENSE_HOOK_PRIO - 1); +#endif diff --git a/board/cyan/board.h b/board/cyan/board.h index 404390e800..670859a0ff 100644 --- a/board/cyan/board.h +++ b/board/cyan/board.h @@ -64,6 +64,7 @@ #define CONFIG_LID_ANGLE_SENSOR_BASE 0 #define CONFIG_LID_ANGLE_SENSOR_LID 1 #define CONFIG_LID_ANGLE +#define CONFIG_LID_ANGLE_UPDATE /* Modules we want to exclude */ #undef CONFIG_EEPROM diff --git a/common/build.mk b/common/build.mk index 2fb599ea06..f1aa62556b 100644 --- a/common/build.mk +++ b/common/build.mk @@ -60,7 +60,7 @@ common-$(CONFIG_KEYBOARD_TEST)+=keyboard_test.o common-$(CONFIG_LED_COMMON)+=led_common.o common-$(CONFIG_LED_POLICY_STD)+=led_policy_std.o common-$(CONFIG_LID_ANGLE)+=motion_lid.o math_util.o -common-$(CONFIG_LID_ANGLE_KEY_SCAN)+=lid_angle.o +common-$(CONFIG_LID_ANGLE_UPDATE)+=lid_angle.o common-$(CONFIG_LID_SWITCH)+=lid_switch.o common-$(CONFIG_LPC)+=acpi.o port80.o common-$(CONFIG_MKBP_EVENT)+=mkbp_event.o diff --git a/common/lid_angle.c b/common/lid_angle.c index eb6f6c94b5..f6091f4349 100644 --- a/common/lid_angle.c +++ b/common/lid_angle.c @@ -12,6 +12,8 @@ #include "keyboard_scan.h" #include "lid_angle.h" #include "lid_switch.h" +#include "math_util.h" +#include "motion_lid.h" #include "motion_sense.h" /* Console output macros */ @@ -20,21 +22,22 @@ /* * Define the number of previous lid angle measurements to keep for determining - * whether to enable or disable key scanning. Note, that in order to change - * the state of key scanning, all stored measurements of the lid angle buffer - * must be in the specified range. + * whether to enable or disable peripherals that are only needed for laptop + * mode. These incude keyboard and trackpad. Note, that in order to change the + * enable/disable state of these peripherals, all stored measurements of the + * lid angle buffer must be in the specified range. */ -#define KEY_SCAN_LID_ANGLE_BUFFER_SIZE 4 +#define LID_ANGLE_BUFFER_SIZE 4 /* - * Define two variables to determine if keyboard scanning should be enabled - * or disabled in S3 based on the current lid angle. Note, the lid angle is - * bound to [0, 360]. Here are two angles, defined such that we segregate the - * lid angle space into two regions. The first region is the region in which - * we enable keyboard scanning in S3 and is when the lid angle CCW of the - * small_angle and CW of the large_angle. The second region is the region in - * which we disable keyboard scanning in S3 and is when the lid angle is CCW - * of the large_angle and CW of the small_angle. + * Define two variables to determine if wake source peripherals that are only + * applicable for laptop mode should be enabled or disabled in S3 based on the + * current lid angle. Note, the lid angle is bound to [0, 360]. Here are two + * angles, defined such that we segregate the lid angle space into two regions. + * The first region is the region in which we enable peripherals in S3 and is + * when the lid angle CCW of the small_angle and CW of the large_angle. The + * second region is the region in which we disable peripherals in S3 and is when + * the lid angle is CCW of the large_angle and CW of the small_angle. * * Note, the most sensical values are small_angle = 0 and large_angle = 180, * but, the angle measurement is not perfect, and we know that if the angle is @@ -42,128 +45,122 @@ * small_angle is set to a small positive value to make sure we don't swap modes * when the lid is open all the way but is measuring a small positive value. */ -static int kb_wake_large_angle = 180; -static const int kb_wake_small_angle = 13; +static int wake_large_angle = 180; +static const int wake_small_angle = 13; -/* Define hysteresis value to add stability to the keyboard scanning flag. */ -#define KB_DIS_HYSTERESIS_DEG 2 +/* Define hysteresis value to add stability to the flags. */ +#define LID_ANGLE_HYSTERESIS_DEG 2 -/* Define max and min values for kb_wake_large_angle. */ -#define KB_DIS_MIN_LARGE_ANGLE 0 -#define KB_DIS_MAX_LARGE_ANGLE 360 +/* Define max and min values for wake_large_angle. */ +#define LID_ANGLE_MIN_LARGE_ANGLE 0 +#define LID_ANGLE_MAX_LARGE_ANGLE 360 /** - * Determine if given angle is in region to accept keyboard presses. + * Determine if given angle is in region to enable peripherals. * * @param ang Some lid angle in degrees [0, 360] * * @return true/false */ -static int lid_in_range_to_accept_keys(int ang) +static int lid_in_range_to_enable_peripherals(int ang) { /* - * If the keyboard wake large angle is min or max, then this - * function should return false or true respectively, independent of - * input angle. + * If the wake large angle is min or max, then this function should + * return false or true respectively, independent of input angle. */ - if (kb_wake_large_angle == KB_DIS_MIN_LARGE_ANGLE) + if (wake_large_angle == LID_ANGLE_MIN_LARGE_ANGLE) return 0; - else if (kb_wake_large_angle == KB_DIS_MAX_LARGE_ANGLE) + else if (wake_large_angle == LID_ANGLE_MAX_LARGE_ANGLE) return 1; - return (ang >= (kb_wake_small_angle + KB_DIS_HYSTERESIS_DEG)) && - (ang <= (kb_wake_large_angle - KB_DIS_HYSTERESIS_DEG)); + return (ang >= (wake_small_angle + LID_ANGLE_HYSTERESIS_DEG)) && + (ang <= (wake_large_angle - LID_ANGLE_HYSTERESIS_DEG)); } /** - * Determine if given angle is in region to ignore keyboard presses. + * Determine if given angle is in region to ignore peripherals. * * @param ang Some lid angle in degrees [0, 360] * * @return true/false */ -static int lid_in_range_to_ignore_keys(int ang) +static int lid_in_range_to_ignore_peripherals(int ang) { /* - * If the keyboard wake large angle is min or max, then this - * function should return true or false respectively, independent of - * input angle. + * If the wake large angle is min or max, then this function should + * return true or false respectively, independent of input angle. */ - if (kb_wake_large_angle == KB_DIS_MIN_LARGE_ANGLE) + if (wake_large_angle == LID_ANGLE_MIN_LARGE_ANGLE) return 1; - else if (kb_wake_large_angle == KB_DIS_MAX_LARGE_ANGLE) + else if (wake_large_angle == LID_ANGLE_MAX_LARGE_ANGLE) return 0; - return (ang <= (kb_wake_small_angle - KB_DIS_HYSTERESIS_DEG)) || - (ang >= (kb_wake_large_angle + KB_DIS_HYSTERESIS_DEG)); + return (ang <= (wake_small_angle - LID_ANGLE_HYSTERESIS_DEG)) || + (ang >= (wake_large_angle + LID_ANGLE_HYSTERESIS_DEG)); } -int lid_angle_get_kb_wake_angle(void) +int lid_angle_get_wake_angle(void) { - return kb_wake_large_angle; + return wake_large_angle; } -void lid_angle_set_kb_wake_angle(int ang) +void lid_angle_set_wake_angle(int ang) { - if (ang < KB_DIS_MIN_LARGE_ANGLE) - ang = KB_DIS_MIN_LARGE_ANGLE; - else if (ang > KB_DIS_MAX_LARGE_ANGLE) - ang = KB_DIS_MAX_LARGE_ANGLE; + if (ang < LID_ANGLE_MIN_LARGE_ANGLE) + ang = LID_ANGLE_MIN_LARGE_ANGLE; + else if (ang > LID_ANGLE_MAX_LARGE_ANGLE) + ang = LID_ANGLE_MAX_LARGE_ANGLE; - kb_wake_large_angle = ang; + wake_large_angle = ang; } -void lidangle_keyscan_update(int lid_ang) +void lid_angle_update(int lid_ang) { - static int lidangle_buffer[KEY_SCAN_LID_ANGLE_BUFFER_SIZE]; + static int lidangle_buffer[LID_ANGLE_BUFFER_SIZE]; static int index; - int i; - int keys_accept = 1, keys_ignore = 1; + int accept = 1, ignore = 1; /* Record most recent lid angle in circular buffer. */ lidangle_buffer[index] = lid_ang; - index = (index == KEY_SCAN_LID_ANGLE_BUFFER_SIZE-1) ? 0 : index+1; + index = (index == LID_ANGLE_BUFFER_SIZE-1) ? 0 : index+1; /* - * Any time the chipset is off, manage whether or not keyboard scanning - * is enabled based on lid angle history. + * Manage whether or not peripherals are enabled based on lid angle + * history. */ - if (!chipset_in_state(CHIPSET_STATE_ON)) { - for (i = 0; i < KEY_SCAN_LID_ANGLE_BUFFER_SIZE; i++) { - /* - * If any lid angle samples are unreliable, then - * don't change keyboard scanning state. - */ - if (lidangle_buffer[i] == LID_ANGLE_UNRELIABLE) - return; - - /* - * Force all elements of the lid angle buffer to be - * in range of one of the conditions in order to change - * to the corresponding key scanning state. - */ - if (!lid_in_range_to_accept_keys(lidangle_buffer[i])) - keys_accept = 0; - if (!lid_in_range_to_ignore_keys(lidangle_buffer[i])) - keys_ignore = 0; - } - - /* Enable or disable keyboard scanning as necessary. */ - if (keys_accept) - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); - else if (keys_ignore && !keys_accept) - keyboard_scan_enable(0, KB_SCAN_DISABLE_LID_ANGLE); + for (i = 0; i < LID_ANGLE_BUFFER_SIZE; i++) { + /* + * If any lid angle samples are unreliable, then + * don't change peripheral state. + */ + if (lidangle_buffer[i] == LID_ANGLE_UNRELIABLE) + return; + + /* + * Force all elements of the lid angle buffer to be + * in range of one of the conditions in order to change + * to the corresponding peripheral state. + */ + if (!lid_in_range_to_enable_peripherals(lidangle_buffer[i])) + accept = 0; + if (!lid_in_range_to_ignore_peripherals(lidangle_buffer[i])) + ignore = 0; } + + /* Enable or disable peripherals as necessary. */ + if (accept) + lid_angle_peripheral_enable(1); + else if (ignore && !accept) + lid_angle_peripheral_enable(0); } -static void enable_keyboard(void) +static void enable_peripherals(void) { /* - * Make sure lid angle is not disabling keyboard scanning when AP is - * running. + * Make sure lid angle is not disabling peripherals when AP is running. */ - keyboard_scan_enable(1, KB_SCAN_DISABLE_LID_ANGLE); + lid_angle_peripheral_enable(1); } -DECLARE_HOOK(HOOK_CHIPSET_RESUME, enable_keyboard, HOOK_PRIO_DEFAULT); +DECLARE_HOOK(HOOK_CHIPSET_RESUME, enable_peripherals, HOOK_PRIO_DEFAULT); diff --git a/common/motion_lid.c b/common/motion_lid.c index 1beb79febb..eca904f900 100644 --- a/common/motion_lid.c +++ b/common/motion_lid.c @@ -153,8 +153,8 @@ void motion_lid_calc(void) accel_lid->xyz, &lid_angle_deg); -#ifdef CONFIG_LID_ANGLE_KEY_SCAN - lidangle_keyscan_update(motion_lid_get_angle()); +#ifdef CONFIG_LID_ANGLE_UPDATE + lid_angle_update(motion_lid_get_angle()); #endif } @@ -170,12 +170,12 @@ int host_cmd_motion_lid(struct host_cmd_handler_args *args) switch (in->cmd) { case MOTIONSENSE_CMD_KB_WAKE_ANGLE: -#ifdef CONFIG_LID_ANGLE_KEY_SCAN +#ifdef CONFIG_LID_ANGLE_UPDATE /* Set new keyboard wake lid angle if data arg has value. */ if (in->kb_wake_angle.data != EC_MOTION_SENSE_NO_VALUE) - lid_angle_set_kb_wake_angle(in->kb_wake_angle.data); + lid_angle_set_wake_angle(in->kb_wake_angle.data); - out->kb_wake_angle.ret = lid_angle_get_kb_wake_angle(); + out->kb_wake_angle.ret = lid_angle_get_wake_angle(); #else out->kb_wake_angle.ret = 0; #endif diff --git a/include/config.h b/include/config.h index 983184d909..3d7271d07c 100644 --- a/include/config.h +++ b/include/config.h @@ -789,10 +789,10 @@ /* Which sensor is located on the lid? */ #undef CONFIG_LID_ANGLE_SENSOR_LID /* - * Allows using the lid angle measurement to determine if key scanning should - * be enabled or disabled when chipset is suspended. + * Allows using the lid angle measurement to determine if peripheral devices + * should be enabled or disabled, like key scanning, trackpad interrupt. */ -#undef CONFIG_LID_ANGLE_KEY_SCAN +#undef CONFIG_LID_ANGLE_UPDATE /* Define which index in motion_sensors is in the base. */ #undef CONFIG_SENSOR_BASE diff --git a/include/lid_angle.h b/include/lid_angle.h index e45a5683a4..3b99a145c6 100644 --- a/include/lid_angle.h +++ b/include/lid_angle.h @@ -10,19 +10,26 @@ /** * Update the lid angle module with the most recent lid angle calculation. Then - * use the lid angle history to enable/disable keyboard scanning when chipset - * is suspended. + * use the lid angle history to enable/disable peripheral devices, keyboard + * scanning and track pad interrupt, etc. * - * @lid_ang Lid angle. + * @param lid_ang Lid angle. */ -void lidangle_keyscan_update(int lid_ang); +void lid_angle_update(int lid_ang); /** * Getter and setter methods for the keyboard wake angle. In S3, when the - * lid angle is greater than this value, the keyboard is disabled, and when - * the lid angle is smaller than this value, the keyboard is enabled. + * lid angle is greater than this value, the peripheral devices are disabled, + * and when the lid angle is smaller than this value, they are enabled. */ -int lid_angle_get_kb_wake_angle(void); -void lid_angle_set_kb_wake_angle(int ang); +int lid_angle_get_wake_angle(void); +void lid_angle_set_wake_angle(int ang); + +/** + * Board level callback for lid angle changes. + * + * @param enable Flag that enables or disables peripherals. + */ +void lid_angle_peripheral_enable(int enable); #endif /* __CROS_EC_LID_ANGLE_H */ |