1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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;
}
|