summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/ryu/board.c137
-rw-r--r--common/motion_sense.c296
-rw-r--r--driver/accel_kxcj9.c10
-rw-r--r--driver/accelgyro_bmi160.c20
-rw-r--r--driver/accelgyro_bmi160.h2
-rw-r--r--driver/accelgyro_lsm6ds0.c17
-rw-r--r--driver/accelgyro_lsm6ds0.h4
-rw-r--r--driver/als_si114x.c2
-rw-r--r--include/accelgyro.h6
-rw-r--r--include/motion_sense.h58
-rw-r--r--test/motion_lid.c93
11 files changed, 427 insertions, 218 deletions
diff --git a/board/ryu/board.c b/board/ryu/board.c
index c38a9823da..53d3d2efd3 100644
--- a/board/ryu/board.c
+++ b/board/ryu/board.c
@@ -287,12 +287,29 @@ struct motion_sensor_t motion_sensors[] = {
.drv_data = &g_bmi160_data,
.addr = BMI160_ADDR0,
.rot_standard_ref = &accelgyro_standard_ref,
- .default_config = {
- /* 100Hz is fast enough for double tap detection */
- .odr = 100000,
- .range = 8, /* g */
- .ec_rate = SUSPEND_SAMPLING_INTERVAL,
- }
+ .default_range = 8, /* g, use hifi requirements */
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC does not need accel in S0 */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* Used for double tap */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 100000,
+ /* Interrupt driven, no polling */
+ .ec_rate = 0,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 100000,
+ .ec_rate = 0,
+ },
+ },
},
{.name = "Gyro",
@@ -304,12 +321,29 @@ struct motion_sensor_t motion_sensors[] = {
.mutex = &g_mutex,
.drv_data = &g_bmi160_data,
.addr = BMI160_ADDR0,
+ .default_range = 1000, /* dps, use hifi requirement */
.rot_standard_ref = &accelgyro_standard_ref,
- .default_config = {
- .odr = 0,
- .range = 1000, /* dps */
- .ec_rate = MAX_MOTION_SENSE_WAIT_TIME,
- }
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC does not need accel in S0 */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* Unused */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ },
},
{.name = "Mag",
@@ -322,11 +356,28 @@ struct motion_sensor_t motion_sensors[] = {
.drv_data = &g_bmi160_data,
.addr = BMI160_ADDR0,
.rot_standard_ref = &mag_standard_ref,
- .default_config = {
- .odr = 0,
- .range = 1 << 11, /* 16LSB / uT */
- .ec_rate = MAX_MOTION_SENSE_WAIT_TIME,
- }
+ .default_range = 1 << 11, /* 16LSB / uT, fixed */
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC does not need accel in S0 */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* Unused */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ },
},
{.name = "Light",
.active_mask = SENSOR_ACTIVE_S0_S3_S5,
@@ -338,11 +389,28 @@ struct motion_sensor_t motion_sensors[] = {
.drv_data = &g_si114x_data,
.addr = SI114X_ADDR,
.rot_standard_ref = NULL,
- .default_config = {
- .odr = 0,
- .range = 9000, /* 90%: int = 0 - frac = 9000/10000 */
- .ec_rate = 1000 * MSEC,
- }
+ .default_range = 9000, /* 90%: int = 0 - frac = 9000/10000 */
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC to use to set led brightness */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 1000,
+ .ec_rate = 1000,
+ },
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 1000,
+ /* Interrupt driven, for double tap */
+ .ec_rate = 0,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 1000,
+ .ec_rate = 0,
+ },
+ },
},
{.name = "Proxi",
.active_mask = SENSOR_ACTIVE_S0_S3_S5,
@@ -354,11 +422,28 @@ struct motion_sensor_t motion_sensors[] = {
.drv_data = &g_si114x_data,
.addr = SI114X_ADDR,
.rot_standard_ref = NULL,
- .default_config = {
- .odr = 0,
- .range = 1 << 16, /* 100% fuzzy unit */
- .ec_rate = 1000 * MSEC,
- }
+ .default_range = 1 << 16, /* 100% fuzzy unit */
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC does not need accel in S0 */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* Unused */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ },
},
};
const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
diff --git a/common/motion_sense.c b/common/motion_sense.c
index b5de3480ff..f2650fbc52 100644
--- a/common/motion_sense.c
+++ b/common/motion_sense.c
@@ -39,11 +39,6 @@ unsigned accel_interval;
static int accel_disp;
#endif
-#define SENSOR_EC_RATE(_sensor) \
- (sensor_active == SENSOR_ACTIVE_S0 ? \
- (_sensor)->runtime_config.ec_rate : \
- (_sensor)->default_config.ec_rate)
-
#define SENSOR_ACTIVE(_sensor) (sensor_active & (_sensor)->active_mask)
/*
@@ -71,7 +66,8 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data,
struct ec_response_motion_sensor_data vector;
int i;
- data->sensor_num = (sensor - motion_sensors);
+ data->sensor_num = sensor - motion_sensors;
+
mutex_lock(&g_sensor_mutex);
if (queue_space(&motion_sense_fifo) == 0) {
queue_remove_unit(&motion_sense_fifo, &vector);
@@ -83,10 +79,29 @@ void motion_sense_fifo_add_unit(struct ec_response_motion_sensor_data *data,
for (i = 0; i < valid_data; i++)
sensor->xyz[i] = data->data[i];
mutex_unlock(&g_sensor_mutex);
+
+ if (valid_data) {
+ int ap_odr = sensor->config[SENSOR_CONFIG_AP].odr &
+ ~ROUND_UP_FLAG;
+ int rate = INT_TO_FP(sensor->drv->get_data_rate(sensor));
+
+ /* If the AP does not want sensor info, skip */
+ if (ap_odr == 0)
+ return;
+
+ /* Skip if EC is oversampling */
+ if (sensor->oversampling < 0) {
+ sensor->oversampling += fp_div(INT_TO_FP(1000), rate);
+ return;
+ }
+ sensor->oversampling += fp_div(INT_TO_FP(1000), rate) -
+ fp_div(INT_TO_FP(1000), INT_TO_FP(ap_odr));
+ }
+
queue_add_unit(&motion_sense_fifo, data);
}
-static inline void motion_sense_insert_flush(struct motion_sensor_t *sensor)
+static void motion_sense_insert_flush(struct motion_sensor_t *sensor)
{
struct ec_response_motion_sensor_data vector;
vector.flags = MOTIONSENSE_SENSOR_FLAG_FLUSH |
@@ -95,7 +110,7 @@ static inline void motion_sense_insert_flush(struct motion_sensor_t *sensor)
motion_sense_fifo_add_unit(&vector, sensor, 0);
}
-static inline void motion_sense_insert_timestamp(void)
+static void motion_sense_insert_timestamp(void)
{
struct ec_response_motion_sensor_data vector;
vector.flags = MOTIONSENSE_SENSOR_FLAG_TIMESTAMP;
@@ -130,53 +145,111 @@ static inline int motion_sensor_time_to_read(const timestamp_t *ts,
sensor->last_collection + 950000000 / rate);
}
+static enum sensor_config motion_sense_get_ec_config(void)
+{
+ switch (sensor_active) {
+ case SENSOR_ACTIVE_S0:
+ return SENSOR_CONFIG_EC_S0;
+ case SENSOR_ACTIVE_S3:
+ return SENSOR_CONFIG_EC_S3;
+ case SENSOR_ACTIVE_S5:
+ return SENSOR_CONFIG_EC_S5;
+ default:
+ CPRINTS("get_ec_config: Invalid active state: %x",
+ sensor_active);
+ return SENSOR_CONFIG_MAX;
+ }
+}
+/* motion_sense_set_data_rate
+ *
+ * Set the sensor data rate. It is altered when the AP change the data
+ * rate or when the power state changes.
+ */
+int motion_sense_set_data_rate(struct motion_sensor_t *sensor)
+{
+ int roundup = 0, ec_odr = 0, odr = 0;
+ enum sensor_config config_id;
+
+ /* We assume the sensor is initalized */
+
+ /* Check the AP setting first. */
+ if (sensor_active != SENSOR_ACTIVE_S5)
+ odr = sensor->config[SENSOR_CONFIG_AP].odr & ~ROUND_UP_FLAG;
+
+ /* check if the EC set the sensor ODR at a higher frequency */
+ config_id = motion_sense_get_ec_config();
+ ec_odr = sensor->config[config_id].odr & ~ROUND_UP_FLAG;
+ if (ec_odr > odr)
+ odr = ec_odr;
+ else
+ config_id = SENSOR_CONFIG_AP;
+ roundup = !!(sensor->config[config_id].odr & ROUND_UP_FLAG);
+ CPRINTS("%s ODR: %d - roundup %d from config %d",
+ sensor->name, odr, roundup, config_id);
+ return sensor->drv->set_data_rate(sensor, odr, roundup);
+}
+
+/* motion_sense_ec_rate
+ *
+ * Calculate the sensor ec rate. It will be use to set the motion task polling
+ * rate.
+ *
+ * Return the EC rate, in us.
+ */
+static int motion_sense_ec_rate(struct motion_sensor_t *sensor)
+{
+ int ec_rate = 0, ec_rate_from_cfg;
+ enum sensor_config config_id = SENSOR_CONFIG_AP;
+
+ /* Check the AP setting first. */
+ if (sensor_active != SENSOR_ACTIVE_S5)
+ ec_rate = sensor->config[SENSOR_CONFIG_AP].ec_rate;
+
+ config_id = motion_sense_get_ec_config();
+ ec_rate_from_cfg = sensor->config[config_id].ec_rate;
+ if ((ec_rate == 0 && ec_rate_from_cfg != 0) ||
+ (ec_rate_from_cfg != 0 && ec_rate_from_cfg < ec_rate))
+ ec_rate = ec_rate_from_cfg;
+ return ec_rate * MSEC;
+}
+
/*
* motion_sense_set_accel_interval
*
* Set the wake up interval for the motion sense thread.
* It is set to the highest frequency one of the sensors need to be polled at.
*
- * driving_sensor: In S0, indicates which sensor has its EC sampling rate
- * changed. In S3, it is hard coded, so in S3 driving_sensor should be NULL.
- * data: The new ec sampling rate for this sensor.
- *
* Note: Not static to be tested.
*/
-int motion_sense_set_accel_interval(
- struct motion_sensor_t *driving_sensor,
- unsigned data)
+int motion_sense_set_accel_interval(void)
{
- int i;
+ int i, sensor_ec_rate, ec_rate, wake_up = 0;
struct motion_sensor_t *sensor;
- if (driving_sensor)
- driving_sensor->runtime_config.ec_rate = data;
-
- for (i = 0; i < motion_sensor_count; ++i) {
+ for (i = 0, ec_rate = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
- if (sensor == driving_sensor)
- continue;
/*
* If the sensor is sleeping, no need to check it periodicaly.
*/
- if ((sensor->runtime_config.odr == 0) ||
- (sensor->state != SENSOR_INITIALIZED))
+ if ((sensor->state != SENSOR_INITIALIZED) ||
+ (sensor->drv->get_data_rate(sensor) == 0))
continue;
- if (SENSOR_EC_RATE(sensor) < data)
- data = SENSOR_EC_RATE(sensor);
+ sensor_ec_rate = motion_sense_ec_rate(sensor);
+ if ((ec_rate == 0 && sensor_ec_rate != 0) ||
+ (sensor_ec_rate != 0 && sensor_ec_rate < ec_rate))
+ ec_rate = sensor_ec_rate;
}
- if (accel_interval > data) {
- accel_interval = data;
- /*
- * Wake up the motion sense task: we want to sensor task to take
- * in account the new period right away.
- */
+ /*
+ * Wake up the motion sense task: we want to sensor task to take
+ * in account the new period right away.
+ */
+ if (accel_interval == 0 ||
+ (ec_rate > 0 && accel_interval > ec_rate))
+ wake_up = 1;
+ accel_interval = ec_rate;
+ if (wake_up)
task_wake(TASK_ID_MOTIONSENSE);
- } else {
- accel_interval = data;
- }
-
- return data;
+ return accel_interval;
}
static inline void motion_sense_init(struct motion_sensor_t *sensor)
@@ -194,29 +267,36 @@ static inline void motion_sense_init(struct motion_sensor_t *sensor)
timestamp_t ts = get_time();
sensor->state = SENSOR_INITIALIZED;
sensor->last_collection = ts.le.lo;
+ sensor->oversampling = 0;
+ motion_sense_set_data_rate(sensor);
}
}
/*
- * motion_sense_switch_unused_sensor
+ * motion_sense_switch_sensor_rate
*
* Suspend all sensors that are not needed.
* Mark them as unitialized, they wll lose power and
* need to be initialized again.
*/
-static void motion_sense_switch_unused_sensor(void)
+static void motion_sense_switch_sensor_rate(void)
{
int i;
struct motion_sensor_t *sensor;
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
- if ((sensor->state == SENSOR_INITIALIZED) &&
- !SENSOR_ACTIVE(sensor)) {
- sensor->drv->set_data_rate(sensor, 0, 0);
- sensor->state = SENSOR_NOT_INITIALIZED;
+ if (SENSOR_ACTIVE(sensor)) {
+ /* Initialize or just back the odr previously set. */
+ if (sensor->state == SENSOR_INITIALIZED)
+ motion_sense_set_data_rate(sensor);
+ else
+ motion_sense_init(sensor);
+ } else {
+ if (sensor->state == SENSOR_INITIALIZED)
+ sensor->state = SENSOR_NOT_INITIALIZED;
}
}
- motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
+ motion_sense_set_accel_interval();
}
static void motion_sense_shutdown(void)
@@ -225,14 +305,16 @@ static void motion_sense_shutdown(void)
struct motion_sensor_t *sensor;
sensor_active = SENSOR_ACTIVE_S5;
- motion_sense_switch_unused_sensor();
for (i = 0; i < motion_sensor_count; i++) {
sensor = &motion_sensors[i];
/* Forget about changes made by the AP */
- memcpy(&sensor->runtime_config, &sensor->default_config,
- sizeof(sensor->runtime_config));
+ sensor->config[SENSOR_CONFIG_AP].odr = 0;
+ sensor->config[SENSOR_CONFIG_AP].ec_rate = 0;
+ sensor->drv->set_range(sensor, sensor->default_range, 0);
+
}
+ motion_sense_switch_sensor_rate();
}
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, motion_sense_shutdown,
MOTION_SENSE_HOOK_PRIO);
@@ -247,27 +329,15 @@ static void motion_sense_suspend(void)
return;
sensor_active = SENSOR_ACTIVE_S3;
- motion_sense_switch_unused_sensor();
+ motion_sense_switch_sensor_rate();
}
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, motion_sense_suspend,
MOTION_SENSE_HOOK_PRIO);
static void motion_sense_resume(void)
{
- int i;
- struct motion_sensor_t *sensor;
-
sensor_active = SENSOR_ACTIVE_S0;
- for (i = 0; i < motion_sensor_count; i++) {
- sensor = &motion_sensors[i];
- /* Initialize or just back the odr previously set. */
- if (sensor->state == SENSOR_INITIALIZED)
- sensor->drv->set_data_rate(sensor,
- sensor->runtime_config.odr, 1);
- else
- motion_sense_init(sensor);
- }
- motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
+ motion_sense_switch_sensor_rate();
}
DECLARE_HOOK(HOOK_CHIPSET_RESUME, motion_sense_resume,
MOTION_SENSE_HOOK_PRIO);
@@ -281,11 +351,7 @@ static void motion_sense_startup(void)
for (i = 0; i < motion_sensor_count; ++i) {
sensor = &motion_sensors[i];
sensor->state = SENSOR_NOT_INITIALIZED;
-
- memcpy(&sensor->runtime_config, &sensor->default_config,
- sizeof(sensor->runtime_config));
}
- motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
/* If the AP is already in S0, call the resume hook now.
* We may initialize the sensor 2 times (once in RO, anoter time in RW),
@@ -357,7 +423,7 @@ static int motion_sense_read(struct motion_sensor_t *sensor)
if (sensor->state != SENSOR_INITIALIZED)
return EC_ERROR_UNKNOWN;
- if (sensor->runtime_config.odr == 0)
+ if (sensor->drv->get_data_rate(sensor) == 0)
return EC_ERROR_NOT_POWERED;
/* Read all raw X,Y,Z accelerations. */
@@ -466,7 +532,6 @@ void motion_sense_task(void)
/* if the sensor is active in the current power state */
if (SENSOR_ACTIVE(sensor)) {
if (sensor->state != SENSOR_INITIALIZED) {
- CPRINTS("S%d active not initalized", i);
continue;
}
@@ -524,7 +589,8 @@ void motion_sense_task(void)
if (fifo_flush_needed ||
event & TASK_EVENT_MOTION_ODR_CHANGE ||
queue_space(&motion_sense_fifo) < CONFIG_ACCEL_FIFO_THRES ||
- (ts_end_task.val - ts_last_int.val) > accel_interval) {
+ (accel_interval > 0 &&
+ (ts_end_task.val - ts_last_int.val) > accel_interval)) {
if (!fifo_flush_needed)
motion_sense_insert_timestamp();
fifo_flush_needed = 0;
@@ -540,16 +606,24 @@ void motion_sense_task(void)
#endif
}
#endif
- /* Delay appropriately to keep sampling time consistent. */
- wait_us = accel_interval -
- (ts_end_task.val - ts_begin_task.val);
+ if (accel_interval > 0) {
+ /*
+ * Delay appropriately to keep sampling time
+ * consistent.
+ */
+ wait_us = accel_interval -
+ (ts_end_task.val - ts_begin_task.val);
+
+ /*
+ * Guarantee some minimum delay to allow other lower
+ * priority tasks to run.
+ */
+ if (wait_us < MIN_MOTION_SENSE_WAIT_TIME)
+ wait_us = MIN_MOTION_SENSE_WAIT_TIME;
+ } else {
+ wait_us = -1;
+ }
- /*
- * Guarantee some minimum delay to allow other lower priority
- * tasks to run.
- */
- if (wait_us < MIN_MOTION_SENSE_WAIT_TIME)
- wait_us = MIN_MOTION_SENSE_WAIT_TIME;
} while ((event = task_wait_event(wait_us)));
}
@@ -591,7 +665,7 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
const struct ec_params_motion_sense *in = args->params;
struct ec_response_motion_sense *out = args->response;
struct motion_sensor_t *sensor;
- int i, data, ret = EC_RES_INVALID_PARAM, reported;
+ int i, ret = EC_RES_INVALID_PARAM, reported;
switch (in->cmd) {
case MOTIONSENSE_CMD_DUMP:
@@ -657,14 +731,18 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
* has a value.
*/
if (in->ec_rate.data != EC_MOTION_SENSE_NO_VALUE) {
+ if (in->ec_rate.data == 0)
+ sensor->config[SENSOR_CONFIG_AP].ec_rate = 0;
+ else
+ sensor->config[SENSOR_CONFIG_AP].ec_rate =
+ MAX(in->ec_rate.data,
+ MIN_MOTION_SENSE_WAIT_TIME / MSEC);
+
/* Bound the new sampling rate. */
- motion_sense_set_accel_interval(
- sensor,
- MAX(in->ec_rate.data * MSEC,
- MIN_MOTION_SENSE_WAIT_TIME));
+ motion_sense_set_accel_interval();
}
- out->ec_rate.ret = sensor->runtime_config.ec_rate / MSEC;
+ out->ec_rate.ret = motion_sense_ec_rate(sensor) / MSEC;
args->response_size = sizeof(out->ec_rate);
break;
@@ -678,14 +756,14 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
/* Set new data rate if the data arg has a value. */
if (in->sensor_odr.data != EC_MOTION_SENSE_NO_VALUE) {
- if (sensor->drv->set_data_rate(sensor,
- in->sensor_odr.data,
- in->sensor_odr.roundup)
- != EC_SUCCESS) {
- CPRINTS("MS bad sensor rate %d",
- in->sensor_odr.data);
+ sensor->config[SENSOR_CONFIG_AP].odr =
+ in->sensor_odr.data |
+ (in->sensor_odr.roundup ? ROUND_UP_FLAG : 0);
+
+ ret = motion_sense_set_data_rate(sensor);
+ if (ret != EC_SUCCESS)
return EC_RES_INVALID_PARAM;
- }
+
/*
* To be sure timestamps are calculated properly,
* Send an event to have a timestamp inserted in the
@@ -698,16 +776,10 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
* suspended, we have to recalculate the EC sampling
* rate
*/
- motion_sense_set_accel_interval(
- NULL, MAX_MOTION_SENSE_WAIT_TIME);
-
+ motion_sense_set_accel_interval();
}
- data = sensor->drv->get_data_rate(sensor);
-
- /* Save configuration parameter: ODR */
- sensor->runtime_config.odr = data;
- out->sensor_odr.ret = data;
+ out->sensor_odr.ret = sensor->drv->get_data_rate(sensor);
args->response_size = sizeof(out->sensor_odr);
@@ -726,18 +798,11 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
in->sensor_range.data,
in->sensor_range.roundup)
!= EC_SUCCESS) {
- CPRINTS("MS bad sensor range %d",
- in->sensor_range.data);
return EC_RES_INVALID_PARAM;
}
}
- data = sensor->drv->get_range(sensor);
-
- /* Save configuration parameter: range */
- sensor->runtime_config.range = data;
-
- out->sensor_range.ret = data;
+ out->sensor_range.ret = sensor->drv->get_range(sensor);
args->response_size = sizeof(out->sensor_range);
break;
@@ -832,8 +897,6 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
if (ret == EC_RES_INVALID_PARAM)
ret = host_cmd_motion_lid(args);
#endif
- if (ret == EC_RES_INVALID_PARAM)
- CPRINTS("MS bad cmd 0x%x", in->cmd);
return ret;
}
@@ -945,8 +1008,9 @@ DECLARE_CONSOLE_COMMAND(accelres, command_accelresolution,
static int command_accel_data_rate(int argc, char **argv)
{
char *e;
- int id, data, round = 1;
+ int id, data, round = 1, ret;
struct motion_sensor_t *sensor;
+ enum sensor_config config_id;
if (argc < 2 || argc > 4)
return EC_ERROR_PARAM_COUNT;
@@ -975,17 +1039,19 @@ static int command_accel_data_rate(int argc, char **argv)
* Write new data rate, if it returns invalid arg, then
* return a parameter error.
*/
- if (sensor->drv->set_data_rate(sensor, data, round) ==
- EC_ERROR_INVAL)
+ config_id = motion_sense_get_ec_config();
+ sensor->config[config_id].odr =
+ data | (round ? ROUND_UP_FLAG : 0);
+ ret = motion_sense_set_data_rate(sensor);
+ if (ret)
return EC_ERROR_PARAM2;
- sensor->runtime_config.odr = data;
- motion_sense_set_accel_interval(
- NULL, MAX_MOTION_SENSE_WAIT_TIME);
+ /* Sensor might be out of suspend, check the ec_rate */
+ motion_sense_set_accel_interval();
} else {
ccprintf("Data rate for sensor %d: %d\n", id,
sensor->drv->get_data_rate(sensor));
ccprintf("EC rate for sensor %d: %d\n", id,
- SENSOR_EC_RATE(sensor));
+ motion_sense_ec_rate(sensor));
ccprintf("Current EC rate: %d\n", accel_interval);
}
diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c
index b893d71c51..dd0cf49115 100644
--- a/driver/accel_kxcj9.c
+++ b/driver/accel_kxcj9.c
@@ -511,7 +511,7 @@ static int init(const struct motion_sensor_t *s)
}
} while (1);
- ret = set_range(s, s->runtime_config.range, 1);
+ ret = set_range(s, s->default_range, 1);
if (ret != EC_SUCCESS)
return ret;
@@ -519,15 +519,11 @@ static int init(const struct motion_sensor_t *s)
if (ret != EC_SUCCESS)
return ret;
- ret = set_data_rate(s, s->runtime_config.odr, 1);
- if (ret != EC_SUCCESS)
- return ret;
-
#ifdef CONFIG_ACCEL_INTERRUPTS
config_interrupt(s);
#endif
- CPRINTF("[%T %s: Done Init type:0x%X range:%d rate:%d]\n",
- s->name, s->type, get_range(s), get_data_rate(s));
+ CPRINTF("[%T %s: Done Init type:0x%X range:%d]\n",
+ s->name, s->type, get_range(s));
return ret;
}
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c
index 0960131926..3044fe1c66 100644
--- a/driver/accelgyro_bmi160.c
+++ b/driver/accelgyro_bmi160.c
@@ -304,7 +304,7 @@ static int set_range(const struct motion_sensor_t *s,
int ret, range_tbl_size;
uint8_t reg_val, ctrl_reg;
const struct accel_param_pair *ranges;
- struct motion_data_t *data = BMI160_GET_SAVED_DATA(s);
+ struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
if (s->type == MOTIONSENSE_TYPE_MAG) {
data->range = range;
@@ -325,7 +325,7 @@ static int set_range(const struct motion_sensor_t *s,
static int get_range(const struct motion_sensor_t *s)
{
- struct motion_data_t *data = BMI160_GET_SAVED_DATA(s);
+ struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
return data->range;
}
@@ -349,7 +349,7 @@ static int set_data_rate(const struct motion_sensor_t *s,
{
int ret, val, normalized_rate;
uint8_t ctrl_reg, reg_val;
- struct motion_data_t *data = BMI160_GET_SAVED_DATA(s);
+ struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
if (rate == 0) {
#ifdef CONFIG_ACCEL_FIFO
@@ -429,8 +429,9 @@ static int set_data_rate(const struct motion_sensor_t *s,
data->odr = normalized_rate;
#ifdef CONFIG_ACCEL_FIFO
- /* FIFO start collecting events */
- enable_fifo(s, 1);
+ /* FIFO start collecting events if AP wants them */
+ if (s->config[SENSOR_CONFIG_AP].odr != 0)
+ enable_fifo(s, 1);
#endif
accel_cleanup:
@@ -440,7 +441,7 @@ accel_cleanup:
static int get_data_rate(const struct motion_sensor_t *s)
{
- struct motion_data_t *data = BMI160_GET_SAVED_DATA(s);
+ struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
return data->odr;
}
@@ -1015,11 +1016,10 @@ static int init(const struct motion_sensor_t *s)
if (s->type == MOTIONSENSE_TYPE_ACCEL)
ret = config_interrupt(s);
#endif
- set_data_rate(s, s->runtime_config.odr, 0);
- set_range(s, s->runtime_config.range, 0);
+ set_range(s, s->default_range, 0);
- CPRINTF("[%T %s: MS Done Init type:0x%X range:%d odr:%d]\n",
- s->name, s->type, get_range(s), get_data_rate(s));
+ CPRINTF("[%T %s: MS Done Init type:0x%X range:%d]\n",
+ s->name, s->type, get_range(s));
return ret;
}
diff --git a/driver/accelgyro_bmi160.h b/driver/accelgyro_bmi160.h
index fd2de42a4b..069e49b265 100644
--- a/driver/accelgyro_bmi160.h
+++ b/driver/accelgyro_bmi160.h
@@ -405,7 +405,7 @@ enum bmi160_running_mode {
#define BMI160_FIFO_ALL_MASK 7
struct bmi160_drv_data_t {
- struct motion_data_t saved_data[3];
+ struct accelgyro_saved_data_t saved_data[3];
uint8_t flags;
#ifdef CONFIG_MAG_BMI160_BMM150
struct bmm150_comp_registers comp_regs;
diff --git a/driver/accelgyro_lsm6ds0.c b/driver/accelgyro_lsm6ds0.c
index dee3e7d622..62996825ac 100644
--- a/driver/accelgyro_lsm6ds0.c
+++ b/driver/accelgyro_lsm6ds0.c
@@ -426,29 +426,20 @@ static int init(const struct motion_sensor_t *s)
if (ret)
return EC_ERROR_UNKNOWN;
- ret = set_range(s, s->runtime_config.range, 1);
- if (ret)
- return EC_ERROR_UNKNOWN;
-
- ret = set_data_rate(s, s->runtime_config.odr, 1);
+ ret = set_range(s, s->default_range, 1);
if (ret)
return EC_ERROR_UNKNOWN;
}
if (MOTIONSENSE_TYPE_GYRO == s->type) {
/* Config GYRO Range */
- ret = set_range(s, s->runtime_config.range, 1);
- if (ret)
- return EC_ERROR_UNKNOWN;
-
- /* Config ACCEL & GYRO ODR */
- ret = set_data_rate(s, s->runtime_config.odr, 1);
+ ret = set_range(s, s->default_range, 1);
if (ret)
return EC_ERROR_UNKNOWN;
}
- CPRINTF("[%T %s: MS Done Init type:0x%X range:%d odr:%d]\n",
- s->name, s->type, get_range(s), get_data_rate(s));
+ CPRINTF("[%T %s: MS Done Init type:0x%X range:%d]\n",
+ s->name, s->type, get_range(s));
return ret;
}
diff --git a/driver/accelgyro_lsm6ds0.h b/driver/accelgyro_lsm6ds0.h
index 82b675db09..481f39aa10 100644
--- a/driver/accelgyro_lsm6ds0.h
+++ b/driver/accelgyro_lsm6ds0.h
@@ -8,7 +8,7 @@
#ifndef __CROS_EC_ACCELGYRO_LSM6DS0_H
#define __CROS_EC_ACCELGYRO_LSM6DS0_H
-#include "motion_sense.h"
+#include "accelgyro.h"
#include "task.h"
/*
@@ -119,7 +119,7 @@ enum lsm6ds0_bdu {
extern const struct accelgyro_drv lsm6ds0_drv;
struct lsm6ds0_data {
- struct motion_data_t base;
+ struct accelgyro_saved_data_t base;
int16_t offset[3];
};
diff --git a/driver/als_si114x.c b/driver/als_si114x.c
index c7a3d0374a..3be0c68d67 100644
--- a/driver/als_si114x.c
+++ b/driver/als_si114x.c
@@ -487,7 +487,7 @@ static int init(const struct motion_sensor_t *s)
resol = 5;
}
- set_range(s, s->runtime_config.range, 0);
+ set_range(s, s->default_range, 0);
/*
* Sensor is most likely behind a glass.
* Max out the gain to get correct measurement
diff --git a/include/accelgyro.h b/include/accelgyro.h
index c65e624bf4..46ab68d855 100644
--- a/include/accelgyro.h
+++ b/include/accelgyro.h
@@ -120,4 +120,10 @@ struct accelgyro_drv {
#endif
};
+/* Used to save sensor information */
+struct accelgyro_saved_data_t {
+ int odr;
+ int range;
+};
+
#endif /* __CROS_EC_ACCELGYRO_H */
diff --git a/include/motion_sense.h b/include/motion_sense.h
index cbe311fdf6..6541893d67 100644
--- a/include/motion_sense.h
+++ b/include/motion_sense.h
@@ -22,6 +22,14 @@ enum sensor_state {
SENSOR_INIT_ERROR = 2
};
+enum sensor_config {
+ SENSOR_CONFIG_AP, /* Configuration requested/for the AP */
+ SENSOR_CONFIG_EC_S0, /* Configuration from the EC while device in S0 */
+ SENSOR_CONFIG_EC_S3, /* from the EC when device sleep */
+ SENSOR_CONFIG_EC_S5, /* from the EC when device powered off */
+ SENSOR_CONFIG_MAX,
+};
+
#define SENSOR_ACTIVE_S5 CHIPSET_STATE_SOFT_OFF
#define SENSOR_ACTIVE_S3 CHIPSET_STATE_SUSPEND
#define SENSOR_ACTIVE_S0 CHIPSET_STATE_ON
@@ -47,17 +55,21 @@ enum sensor_state {
#define MIN_MOTION_SENSE_WAIT_TIME (3 * MSEC)
#define MAX_MOTION_SENSE_WAIT_TIME (60000 * MSEC)
+#define ROUND_UP_FLAG (1 << 31)
+
struct motion_data_t {
- /* data rate the sensor will measure, in mHz */
- int odr;
- /* range of measurement in SI */
- int range;
+ /*
+ * data rate the sensor will measure, in mHz: 0 suspended.
+ * MSB is used to know if we are rounding up.
+ * */
+ unsigned odr;
/* delay between collection by EC, in ms.
* For non FIFO sensor, should be nead 1e6/odr to
* collect events.
* For sensor with FIFO, can be much longer.
+ * 0: no collection.
*/
- unsigned ec_rate;
+ unsigned short ec_rate;
};
struct motion_sensor_t {
@@ -74,11 +86,29 @@ struct motion_sensor_t {
uint8_t addr;
const matrix_3x3_t *rot_standard_ref;
- /* Default configuration parameters, RO only */
- struct motion_data_t default_config;
+ /*
+ * default_range: set by default by the EC.
+ * The host can change it, but rarely does.
+ */
+ int default_range;
- /* Run-Time configuration parameters */
- struct motion_data_t runtime_config;
+ /*
+ * There are 4 configuration parameters to deal with different
+ * configuration
+ *
+ * Power | S0 | S3 | S5
+ * --------+-------------------+-------------------+-----------------
+ * From AP | <------- SENSOR_CONFIG_AP ----------> |
+ * | Use for normal | While sleeping | Always disabled
+ * | operation: game, | iFor Activity |
+ * | screen rotatopm | Recognition |
+ * --------+-------------------+-------------------+------------------
+ * From EC |SENSOR_CONFIG_EC_S0|SENSOR_CONFIG_EC_S3|SENSOR_CONFIG_EC_S5
+ * | Background | Gesture Recognition (Double tap, ...)
+ * | Activity: compass,|
+ * | ambient light)|
+ */
+ struct motion_data_t config[SENSOR_CONFIG_MAX];
/* state parameters */
enum sensor_state state;
@@ -89,6 +119,11 @@ struct motion_sensor_t {
uint32_t flush_pending;
/*
+ * Allow EC to request an higher frequency for the sensors than the AP.
+ */
+ fp_t oversampling;
+
+ /*
* How many vector events are lost in the FIFO since last time
* FIFO info has been transmitted.
*/
@@ -109,10 +144,9 @@ extern struct motion_sensor_t motion_sensors[];
extern const unsigned motion_sensor_count;
/* For testing purposes: export the sampling interval. */
+extern enum chipset_state_mask sensor_active;
extern unsigned accel_interval;
-int motion_sense_set_accel_interval(
- struct motion_sensor_t *driving_sensor,
- unsigned data);
+int motion_sense_set_accel_interval(void);
/*
* Priority of the motion sense resume/suspend hooks, to be sure associated
diff --git a/test/motion_lid.c b/test/motion_lid.c
index d204ec4ab0..964bd9f026 100644
--- a/test/motion_lid.c
+++ b/test/motion_lid.c
@@ -24,7 +24,7 @@
* Period in us for the motion task period.
* The task will read the vectors at that interval
*/
-#define TEST_LID_EC_RATE (SUSPEND_SAMPLING_INTERVAL / 10)
+#define TEST_LID_EC_RATE (10)
/*
* Time in ms to wait for the task to read the vectors.
@@ -51,10 +51,9 @@ static int accel_set_range(const struct motion_sensor_t *s,
return EC_SUCCESS;
}
-static int accel_get_range(const struct motion_sensor_t *s,
- int * const range)
+static int accel_get_range(const struct motion_sensor_t *s)
{
- return EC_SUCCESS;
+ return 0;
}
static int accel_set_resolution(const struct motion_sensor_t *s,
@@ -64,23 +63,24 @@ static int accel_set_resolution(const struct motion_sensor_t *s,
return EC_SUCCESS;
}
-static int accel_get_resolution(const struct motion_sensor_t *s,
- int * const res)
+static int accel_get_resolution(const struct motion_sensor_t *s)
{
- return EC_SUCCESS;
+ return 0;
}
+int test_data_rate[2] = { 0 };
+
static int accel_set_data_rate(const struct motion_sensor_t *s,
const int rate,
const int rnd)
{
+ test_data_rate[s - motion_sensors] = rate | (rnd ? ROUND_UP_FLAG : 0);
return EC_SUCCESS;
}
-static int accel_get_data_rate(const struct motion_sensor_t *s,
- int * const rate)
+static int accel_get_data_rate(const struct motion_sensor_t *s)
{
- return EC_SUCCESS;
+ return test_data_rate[s - motion_sensors];
}
const struct accelgyro_drv test_motion_sense = {
@@ -117,11 +117,28 @@ struct motion_sensor_t motion_sensors[] = {
.drv_data = NULL,
.addr = 0,
.rot_standard_ref = &base_standard_ref,
- .default_config = {
- .odr = 119000,
- .range = 2,
- .ec_rate = SUSPEND_SAMPLING_INTERVAL,
- }
+ .default_range = 2, /* g, enough for laptop. */
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC use accel for angle detection */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 119000 | ROUND_UP_FLAG,
+ .ec_rate = TEST_LID_EC_RATE
+ },
+ /* Used for double tap */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 119000 | ROUND_UP_FLAG,
+ .ec_rate = TEST_LID_EC_RATE * 100,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ },
},
{.name = "lid",
.active_mask = SENSOR_ACTIVE_S0,
@@ -133,11 +150,28 @@ struct motion_sensor_t motion_sensors[] = {
.drv_data = NULL,
.addr = 0,
.rot_standard_ref = &lid_standard_ref,
- .default_config = {
- .odr = 119000,
- .range = 2,
- .ec_rate = SUSPEND_SAMPLING_INTERVAL,
- }
+ .default_range = 2, /* g, enough for laptop. */
+ .config = {
+ /* AP: by default shutdown all sensors */
+ [SENSOR_CONFIG_AP] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ /* EC use accel for angle detection */
+ [SENSOR_CONFIG_EC_S0] = {
+ .odr = 119000 | ROUND_UP_FLAG,
+ .ec_rate = TEST_LID_EC_RATE,
+ },
+ /* Used for double tap */
+ [SENSOR_CONFIG_EC_S3] = {
+ .odr = 119000 | ROUND_UP_FLAG,
+ .ec_rate = TEST_LID_EC_RATE * 100,
+ },
+ [SENSOR_CONFIG_EC_S5] = {
+ .odr = 0,
+ .ec_rate = 0,
+ },
+ },
},
};
const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
@@ -163,19 +197,16 @@ static int test_lid_angle(void)
struct motion_sensor_t *lid = &motion_sensors[1];
/* Go to S3 state */
- TEST_ASSERT(accel_interval == SUSPEND_SAMPLING_INTERVAL);
- TEST_ASSERT(motion_sensors[0].active == SENSOR_ACTIVE_S5);
+ TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S5);
+ TEST_ASSERT(accel_get_data_rate(lid) == 0);
+ TEST_ASSERT(accel_interval == 0);
/* Go to S0 state */
hook_notify(HOOK_CHIPSET_RESUME);
- TEST_ASSERT(accel_interval == SUSPEND_SAMPLING_INTERVAL);
- TEST_ASSERT(motion_sensors[0].active == SENSOR_ACTIVE_S0);
-
- motion_sense_set_accel_interval(base, TEST_LID_EC_RATE);
- TEST_ASSERT(accel_interval == TEST_LID_EC_RATE);
-
- motion_sense_set_accel_interval(lid, TEST_LID_EC_RATE);
- TEST_ASSERT(accel_interval == TEST_LID_EC_RATE);
+ msleep(1000);
+ TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S0);
+ TEST_ASSERT(accel_get_data_rate(lid) == (119000 | ROUND_UP_FLAG));
+ TEST_ASSERT(accel_interval == TEST_LID_EC_RATE * MSEC);
/*
* Set the base accelerometer as if it were sitting flat on a desk
@@ -191,7 +222,7 @@ static int test_lid_angle(void)
task_wake(TASK_ID_MOTIONSENSE);
/* wait for the EC sampling period to expire */
- msleep(TEST_LID_EC_RATE/MSEC);
+ msleep(TEST_LID_EC_RATE);
task_wake(TASK_ID_MOTIONSENSE);
wait_for_valid_sample();