diff options
Diffstat (limited to 'board/terrador/sensors.c')
-rw-r--r-- | board/terrador/sensors.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/board/terrador/sensors.c b/board/terrador/sensors.c new file mode 100644 index 0000000000..1d192d4289 --- /dev/null +++ b/board/terrador/sensors.c @@ -0,0 +1,255 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Volteer family-specific sensor configuration */ +#include "common.h" +#include "accelgyro.h" +#include "driver/accel_bma2x2.h" +#include "driver/accelgyro_bmi_common.h" +#include "driver/accelgyro_bmi260.h" +#include "driver/als_tcs3400.h" +#include "driver/sync.h" +#include "keyboard_scan.h" +#include "hooks.h" +#include "i2c.h" +#include "task.h" +#include "tablet_mode.h" +#include "util.h" + +/******************************************************************************/ +/* Sensors */ +static struct mutex g_lid_accel_mutex; +static struct mutex g_base_mutex; + +/* BMA253 private data */ +static struct accelgyro_saved_data_t g_bma253_data; + +/* BMI260 private data */ +static struct bmi_drv_data_t g_bmi260_data; + +/* TCS3400 private data */ +static struct als_drv_data_t g_tcs3400_data = { + .als_cal.scale = 1, + .als_cal.uscale = 0, + .als_cal.offset = 0, + .als_cal.channel_scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kc from VPD */ + .cover_scale = ALS_CHANNEL_SCALE(1.0), /* CT */ + }, +}; + +/* + * TODO: b/146166425 need to calibrate ALS/RGB sensor. At default settings, + * shining phone flashlight on sensor pegs all readings at 0xFFFF. + */ +static struct tcs3400_rgb_drv_data_t g_tcs3400_rgb_data = { + .calibration.rgb_cal[X] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kr */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + } + }, + .calibration.rgb_cal[Y] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kg */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + }, + }, + .calibration.rgb_cal[Z] = { + .offset = 0, + .coeff[TCS_RED_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_GREEN_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_BLUE_COEFF_IDX] = FLOAT_TO_FP(0), + .coeff[TCS_CLEAR_COEFF_IDX] = FLOAT_TO_FP(0), + .scale = { + .k_channel_scale = ALS_CHANNEL_SCALE(1.0), /* kb */ + .cover_scale = ALS_CHANNEL_SCALE(1.0) + } + }, + .calibration.irt = INT_TO_FP(1), + .saturation.again = TCS_DEFAULT_AGAIN, + .saturation.atime = TCS_DEFAULT_ATIME, +}; + +/* Rotation matrix for the lid accelerometer */ +static const mat33_fp_t lid_standard_ref = { + { FLOAT_TO_FP(1), 0, 0}, + { 0, FLOAT_TO_FP(-1), 0}, + { 0, 0, FLOAT_TO_FP(-1)} +}; + +const mat33_fp_t base_standard_ref = { + { 0, FLOAT_TO_FP(1), 0}, + { FLOAT_TO_FP(-1), 0, 0}, + { 0, 0, FLOAT_TO_FP(1)} +}; + +struct motion_sensor_t motion_sensors[] = { + [LID_ACCEL] = { + .name = "Lid Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMA255, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_LID, + .drv = &bma2x2_accel_drv, + .mutex = &g_lid_accel_mutex, + .drv_data = &g_bma253_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMA2x2_I2C_ADDR1_FLAGS, + .rot_standard_ref = &lid_standard_ref, + .min_frequency = BMA255_ACCEL_MIN_FREQ, + .max_frequency = BMA255_ACCEL_MAX_FREQ, + .default_range = 2, /* g, to support tablet mode */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + }, + }, + }, + [BASE_ACCEL] = { + .name = "Base Accel", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_ACCEL, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_ACCEL_MIN_FREQ, + .max_frequency = BMI_ACCEL_MAX_FREQ, + .default_range = 4, /* g */ + .config = { + /* EC use accel for angle detection */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + /* Sensor on in S3 */ + [SENSOR_CONFIG_EC_S3] = { + .odr = 10000 | ROUND_UP_FLAG, + .ec_rate = 100 * MSEC, + }, + }, + }, + + [BASE_GYRO] = { + .name = "Base Gyro", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_BMI260, + .type = MOTIONSENSE_TYPE_GYRO, + .location = MOTIONSENSE_LOC_BASE, + .drv = &bmi260_drv, + .mutex = &g_base_mutex, + .drv_data = &g_bmi260_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = BMI260_ADDR0_FLAGS, + .default_range = 1000, /* dps */ + .rot_standard_ref = &base_standard_ref, + .min_frequency = BMI_GYRO_MIN_FREQ, + .max_frequency = BMI_GYRO_MAX_FREQ, + }, + [CLEAR_ALS] = { + .name = "Clear Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT, + .location = MOTIONSENSE_LOC_BASE, + .drv = &tcs3400_drv, + .drv_data = &g_tcs3400_data, + .port = I2C_PORT_SENSOR, + .i2c_spi_addr_flags = TCS3400_I2C_ADDR_FLAGS, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + .min_frequency = TCS3400_LIGHT_MIN_FREQ, + .max_frequency = TCS3400_LIGHT_MAX_FREQ, + .config = { + /* Run ALS sensor in S0 */ + [SENSOR_CONFIG_EC_S0] = { + .odr = 1000, + }, + }, + }, + + [RGB_ALS] = { + /* + * RGB channels read by CLEAR_ALS and so the i2c port and + * address do not need to be defined for RGB_ALS. + */ + .name = "RGB Light", + .active_mask = SENSOR_ACTIVE_S0_S3, + .chip = MOTIONSENSE_CHIP_TCS3400, + .type = MOTIONSENSE_TYPE_LIGHT_RGB, + .location = MOTIONSENSE_LOC_BASE, + .drv = &tcs3400_rgb_drv, + .drv_data = &g_tcs3400_rgb_data, + .rot_standard_ref = NULL, + .default_range = 0x10000, /* scale = 1x, uscale = 0 */ + }, + + [VSYNC] = { + .name = "Camera VSYNC", + .active_mask = SENSOR_ACTIVE_S0, + .chip = MOTIONSENSE_CHIP_GPIO, + .type = MOTIONSENSE_TYPE_SYNC, + .location = MOTIONSENSE_LOC_CAMERA, + .drv = &sync_drv, + .default_range = 0, + .min_frequency = 0, + .max_frequency = 1, + }, +}; +unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors); + +/* ALS instances when LPC mapping is needed. Each entry directs to a sensor. */ +const struct motion_sensor_t *motion_als_sensors[] = { + &motion_sensors[CLEAR_ALS], +}; +BUILD_ASSERT(ARRAY_SIZE(motion_als_sensors) == ALS_COUNT); + +static void baseboard_sensors_init(void) +{ + /* Note - BMA253 interrupt unused by EC */ + + /* Enable gpio interrupt for camera vsync */ + gpio_enable_interrupt(GPIO_EC_CAM_VSYN_SLP_S0IX); + /* Enable interrupt for the TCS3400 color light sensor */ + gpio_enable_interrupt(GPIO_EC_ALS_RGB_INT_L); + /* Enable interrupt for the BMI260 accel/gyro sensor */ + gpio_enable_interrupt(GPIO_EC_IMU_INT_L); +} +DECLARE_HOOK(HOOK_INIT, baseboard_sensors_init, HOOK_PRIO_DEFAULT); + +#ifndef TEST_BUILD +void lid_angle_peripheral_enable(int enable) +{ + /* + * If the lid is in tablet position via other sensors, + * ignore the lid angle, which might be faulty then + * disable keyboard. + */ + if (tablet_get_mode()) + enable = 0; + + keyboard_scan_enable(enable, KB_SCAN_DISABLE_LID_ANGLE); +} +#endif |