• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &regValue, 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, &regValue, 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, &regValue, 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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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