1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "als_bh1745.h"
10 #include <securec.h>
11 #include "osal_mem.h"
12 #include "osal_time.h"
13 #include "sensor_als_driver.h"
14 #include "sensor_config_controller.h"
15 #include "sensor_device_manager.h"
16
17 #define HDF_LOG_TAG hdf_sensor_als
18
19 /* IO config for int-pin and I2C-pin */
20 #define SENSOR_I2C6_DATA_REG_ADDR 0x114f004c
21 #define SENSOR_I2C6_CLK_REG_ADDR 0x114f0048
22 #define SENSOR_I2C_REG_CFG 0x403
23 #define SENSOR_TIME_INCREASE 0
24 #define SENSOR_TIME_DECREASE 1
25
26 static struct Bh1745DrvData *g_bh1745DrvData = NULL;
27 static uint32_t g_timeChangeStatus = SENSOR_TIME_DECREASE;
28
29 static struct TimeRegAddrValueMap g_timeMap[EXTENDED_ALS_TIME_GROUP_INDEX_MAX] = {
30 { EXTENDED_ALS_TIME_GROUP_ATTR_VALUE_0, BH1745_TIME_160MSEC },
31 { EXTENDED_ALS_TIME_GROUP_ATTR_VALUE_1, BH1745_TIME_320MSEC },
32 { EXTENDED_ALS_TIME_GROUP_ATTR_VALUE_2, BH1745_TIME_640MSEC },
33 { EXTENDED_ALS_TIME_GROUP_ATTR_VALUE_3, BH1745_TIME_1280MSEC },
34 { EXTENDED_ALS_TIME_GROUP_ATTR_VALUE_4, BH1745_TIME_2560MSEC },
35 { EXTENDED_ALS_TIME_GROUP_ATTR_VALUE_5, BH1745_TIME_5120MSEC }
36 };
37
38 static struct GainRegAddrValueMap g_gainMap[EXTENDED_ALS_GAIN_GROUP_INDEX_MAX] = {
39 { EXTENDED_ALS_GAIN_GROUP_ATTR_VALUE_0, BH1745_GAIN_1X },
40 { EXTENDED_ALS_GAIN_GROUP_ATTR_VALUE_1, BH1745_GAIN_2X },
41 { EXTENDED_ALS_GAIN_GROUP_ATTR_VALUE_2, BH1745_GAIN_16X }
42 };
43
44 static uint32_t g_red[BH1745_COEFFICIENT_RED] = {
45 BH1745_COEFFICIENT_RED_LEVEL_0,
46 BH1745_COEFFICIENT_RED_LEVEL_1
47 };
48
49 static uint32_t g_green[BH1745_COEFFICIENT_GREEN] = {
50 BH1745_COEFFICIENT_GREEN_LEVEL_0,
51 BH1745_COEFFICIENT_GREEN_LEVEL_1
52 };
53
Bh1745GetDrvData(void)54 struct Bh1745DrvData *Bh1745GetDrvData(void)
55 {
56 return g_bh1745DrvData;
57 }
58
DynamicRangCovert(struct SensorCfgData * CfgData,uint32_t * rgbcData)59 static int32_t DynamicRangCovert(struct SensorCfgData *CfgData, uint32_t *rgbcData)
60 {
61 int32_t ret;
62 uint8_t regValue;
63 uint32_t temp;
64 uint8_t timeItemNum;
65 struct SensorRegCfgGroupNode *timeGroupNode = NULL;
66 int32_t index = EXTENDED_ALS_TIME_GROUP_INDEX_0;
67
68 timeGroupNode = CfgData->extendedRegCfgGroup[EXTENDED_ALS_TIME_GROUP];
69 timeItemNum = timeGroupNode->itemNum;
70 if (timeItemNum > EXTENDED_ALS_TIME_GROUP_INDEX_MAX) {
71 HDF_LOGE("%s: TimeItemNum out of range ", __func__);
72 return HDF_FAILURE;
73 }
74
75 ret = ReadSensorRegCfgArray(&CfgData->busCfg, timeGroupNode, index, ®Value, sizeof(regValue));
76 if (ret != HDF_SUCCESS) {
77 HDF_LOGE("%s: Failed to read sensor register array ", __func__);
78 return HDF_FAILURE;
79 }
80 regValue &= timeGroupNode->regCfgItem->mask;
81
82 temp = GetTimeByRegValue(regValue, g_timeMap, timeItemNum);
83 index = GetRegGroupIndexByTime(temp, g_timeMap, timeItemNum);
84 if (index < 0) {
85 HDF_LOGE("%s: Index out of range ", __func__);
86 return HDF_FAILURE;
87 }
88
89 if (((rgbcData[ALS_R] * BH1745_MULTIPLE_100 > BH1745_TIME_MAX) ||
90 (rgbcData[ALS_G] * BH1745_MULTIPLE_100 > BH1745_TIME_MAX)) && (temp >= BH1745_TIME_320MSEC)) {
91 g_timeChangeStatus = SENSOR_TIME_DECREASE;
92 index = GetRegGroupIndexByTime(temp, g_timeMap, timeItemNum);
93 index--;
94
95 ret = WriteSensorRegCfgArray(&CfgData->busCfg, timeGroupNode, index, sizeof(regValue));
96 if (ret != HDF_SUCCESS) {
97 HDF_LOGE("%s: Failed to write sensor register array ", __func__);
98 return HDF_FAILURE;
99 }
100 } else if (((rgbcData[ALS_R] * BH1745_MULTIPLE_100 < BH1745_TIME_MIN) ||
101 (rgbcData[ALS_G] * BH1745_MULTIPLE_100 < BH1745_TIME_MIN)) && (g_timeChangeStatus == SENSOR_TIME_DECREASE)) {
102 g_timeChangeStatus = SENSOR_TIME_INCREASE;
103 index = GetRegGroupIndexByTime(temp, g_timeMap, timeItemNum);
104 index++;
105 if (index >= timeItemNum) {
106 HDF_LOGE("%s: Index out of range ", __func__);
107 return HDF_FAILURE;
108 }
109
110 ret = WriteSensorRegCfgArray(&CfgData->busCfg, timeGroupNode, index, sizeof(regValue));
111 if (ret != HDF_SUCCESS) {
112 HDF_LOGE("%s: Failed to write sensor register array ", __func__);
113 return HDF_FAILURE;
114 }
115 }
116
117 return HDF_SUCCESS;
118 }
119
CalLux(struct SensorCfgData * CfgData,struct AlsReportData * reportData,uint32_t * rgbcData)120 static int32_t CalLux(struct SensorCfgData *CfgData, struct AlsReportData *reportData, uint32_t *rgbcData)
121 {
122 int32_t ret;
123 uint32_t time;
124 uint32_t gain;
125 uint8_t regValue;
126 uint32_t index = 1;
127 uint32_t luxTemp;
128 uint8_t itemNum;
129 struct SensorRegCfgGroupNode *GroupNode = NULL;
130 int32_t timeIndex = EXTENDED_ALS_TIME_GROUP_INDEX_0;
131 int32_t gainIndex = EXTENDED_ALS_GAIN_GROUP_INDEX_0;
132
133 if (rgbcData[ALS_G] <= 0) {
134 HDF_LOGE("%s: RgbcData out of range ", __func__);
135 return HDF_FAILURE;
136 }
137
138 if (BH1745_MULTIPLE_100 * rgbcData[ALS_C] / rgbcData[ALS_G] < BH1745_COEFFICIENT_JUDGE) {
139 index = 0;
140 }
141
142 luxTemp = g_red[index] * rgbcData[ALS_R] + g_green[index] * rgbcData[ALS_G];
143
144 GroupNode = CfgData->extendedRegCfgGroup[EXTENDED_ALS_TIME_GROUP];
145 itemNum = GroupNode->itemNum;
146 if (itemNum > EXTENDED_ALS_TIME_GROUP_INDEX_MAX) {
147 HDF_LOGE("%s: ItemNum out of range ", __func__);
148 return HDF_FAILURE;
149 }
150
151 ret = ReadSensorRegCfgArray(&CfgData->busCfg, GroupNode, timeIndex, ®Value, sizeof(regValue));
152 if (ret != HDF_SUCCESS) {
153 HDF_LOGE("%s: Failed to read sensor register array ", __func__);
154 return HDF_FAILURE;
155 }
156 regValue &= GroupNode->regCfgItem->mask;
157 time = GetTimeByRegValue(regValue, g_timeMap, itemNum);
158
159 regValue = 0;
160 GroupNode = CfgData->extendedRegCfgGroup[EXTENDED_ALS_GAIN_GROUP];
161 itemNum = GroupNode->itemNum;
162 if (itemNum > EXTENDED_ALS_GAIN_GROUP_INDEX_MAX) {
163 HDF_LOGE("%s: ItemNum out of range ", __func__);
164 return HDF_FAILURE;
165 }
166
167 ret = ReadSensorRegCfgArray(&CfgData->busCfg, GroupNode, gainIndex, ®Value, sizeof(regValue));
168 if (ret != HDF_SUCCESS) {
169 HDF_LOGE("%s: Failed to read sensor register array ", __func__);
170 return HDF_FAILURE;
171 }
172 regValue &= GroupNode->regCfgItem->mask;
173 gain = GetGainByRegValue(regValue, g_gainMap, itemNum);
174
175 reportData->als = ((luxTemp * BH1745_TIME_160MSEC * BH1745_GAIN_16X) / gain) / time;
176
177 return HDF_SUCCESS;
178 }
179
RawDataConvert(struct SensorCfgData * CfgData,struct AlsReportData * reportData,uint32_t * rgbcData)180 static int32_t RawDataConvert(struct SensorCfgData *CfgData, struct AlsReportData *reportData, uint32_t *rgbcData)
181 {
182 int ret;
183
184 ret = CalLux(CfgData, reportData, rgbcData);
185 if (ret != HDF_SUCCESS) {
186 HDF_LOGE("%s: Failed to calculate sensor brightness ", __func__);
187 return HDF_FAILURE;
188 }
189
190 reportData->als = (reportData->als > 0) ? reportData->als : 0;
191
192 ret = DynamicRangCovert(CfgData, rgbcData);
193 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "DynamicRangCovert");
194
195 return HDF_SUCCESS;
196 }
197
ReadBh1745RawData(struct SensorCfgData * data,struct AlsData * rawData,int64_t * timestamp)198 static int32_t ReadBh1745RawData(struct SensorCfgData *data, struct AlsData *rawData, int64_t *timestamp)
199 {
200 uint8_t status = 0;
201 uint8_t reg[ALS_LIGHT_BUTT];
202 OsalTimespec time;
203
204 (void)memset_s(&time, sizeof(time), 0, sizeof(time));
205 (void)memset_s(reg, sizeof(reg), 0, sizeof(reg));
206
207 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
208
209 if (OsalGetTime(&time) != HDF_SUCCESS) {
210 HDF_LOGE("%s: Get time failed", __func__);
211 return HDF_FAILURE;
212 }
213 *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
214
215 int32_t ret = ReadSensor(&data->busCfg, BH1745_MODECONTROL3_ADDR, &status, sizeof(uint8_t));
216 if (!(status & BH1745_ALS_DATA_READY_MASK) || (ret != HDF_SUCCESS)) {
217 HDF_LOGE("%s: data status [%u] ret [%d]", __func__, status, ret);
218 return HDF_FAILURE;
219 }
220
221 ret = ReadSensor(&data->busCfg, BH1745_ALS_R_LSB_ADDR, ®[ALS_R_LSB], sizeof(uint8_t));
222 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
223
224 ret = ReadSensor(&data->busCfg, BH1745_ALS_R_MSB_ADDR, ®[ALS_R_MSB], sizeof(uint8_t));
225 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
226
227 ret = ReadSensor(&data->busCfg, BH1745_ALS_G_LSB_ADDR, ®[ALS_G_LSB], sizeof(uint8_t));
228 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
229
230 ret = ReadSensor(&data->busCfg, BH1745_ALS_G_MSB_ADDR, ®[ALS_G_MSB], sizeof(uint8_t));
231 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
232
233 ret = ReadSensor(&data->busCfg, BH1745_ALS_B_LSB_ADDR, ®[ALS_B_LSB], sizeof(uint8_t));
234 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
235
236 ret = ReadSensor(&data->busCfg, BH1745_ALS_B_MSB_ADDR, ®[ALS_B_MSB], sizeof(uint8_t));
237 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
238
239 ret = ReadSensor(&data->busCfg, BH1745_ALS_C_LSB_ADDR, ®[ALS_C_LSB], sizeof(uint8_t));
240 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
241
242 ret = ReadSensor(&data->busCfg, BH1745_ALS_C_MSB_ADDR, ®[ALS_C_MSB], sizeof(uint8_t));
243 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
244
245 rawData->red = (uint16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ALS_R_MSB], SENSOR_DATA_WIDTH_8_BIT) |
246 reg[ALS_R_LSB]);
247 rawData->green = (uint16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ALS_G_MSB], SENSOR_DATA_WIDTH_8_BIT) |
248 reg[ALS_G_LSB]);
249 rawData->blue = (uint16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ALS_B_MSB], SENSOR_DATA_WIDTH_8_BIT) |
250 reg[ALS_B_LSB]);
251 rawData->clear = (uint16_t)(SENSOR_DATA_SHIFT_LEFT(reg[ALS_C_MSB], SENSOR_DATA_WIDTH_8_BIT) |
252 reg[ALS_C_LSB]);
253
254 return HDF_SUCCESS;
255 }
256
ReadBh1745Data(struct SensorCfgData * data)257 int32_t ReadBh1745Data(struct SensorCfgData *data)
258 {
259 int32_t ret;
260 struct AlsData rawData = { 0, 0, 0, 0 };
261 uint32_t tmp[ALS_LIGHT_NUM];
262 struct SensorReportEvent event;
263 struct AlsReportData reportData;
264
265 (void)memset_s(&event, sizeof(event), 0, sizeof(event));
266 ret = ReadBh1745RawData(data, &rawData, &event.timestamp);
267 if (ret != HDF_SUCCESS) {
268 HDF_LOGE("%s: BH1745 read raw data failed", __func__);
269 return HDF_FAILURE;
270 }
271
272 event.sensorId = SENSOR_TAG_AMBIENT_LIGHT;
273 event.option = 0;
274 event.mode = SENSOR_WORK_MODE_REALTIME;
275
276 tmp[ALS_R] = rawData.red;
277 tmp[ALS_G] = rawData.green;
278 tmp[ALS_B] = rawData.blue;
279 tmp[ALS_C] = rawData.clear;
280
281 ret = RawDataConvert(data, &reportData, tmp);
282 CHECK_PARSER_RESULT_RETURN_VALUE(ret, "RawDataConvert");
283
284 event.dataLen = sizeof(reportData.als);
285 event.data = (uint8_t *)&reportData.als;
286
287 ret = ReportSensorEvent(&event);
288 if (ret != HDF_SUCCESS) {
289 HDF_LOGE("%s: BH1745 report data failed", __func__);
290 }
291 return ret;
292 }
293
InitBh1745(struct SensorCfgData * data)294 static int32_t InitBh1745(struct SensorCfgData *data)
295 {
296 int32_t ret;
297
298 CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
299 ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]);
300 if (ret != HDF_SUCCESS) {
301 HDF_LOGE("%s: BH1745 sensor init config failed", __func__);
302 return HDF_FAILURE;
303 }
304
305 return HDF_SUCCESS;
306 }
307
InitAlsPreConfig(void)308 static int32_t InitAlsPreConfig(void)
309 {
310 if (SetSensorPinMux(SENSOR_I2C6_DATA_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) {
311 HDF_LOGE("%s: Data write mux pin failed", __func__);
312 return HDF_FAILURE;
313 }
314 if (SetSensorPinMux(SENSOR_I2C6_CLK_REG_ADDR, SENSOR_ADDR_WIDTH_4_BYTE, SENSOR_I2C_REG_CFG) != HDF_SUCCESS) {
315 HDF_LOGE("%s: Clk write mux pin failed", __func__);
316 return HDF_FAILURE;
317 }
318
319 return HDF_SUCCESS;
320 }
321
DispatchBH1745(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)322 static int32_t DispatchBH1745(struct HdfDeviceIoClient *client,
323 int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
324 {
325 (void)client;
326 (void)cmd;
327 (void)data;
328 (void)reply;
329
330 return HDF_SUCCESS;
331 }
332
Bh1745BindDriver(struct HdfDeviceObject * device)333 int32_t Bh1745BindDriver(struct HdfDeviceObject *device)
334 {
335 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
336
337 struct Bh1745DrvData *drvData = (struct Bh1745DrvData *)OsalMemCalloc(sizeof(*drvData));
338 if (drvData == NULL) {
339 HDF_LOGE("%s: Malloc Bh1745 drv data fail", __func__);
340 return HDF_ERR_MALLOC_FAIL;
341 }
342
343 drvData->ioService.Dispatch = DispatchBH1745;
344 drvData->device = device;
345 device->service = &drvData->ioService;
346 g_bh1745DrvData = drvData;
347
348 return HDF_SUCCESS;
349 }
350
Bh1745InitDriver(struct HdfDeviceObject * device)351 int32_t Bh1745InitDriver(struct HdfDeviceObject *device)
352 {
353 int32_t ret;
354 struct AlsOpsCall ops;
355
356 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
357 struct Bh1745DrvData *drvData = (struct Bh1745DrvData *)device->service;
358 CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
359
360 ret = InitAlsPreConfig();
361 if (ret != HDF_SUCCESS) {
362 HDF_LOGE("%s: Init BH1745 bus mux config", __func__);
363 return HDF_FAILURE;
364 }
365
366 drvData->sensorCfg = AlsCreateCfgData(device->property);
367 if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
368 HDF_LOGD("%s: Creating alscfg failed because detection failed", __func__);
369 return HDF_ERR_NOT_SUPPORT;
370 }
371
372 ops.Init = NULL;
373 ops.ReadData = ReadBh1745Data;
374 ret = AlsRegisterChipOps(&ops);
375 if (ret != HDF_SUCCESS) {
376 HDF_LOGE("%s: Register BH1745 als failed", __func__);
377 return HDF_FAILURE;
378 }
379
380 ret = InitBh1745(drvData->sensorCfg);
381 if (ret != HDF_SUCCESS) {
382 HDF_LOGE("%s: Init BH1745 als failed", __func__);
383 return HDF_FAILURE;
384 }
385
386 return HDF_SUCCESS;
387 }
388
Bh1745ReleaseDriver(struct HdfDeviceObject * device)389 void Bh1745ReleaseDriver(struct HdfDeviceObject *device)
390 {
391 CHECK_NULL_PTR_RETURN(device);
392
393 struct Bh1745DrvData *drvData = (struct Bh1745DrvData *)device->service;
394 CHECK_NULL_PTR_RETURN(drvData);
395
396 if (drvData->sensorCfg != NULL) {
397 AlsReleaseCfgData(drvData->sensorCfg);
398 drvData->sensorCfg = NULL;
399 }
400 OsalMemFree(drvData);
401 }
402
403 struct HdfDriverEntry g_alsBh1745DevEntry = {
404 .moduleVersion = 1,
405 .moduleName = "HDF_SENSOR_ALS_BH1745",
406 .Bind = Bh1745BindDriver,
407 .Init = Bh1745InitDriver,
408 .Release = Bh1745ReleaseDriver,
409 };
410
411 HDF_INIT(g_alsBh1745DevEntry);
412