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