summaryrefslogtreecommitdiff
path: root/driver/als_opt3001.c
diff options
context:
space:
mode:
authorVijay Hiremath <vijay.p.hiremath@intel.com>2015-07-15 13:58:25 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-07-21 01:34:27 +0000
commitcd0df39ba5a22f390b57cba584e6a919be5ae53b (patch)
treee3eeb13165aa6a3dd1558c6d32c0779b5869497c /driver/als_opt3001.c
parent26db470b39687b5abbbc8c5a5c8ac334a900fbae (diff)
downloadchrome-ec-cd0df39ba5a22f390b57cba584e6a919be5ae53b.tar.gz
Driver: OPT3001: Add TI OPT3001 light sensor driver
BUG=none BRANCH=none TEST=Added OPT3001 config to test the sensor in Kunimitsu. Able to read the als data from "als" console command. Varied the light intensity and the als reading are changing. Driver fits into the existing ALS framework. Change-Id: Idb2e6f9f50b6d0d6c8f64c11336efd3f2c76d498 Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com> Reviewed-on: https://chromium-review.googlesource.com/286782 Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'driver/als_opt3001.c')
-rw-r--r--driver/als_opt3001.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/driver/als_opt3001.c b/driver/als_opt3001.c
new file mode 100644
index 0000000000..c2c4cc2592
--- /dev/null
+++ b/driver/als_opt3001.c
@@ -0,0 +1,104 @@
+/* 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 "common.h"
+#include "console.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "timer.h"
+
+#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args)
+
+/**
+ * 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.
+ */
+static void opt3001_init(void)
+{
+ int data;
+ int ret;
+
+ ret = opt3001_i2c_read(OPT3001_REG_MAN_ID, &data);
+ if (ret || data != OPT3001_MANUFACTURER_ID) {
+ CPRINTF("ALS init failed: ret=%d, data=0x%x\n", ret, data);
+ return;
+ }
+
+ ret = opt3001_i2c_read(OPT3001_REG_DEV_ID, &data);
+ if (ret || data != OPT3001_DEVICE_ID) {
+ CPRINTF("ALS init failed: ret=%d, data=0x%x\n", ret, data);
+ return;
+ }
+
+ /*
+ * [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
+ */
+ ret = opt3001_i2c_write(OPT3001_REG_CONFIGURE, 0x5C10);
+ if (ret)
+ CPRINTF("ALS configure failed: ret=%d\n", ret);
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESUME, opt3001_init, HOOK_PRIO_DEFAULT);
+
+/**
+ * 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) {
+ CPRINTF("ALS read failed: ret=%d\n", 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;
+}