summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorli feng <li1.feng@intel.com>2015-07-02 13:29:10 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-08-10 20:42:18 +0000
commit2911e38022a950d9f0e85ed7480829bf21d34a1f (patch)
tree3a5997761bcee8f6443069d4b49cd08c549d386c
parent68b2809ee8f611d089f6d946dba10bb1b6d5c507 (diff)
downloadchrome-ec-2911e38022a950d9f0e85ed7480829bf21d34a1f.tar.gz
Cyan: Added Clamshell/Tablet mode support
Enabled lid angle calculation. Clamshell/Tablet mode is decided by lid angle. Accelerometers are set to be active in S3 also. Trackpad is enabled/disabled by GPIO TP_INT_DISABLE. Keyboard scan and trackpad are enabled in clamshell mode and disabled in tablet mode. Removed enable_keyboard() since keyboard is enabled in clamshell S0 and S3. BUG=chrome-os-partner:41353 TEST=Verify in clamshell mode, system can be waken up from S3 by keyboard/trackpad; And not tablet mode. BRANCH=None Change-Id: Ic5fb5a562e8426288eae2fb9815a213fe5033955 Signed-off-by: li feng <li1.feng@intel.com> Signed-off-by: Shamile Khan <shamile.khan@intel.com> Reviewed-on: https://chromium-review.googlesource.com/287341 Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--board/cyan/board.c49
-rw-r--r--board/cyan/board.h1
-rw-r--r--common/build.mk2
-rw-r--r--common/lid_angle.c161
-rw-r--r--common/motion_lid.c10
-rw-r--r--include/config.h6
-rw-r--r--include/lid_angle.h23
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 */