| /* Copyright 2015 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. |
| * |
| * TI OPT3001 light sensor driver |
| */ |
| |
| #include "driver/als_opt3001.h" |
| #include "i2c.h" |
| |
| /** |
| * Read register from OPT3001 light sensor. |
| */ |
| static int opt3001_i2c_read(const int reg, int *data_ptr) |
| { |
| int ret; |
| |
| ret = i2c_read16(I2C_PORT_ALS, OPT3001_I2C_ADDR, reg, data_ptr); |
| if (!ret) |
| *data_ptr = ((*data_ptr << 8) & 0xFF00) | |
| ((*data_ptr >> 8) & 0x00FF); |
| |
| return ret; |
| } |
| |
| /** |
| * Write register to OPT3001 light sensor. |
| */ |
| static int opt3001_i2c_write(const int reg, int data) |
| { |
| int ret; |
| |
| data = ((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF); |
| ret = i2c_write16(I2C_PORT_ALS, OPT3001_I2C_ADDR, reg, data); |
| |
| return ret; |
| } |
| |
| /** |
| * Initialise OPT3001 light sensor. |
| */ |
| int opt3001_init(void) |
| { |
| int data; |
| int ret; |
| |
| ret = opt3001_i2c_read(OPT3001_REG_MAN_ID, &data); |
| if (ret || data != OPT3001_MANUFACTURER_ID) |
| return ret; |
| |
| ret = opt3001_i2c_read(OPT3001_REG_DEV_ID, &data); |
| if (ret || data != OPT3001_DEVICE_ID) |
| return ret; |
| |
| /* |
| * [15:12]: 0101b Automatic full scale (1310.40lux, 0.32lux/lsb) |
| * [11] : 1b Conversion time 800ms |
| * [10:9] : 10b Continuous Mode of conversion operation |
| * [4] : 1b Latched window-style comparison operation |
| */ |
| return opt3001_i2c_write(OPT3001_REG_CONFIGURE, 0x5C10); |
| } |
| |
| /** |
| * Read OPT3001 light sensor data. |
| */ |
| int opt3001_read_lux(int *lux, int af) |
| { |
| int ret; |
| int data; |
| |
| ret = opt3001_i2c_read(OPT3001_REG_RESULT, &data); |
| if (ret) |
| return ret; |
| |
| /* |
| * The default power-on values will give 12 bits of precision: |
| * 0x0000-0x0fff indicates 0 to 1310.40 lux. We multiply the sensor |
| * value by a scaling factor to account for attenuation by glass, |
| * tinting, etc. |
| */ |
| |
| /* |
| * lux = 2EXP[3:0] × R[11:0] / 100 |
| */ |
| *lux = (1 << ((data & 0xF000) >> 12)) * (data & 0x0FFF) * af / 100; |
| |
| return EC_SUCCESS; |
| } |