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