summaryrefslogtreecommitdiff
path: root/common/motion_lid.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/motion_lid.c')
-rw-r--r--common/motion_lid.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/common/motion_lid.c b/common/motion_lid.c
index d737046c53..db7b076afa 100644
--- a/common/motion_lid.c
+++ b/common/motion_lid.c
@@ -135,8 +135,8 @@ __attribute__((weak)) int board_is_lid_angle_tablet_mode(void)
* - when lid is closed while the hinge is perpendicular to the floor, we will
* stay in tablet mode.
*
- * Tablet mode is defined as the lid angle being greater than 180 degree. We use
- * 2 threshold to calculate tablet mode:
+ * Tablet mode is defined as the lid angle being greater than 180 degree(by
+ * default). We use 2 threshold to calculate tablet mode:
* tablet_mode:
* 1 | +-----<----+----------
* | \/ /\
@@ -144,9 +144,26 @@ __attribute__((weak)) int board_is_lid_angle_tablet_mode(void)
* 0 |------------------>----+
* +------------+----------+----------+ lid angle
* 0 160 200 360
+ *
+ * Host can configure the threshold to be different than default of 180 +/- 20
+ * by using MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE.
*/
-#define TABLET_ZONE_LID_ANGLE FLOAT_TO_FP(200)
-#define LAPTOP_ZONE_LID_ANGLE FLOAT_TO_FP(160)
+
+#define DEFAULT_TABLET_MODE_ANG (180)
+#define DEFAULT_TABLET_MODE_HYS (20)
+
+#define TABLET_ZONE_ANGLE(a, h) ((a) + (h))
+#define LAPTOP_ZONE_ANGLE(a, h) ((a) - (h))
+
+static fp_t tablet_zone_lid_angle =
+ FLOAT_TO_FP(TABLET_ZONE_ANGLE(DEFAULT_TABLET_MODE_ANG,
+ DEFAULT_TABLET_MODE_HYS));
+static fp_t laptop_zone_lid_angle =
+ FLOAT_TO_FP(LAPTOP_ZONE_ANGLE(DEFAULT_TABLET_MODE_ANG,
+ DEFAULT_TABLET_MODE_HYS));
+
+static int tablet_mode_lid_ang = DEFAULT_TABLET_MODE_ANG;
+static int tablet_mode_hys_deg = DEFAULT_TABLET_MODE_HYS;
/*
* We will change our tablet mode status when we are "convinced" that it has
@@ -165,9 +182,9 @@ static void motion_lid_set_tablet_mode(int reliable)
int new_mode = current_mode;
if (reliable) {
- if (last_lid_angle_fp > TABLET_ZONE_LID_ANGLE)
+ if (last_lid_angle_fp > tablet_zone_lid_angle)
new_mode = 1;
- else if (last_lid_angle_fp < LAPTOP_ZONE_LID_ANGLE)
+ else if (last_lid_angle_fp < laptop_zone_lid_angle)
new_mode = 0;
/* Only change tablet mode if we're sure. */
@@ -195,6 +212,24 @@ static void motion_lid_set_tablet_mode(int reliable)
tablet_mode_debounce_cnt = TABLET_MODE_DEBOUNCE_COUNT;
}
+static int lid_angle_set_tablet_mode_threshold(int ang, int hys)
+{
+ if ((ang == EC_MOTION_SENSE_NO_VALUE) ||
+ (hys == EC_MOTION_SENSE_NO_VALUE))
+ return EC_RES_SUCCESS;
+
+ if ((ang < 0) || (hys < 0) || (ang < hys) || ((ang + hys) > 360))
+ return EC_RES_INVALID_PARAM;
+
+ tablet_mode_lid_ang = ang;
+ tablet_mode_hys_deg = hys;
+
+ tablet_zone_lid_angle = INT_TO_FP(TABLET_ZONE_ANGLE(ang, hys));
+ laptop_zone_lid_angle = INT_TO_FP(LAPTOP_ZONE_ANGLE(ang, hys));
+
+ return EC_RES_SUCCESS;
+}
+
#endif /* CONFIG_TABLET_MODE */
#if defined(CONFIG_DPTF_MULTI_PROFILE) && \
@@ -534,6 +569,29 @@ int host_cmd_motion_lid(struct host_cmd_handler_args *args)
#endif
break;
+ case MOTIONSENSE_CMD_TABLET_MODE_LID_ANGLE:
+ {
+#ifdef CONFIG_TABLET_MODE
+ int ret;
+ ret = lid_angle_set_tablet_mode_threshold(
+ in->tablet_mode_threshold.lid_ang,
+ in->tablet_mode_threshold.hys_deg);
+
+ if (ret != EC_RES_SUCCESS)
+ return ret;
+
+ out->tablet_mode_threshold.lid_ang =
+ tablet_mode_lid_ang;
+ out->tablet_mode_threshold.hys_deg =
+ tablet_mode_hys_deg;
+
+ args->response_size =
+ sizeof(out->tablet_mode_threshold);
+#else
+ return EC_RES_INVALID_PARAM;
+#endif
+ }
+ break;
default:
return EC_RES_INVALID_PARAM;
}