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