diff options
Diffstat (limited to 'driver/als_tcs3400.c')
-rw-r--r-- | driver/als_tcs3400.c | 164 |
1 files changed, 162 insertions, 2 deletions
diff --git a/driver/als_tcs3400.c b/driver/als_tcs3400.c index f63b7156ae..e821b6bb9c 100644 --- a/driver/als_tcs3400.c +++ b/driver/als_tcs3400.c @@ -58,15 +58,28 @@ static int tcs3400_read(const struct motion_sensor_t *s, intv3_t v) return ret; } +static int tcs3400_rgb_read(const struct motion_sensor_t *s, intv3_t v) +{ + return EC_SUCCESS; +} + static int tcs3400_post_events(struct motion_sensor_t *s, uint32_t last_ts) { + /* + * Rule says RGB sensor is right after ALS sensor, and this + * routine will only get called from ALS sensor driver. + */ + struct motion_sensor_t *rgb_s = s + 1; struct tcs3400_drv_data_t *drv_data = TCS3400_DRV_DATA(s); + struct tcs3400_rgb_drv_data_t *rgb_drv_data = + TCS3400_RGB_DRV_DATA(rgb_s); struct ec_response_motion_sensor_data vector; uint8_t light_data[TCS_RGBC_DATA_SIZE]; int *v = s->raw_xyz; int retries = 20; /* 400 ms max */ + int rgb_data[3]; int data = 0; - int ret; + int i, ret; /* Make sure data is valid */ do { @@ -94,6 +107,7 @@ static int tcs3400_post_events(struct motion_sensor_t *s, uint32_t last_ts) data = data * drv_data->als_cal.scale + data * drv_data->als_cal.uscale / 10000; + /* Correct negative values to zero */ if (data < 0) { CPRINTS("Negative clear val 0x%x set to 0", data); data = 0; @@ -124,6 +138,63 @@ skip_clear_vector_load: #endif } +#ifdef CONFIG_ACCEL_SPOOF_MODE + if (s->in_spoof_mode) { + rgb_data[X] = s->spoof_xyz[X]; + rgb_data[Y] = s->spoof_xyz[Y]; + rgb_data[Z] = s->spoof_xyz[Z]; + goto skip_rgb_load; + } +#endif + + for (i = 0; i < 3; i++) { + /* rgb data at indicies 2 thru 7 inclusive in light_data */ + int index = 3 + (i * 2); + + rgb_data[i] = ((light_data[index] << 8) | light_data[index-1]); + rgb_data[i] += rgb_drv_data->rgb_cal[i].offset; + rgb_data[i] *= rgb_drv_data->rgb_cal[i].scale / BIT(15); + rgb_data[i] = rgb_data[i] * rgb_drv_data->device_scale + + rgb_data[i] * rgb_drv_data->device_uscale / 10000; + + /* Correct any negative values to zero */ + if (rgb_data[i] < 0) { + CPRINTS("Negative rgb channel #%d val 0x%x set to 0", + i, rgb_data[i]); + rgb_data[i] = 0; + } + } + +#ifdef CONFIG_ACCEL_SPOOF_MODE +skip_rgb_load: +#endif + /* If anything changed, transfer RGB data */ + if ((rgb_drv_data->last_value[X] != rgb_data[X]) || + (rgb_drv_data->last_value[Y] != rgb_data[Y]) || + (rgb_drv_data->last_value[Z] != rgb_data[Z])) { + for (i = 0; i < 3; i++) + rgb_drv_data->last_value[i] = rgb_data[i]; + v = rgb_s->raw_xyz; + vector.flags = 0; +#ifdef CONFIG_ACCEL_SPOOF_MODE + if (rgb_s->in_spoof_mode) { + for (i = 0; i < 3; i++) + vector.data[i] = v[i] = rgb_s->spoof_xyz[i]; + goto skip_vector_load; + } +#endif /* defined(CONFIG_ACCEL_SPOOF_MODE) */ + + vector.data[X] = v[X] = rgb_data[X]; + vector.data[Y] = v[Y] = rgb_data[Y]; + vector.data[Z] = v[Z] = rgb_data[Z]; + +#ifdef CONFIG_ACCEL_SPOOF_MODE +skip_vector_load: +#endif + vector.sensor_num = rgb_s - motion_sensors; + motion_sense_fifo_add_data(&vector, rgb_s, 3, last_ts); + } + return EC_SUCCESS; } @@ -136,7 +207,7 @@ void tcs3400_interrupt(enum gpio_signal signal) CONFIG_ALS_TCS3400_INT_EVENT, 0); } -/** +/* * tcs3400_irq_handler - bottom half of the interrupt stack. * Ran from the motion_sense task, finds the events that raised the interrupt, * and posts those events via motion_sense_fifo_add_data().. @@ -175,6 +246,77 @@ static int tcs3400_irq_handler(struct motion_sensor_t *s, uint32_t *event) return ret; } +static int tcs3400_rgb_get_range(const struct motion_sensor_t *s) +{ + /* Currently, calibration info is same for all channels */ + return (TCS3400_RGB_DRV_DATA(s)->device_scale << 16) | + TCS3400_RGB_DRV_DATA(s)->device_uscale; +} + +static int tcs3400_rgb_set_range(const struct motion_sensor_t *s, + int range, + int rnd) +{ + TCS3400_RGB_DRV_DATA(s)->device_scale = range >> 16; + TCS3400_RGB_DRV_DATA(s)->device_uscale = range & 0xffff; + return EC_SUCCESS; +} + +static int tcs3400_rgb_get_scale(const struct motion_sensor_t *s, + uint16_t *scale, + int16_t *temp) +{ + scale[X] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[X].scale; + scale[Y] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[Y].scale; + scale[Z] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[Z].scale; + *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; + return EC_SUCCESS; +} + +static int tcs3400_rgb_set_scale(const struct motion_sensor_t *s, + const uint16_t *scale, + int16_t temp) +{ + TCS3400_RGB_DRV_DATA(s)->rgb_cal[X].scale = scale[X]; + TCS3400_RGB_DRV_DATA(s)->rgb_cal[Y].scale = scale[Y]; + TCS3400_RGB_DRV_DATA(s)->rgb_cal[Z].scale = scale[Z]; + return EC_SUCCESS; +} + +static int tcs3400_rgb_get_offset(const struct motion_sensor_t *s, + int16_t *offset, + int16_t *temp) +{ + offset[X] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[X].offset; + offset[Y] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[Y].offset; + offset[Z] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[Z].offset; + *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; + return EC_SUCCESS; +} + +static int tcs3400_rgb_set_offset(const struct motion_sensor_t *s, + const int16_t *offset, + int16_t temp) +{ + TCS3400_RGB_DRV_DATA(s)->rgb_cal[X].offset = offset[X]; + TCS3400_RGB_DRV_DATA(s)->rgb_cal[Y].offset = offset[Y]; + TCS3400_RGB_DRV_DATA(s)->rgb_cal[Z].offset = offset[Z]; + return EC_SUCCESS; +} + +static int tcs3400_rgb_get_data_rate(const struct motion_sensor_t *s) +{ + return TCS3400_RGB_DRV_DATA(s)->rate; +} + +static int tcs3400_rgb_set_data_rate(const struct motion_sensor_t *s, + int rate, + int rnd) +{ + TCS3400_RGB_DRV_DATA(s)->rate = rate; + return EC_SUCCESS; +} + static int tcs3400_get_range(const struct motion_sensor_t *s) { return (TCS3400_DRV_DATA(s)->als_cal.scale << 16) | @@ -250,6 +392,11 @@ static int tcs3400_set_data_rate(const struct motion_sensor_t *s, /** * Initialise TCS3400 light sensor. */ +static int tcs3400_rgb_init(const struct motion_sensor_t *s) +{ + return sensor_init_done(s); +} + static int tcs3400_init(const struct motion_sensor_t *s) { /* @@ -310,3 +457,16 @@ const struct accelgyro_drv tcs3400_drv = { .irq_handler = tcs3400_irq_handler, #endif }; + +const struct accelgyro_drv tcs3400_rgb_drv = { + .init = tcs3400_rgb_init, + .read = tcs3400_rgb_read, + .set_range = tcs3400_rgb_set_range, + .get_range = tcs3400_rgb_get_range, + .set_offset = tcs3400_rgb_set_offset, + .get_offset = tcs3400_rgb_get_offset, + .set_scale = tcs3400_rgb_set_scale, + .get_scale = tcs3400_rgb_get_scale, + .set_data_rate = tcs3400_rgb_set_data_rate, + .get_data_rate = tcs3400_rgb_get_data_rate, +}; |