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