mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 18:41:11 +00:00
motion_sense: Fix init routines
active state is global, remove it from motion_sensor structure. Reinit sensors when entering RW, fix regression introduced by CL:284616. Improve EC polling rate calculation by excluding suspended sensors. Wake up sensor thread in case the motion task was in deep sleep. Do not send sense interrupt while suspened. Will revisit once wakeup sensors are implemented. BRANCH=smaug TEST=Check when in RW the sensors are exposed. Check EC rate are correct in different power state. Check when jumping from RO to RW and back, after setting the frequencies parameters via sysfs properly, AndroSensor acquires the data properly. BUG=chrome-os-partner:43132,chrome-os-partner:40741 Change-Id: Ie70732b135a432d64935eead4200ddc0e1a7c0b4 Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/288201 Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
324a2716d4
commit
34677eed4e
@@ -286,7 +286,11 @@ DECLARE_HOOK(HOOK_CHIPSET_RESUME, gesture_chipset_resume,
|
||||
|
||||
static void gesture_chipset_suspend(void)
|
||||
{
|
||||
/* Set ODR to desired value */
|
||||
/*
|
||||
* Set ODR to desired value
|
||||
* We assume EC rate set correctly: it works because the sensor used
|
||||
* is never offlined/suspened.
|
||||
*/
|
||||
sensor->drv->set_data_rate(sensor, TAP_ODR, 1);
|
||||
|
||||
/*
|
||||
|
||||
@@ -40,10 +40,12 @@ static int accel_disp;
|
||||
#endif
|
||||
|
||||
#define SENSOR_EC_RATE(_sensor) \
|
||||
((_sensor)->active == SENSOR_ACTIVE_S0 ? \
|
||||
(sensor_active == SENSOR_ACTIVE_S0 ? \
|
||||
(_sensor)->runtime_config.ec_rate : \
|
||||
(_sensor)->default_config.ec_rate)
|
||||
|
||||
#define SENSOR_ACTIVE(_sensor) (sensor_active & (_sensor)->active_mask)
|
||||
|
||||
/* Minimal amount of time since last collection before triggering a new one */
|
||||
#define SENSOR_EC_RATE_THRES(_sensor) \
|
||||
(SENSOR_EC_RATE(_sensor) * 9 / 10)
|
||||
@@ -56,6 +58,11 @@ static int accel_disp;
|
||||
*/
|
||||
static struct mutex g_sensor_mutex;
|
||||
|
||||
/*
|
||||
* Current power level (S0, S3, S5, ...)
|
||||
*/
|
||||
enum chipset_state_mask sensor_active;
|
||||
|
||||
#ifdef CONFIG_ACCEL_FIFO
|
||||
struct queue motion_sense_fifo = QUEUE_NULL(CONFIG_ACCEL_FIFO,
|
||||
struct ec_response_motion_sensor_data);
|
||||
@@ -116,6 +123,7 @@ static void motion_sense_get_fifo_info(
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@@ -132,73 +140,99 @@ int motion_sense_set_accel_interval(
|
||||
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))
|
||||
continue;
|
||||
|
||||
if (SENSOR_EC_RATE(sensor) < data)
|
||||
data = SENSOR_EC_RATE(sensor);
|
||||
}
|
||||
accel_interval = data;
|
||||
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.
|
||||
*/
|
||||
task_wake(TASK_ID_MOTIONSENSE);
|
||||
} else {
|
||||
accel_interval = data;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void motion_sense_startup(void)
|
||||
static inline void motion_sense_init(struct motion_sensor_t *sensor)
|
||||
{
|
||||
int ret, cnt = 3;
|
||||
|
||||
/* Initialize accelerometers. */
|
||||
do {
|
||||
ret = sensor->drv->init(sensor);
|
||||
} while ((ret != EC_SUCCESS) && (--cnt > 0));
|
||||
|
||||
if (ret != EC_SUCCESS) {
|
||||
sensor->state = SENSOR_INIT_ERROR;
|
||||
} else {
|
||||
timestamp_t ts = get_time();
|
||||
sensor->state = SENSOR_INITIALIZED;
|
||||
sensor->last_collection = ts.val;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* motion_sense_switch_unused_sensor
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
int i;
|
||||
struct motion_sensor_t *sensor;
|
||||
for (i = 0; i < motion_sensor_count; ++i) {
|
||||
sensor = &motion_sensors[i];
|
||||
sensor->state = SENSOR_NOT_INITIALIZED;
|
||||
sensor->active = SENSOR_ACTIVE_S5;
|
||||
|
||||
memcpy(&sensor->runtime_config, &sensor->default_config,
|
||||
sizeof(sensor->runtime_config));
|
||||
if ((sensor->state == SENSOR_INITIALIZED) &&
|
||||
!SENSOR_ACTIVE(sensor)) {
|
||||
sensor->drv->set_data_rate(sensor, 0, 0);
|
||||
sensor->state = SENSOR_NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, motion_sense_startup,
|
||||
MOTION_SENSE_HOOK_PRIO);
|
||||
|
||||
static void motion_sense_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
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];
|
||||
sensor->active = SENSOR_ACTIVE_S5;
|
||||
/* Forget about changes made by the AP */
|
||||
memcpy(&sensor->runtime_config, &sensor->default_config,
|
||||
sizeof(sensor->runtime_config));
|
||||
if ((sensor->state == SENSOR_INITIALIZED) &&
|
||||
!(sensor->active_mask & sensor->active)) {
|
||||
sensor->drv->set_data_rate(sensor, 0, 0);
|
||||
sensor->state = SENSOR_NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, motion_sense_shutdown,
|
||||
MOTION_SENSE_HOOK_PRIO);
|
||||
|
||||
static void motion_sense_suspend(void)
|
||||
{
|
||||
int i;
|
||||
struct motion_sensor_t *sensor;
|
||||
/*
|
||||
* If we are comming from S5, don't enter suspend:
|
||||
* We will go in SO almost immediately.
|
||||
*/
|
||||
if (sensor_active == SENSOR_ACTIVE_S5)
|
||||
return;
|
||||
|
||||
for (i = 0; i < motion_sensor_count; i++) {
|
||||
sensor = &motion_sensors[i];
|
||||
|
||||
/* if we are comming from S5, don't enter suspend */
|
||||
if (sensor->active == SENSOR_ACTIVE_S5)
|
||||
return;
|
||||
|
||||
sensor->active = SENSOR_ACTIVE_S3;
|
||||
|
||||
/* Saving power if the sensor is not active in S3 */
|
||||
if ((sensor->state == SENSOR_INITIALIZED) &&
|
||||
!(sensor->active_mask & sensor->active)) {
|
||||
sensor->drv->set_data_rate(sensor, 0, 0);
|
||||
sensor->state = SENSOR_NOT_INITIALIZED;
|
||||
}
|
||||
}
|
||||
motion_sense_set_accel_interval(NULL, MAX_MOTION_SENSE_WAIT_TIME);
|
||||
sensor_active = SENSOR_ACTIVE_S3;
|
||||
motion_sense_switch_unused_sensor();
|
||||
}
|
||||
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, motion_sense_suspend,
|
||||
MOTION_SENSE_HOOK_PRIO);
|
||||
@@ -208,20 +242,48 @@ 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];
|
||||
sensor->active = SENSOR_ACTIVE_S0;
|
||||
if (sensor->state == SENSOR_INITIALIZED) {
|
||||
/* Put back the odr previously set. */
|
||||
/* 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);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_CHIPSET_RESUME, motion_sense_resume,
|
||||
MOTION_SENSE_HOOK_PRIO);
|
||||
|
||||
static void motion_sense_startup(void)
|
||||
{
|
||||
int i;
|
||||
struct motion_sensor_t *sensor;
|
||||
|
||||
sensor_active = SENSOR_ACTIVE_S5;
|
||||
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),
|
||||
* but it may be necessary if the init sequence has changed.
|
||||
*/
|
||||
if (chipset_in_state(SENSOR_ACTIVE_S0_S3))
|
||||
motion_sense_suspend();
|
||||
if (chipset_in_state(SENSOR_ACTIVE_S0))
|
||||
motion_sense_resume();
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, motion_sense_startup,
|
||||
MOTION_SENSE_HOOK_PRIO);
|
||||
|
||||
/* Write to LPC status byte to represent that accelerometers are present. */
|
||||
static inline void set_present(uint8_t *lpc_status)
|
||||
{
|
||||
@@ -272,24 +334,6 @@ static inline void update_sense_data(uint8_t *lpc_status,
|
||||
*lpc_status = EC_MEMMAP_ACC_STATUS_PRESENCE_BIT | *psample_id;
|
||||
}
|
||||
|
||||
static inline void motion_sense_init(struct motion_sensor_t *sensor)
|
||||
{
|
||||
int ret, cnt = 3;
|
||||
|
||||
/* Initialize accelerometers. */
|
||||
do {
|
||||
ret = sensor->drv->init(sensor);
|
||||
} while ((ret != EC_SUCCESS) && (--cnt > 0));
|
||||
|
||||
if (ret != EC_SUCCESS) {
|
||||
sensor->state = SENSOR_INIT_ERROR;
|
||||
} else {
|
||||
timestamp_t ts = get_time();
|
||||
sensor->state = SENSOR_INITIALIZED;
|
||||
sensor->last_collection = ts.val;
|
||||
}
|
||||
}
|
||||
|
||||
static int motion_sense_read(struct motion_sensor_t *sensor)
|
||||
{
|
||||
if (sensor->state != SENSOR_INITIALIZED)
|
||||
@@ -374,7 +418,6 @@ void motion_sense_task(void)
|
||||
lpc_data = (uint16_t *)host_get_memmap(EC_MEMMAP_ACC_DATA);
|
||||
set_present(lpc_status);
|
||||
|
||||
wait_us = accel_interval;
|
||||
#ifdef CONFIG_ACCEL_FIFO
|
||||
ts_last_int = get_time();
|
||||
#endif
|
||||
@@ -386,9 +429,13 @@ void motion_sense_task(void)
|
||||
sensor = &motion_sensors[i];
|
||||
|
||||
/* if the sensor is active in the current power state */
|
||||
if (sensor->active & sensor->active_mask) {
|
||||
if (sensor->state == SENSOR_NOT_INITIALIZED)
|
||||
motion_sense_init(sensor);
|
||||
if (SENSOR_ACTIVE(sensor) &&
|
||||
(sensor->runtime_config.odr != 0)) {
|
||||
if (sensor->state != SENSOR_INITIALIZED) {
|
||||
CPRINTS("S%d active, not initalized",
|
||||
sensor);
|
||||
continue;
|
||||
}
|
||||
|
||||
ts_begin_task = get_time();
|
||||
ret = motion_sense_process(sensor, event,
|
||||
@@ -459,7 +506,13 @@ void motion_sense_task(void)
|
||||
fifo_flush_needed = 0;
|
||||
ts_last_int = ts_end_task;
|
||||
#ifdef CONFIG_MKBP_EVENT
|
||||
mkbp_send_event(EC_MKBP_EVENT_SENSOR_FIFO);
|
||||
/*
|
||||
* We don't currently support wake up sensor.
|
||||
* When we do, add per sensor test to know
|
||||
* when sending the event.
|
||||
*/
|
||||
if (sensor_active == SENSOR_ACTIVE_S0)
|
||||
mkbp_send_event(EC_MKBP_EVENT_SENSOR_FIFO);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -502,9 +555,8 @@ static struct motion_sensor_t
|
||||
sensor = &motion_sensors[host_id];
|
||||
|
||||
/* if sensor is powered and initialized, return match */
|
||||
if ((sensor->active & sensor->active_mask)
|
||||
&& (sensor->state == SENSOR_INITIALIZED))
|
||||
return sensor;
|
||||
if (SENSOR_ACTIVE(sensor) && (sensor->state == SENSOR_INITIALIZED))
|
||||
return sensor;
|
||||
|
||||
/* If no match then the EC currently doesn't support ID received. */
|
||||
return NULL;
|
||||
@@ -626,6 +678,12 @@ static int host_cmd_motion_sense(struct host_cmd_handler_args *args)
|
||||
out->sensor_odr.ret = data;
|
||||
|
||||
args->response_size = sizeof(out->sensor_odr);
|
||||
|
||||
/* If the sensor was suspended before, or now suspended, we have
|
||||
* to recalculate the EC sampling rate */
|
||||
motion_sense_set_accel_interval(
|
||||
NULL, MAX_MOTION_SENSE_WAIT_TIME);
|
||||
|
||||
break;
|
||||
|
||||
case MOTIONSENSE_CMD_SENSOR_RANGE:
|
||||
@@ -893,9 +951,15 @@ static int command_accel_data_rate(int argc, char **argv)
|
||||
if (sensor->drv->set_data_rate(sensor, data, round)
|
||||
== EC_ERROR_INVAL)
|
||||
return EC_ERROR_PARAM2;
|
||||
sensor->runtime_config.odr = data;
|
||||
motion_sense_set_accel_interval(
|
||||
NULL, MAX_MOTION_SENSE_WAIT_TIME);
|
||||
} else {
|
||||
sensor->drv->get_data_rate(sensor, &data);
|
||||
ccprintf("Data rate for sensor %d: %d\n", id, data);
|
||||
ccprintf("EC rate for sensor %d: %d\n", id,
|
||||
SENSOR_EC_RATE(sensor));
|
||||
ccprintf("Current EC rate: %d\n", accel_interval);
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
@@ -996,6 +1060,8 @@ static int command_display_accel_info(int argc, char **argv)
|
||||
return EC_ERROR_PARAM2;
|
||||
|
||||
accel_interval = val * MSEC;
|
||||
task_wake(TASK_ID_MOTIONSENSE);
|
||||
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
|
||||
@@ -80,7 +80,6 @@ struct motion_sensor_t {
|
||||
|
||||
/* state parameters */
|
||||
enum sensor_state state;
|
||||
enum chipset_state_mask active;
|
||||
vector_3_t raw_xyz;
|
||||
vector_3_t xyz;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user