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