• 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    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, &regValue, 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, &regValue, 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, &regValue, 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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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, &reg[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