/* * Copyright (c) 2020-2021 Huawei Device Co., Ltd. * * HDF is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. * See the LICENSE file in the root of this repository for complete details. */ #include "device_resource_if.h" #include "hdf_base.h" #include "hdf_bl.h" #include "hdf_disp.h" #include "hdf_log.h" #include "hdf_types.h" #include "osal.h" #include "pwm_if.h" #define DEF_MIN_BRIGHTNESS 0 #define DEF_MAX_BRIGHTNESS 255 #define CHECK_PARSER_RET(ret, str) do { \ if ((ret) != HDF_SUCCESS) { \ HDF_LOGE("%s: %s failed, ret = %d", __func__, str, ret); \ return HDF_FAILURE; \ } \ } while (0) struct BlPwmDev { const char *name; uint8_t pwmDevNum; DevHandle pwmHandle; struct PwmConfig config; struct BacklightProperties props; }; static int32_t BlPwmUpdateBrightness(struct BacklightDev *blDev, uint32_t brightness) { int32_t ret; uint32_t duty; struct BlPwmDev *blPwmDev = NULL; blPwmDev = ToBlDevPriv(blDev); if (blPwmDev == NULL) { HDF_LOGE("%s blPwmDev is null", __func__); return HDF_FAILURE; } if (blPwmDev->props.maxBrightness == 0) { HDF_LOGE("%s maxBrightness is 0", __func__); return HDF_FAILURE; } if (brightness == 0) { return PwmDisable(blPwmDev->pwmHandle); } duty = (brightness * blPwmDev->config.period) / blPwmDev->props.maxBrightness; ret = PwmSetDuty(blPwmDev->pwmHandle, duty); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: PwmSetDuty failed, ret %d", __func__, ret); return HDF_FAILURE; } return PwmEnable(blPwmDev->pwmHandle); } static struct BacklightOps g_blDevOps = { .updateBrightness = BlPwmUpdateBrightness, }; static int32_t ParsePwmNum(const struct DeviceResourceNode *node, uint8_t *pwmNum) { int32_t ret; struct DeviceResourceIface *parser = NULL; if (node == NULL) { HDF_LOGE("%s: node is null", __func__); return HDF_FAILURE; } parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); if (parser == NULL) { HDF_LOGE("%s: instance parser failed", __func__); return HDF_FAILURE; } ret = parser->GetUint8(node, "pwmDevNum", pwmNum, 0); CHECK_PARSER_RET(ret, "GetUint8"); return HDF_SUCCESS; } static int32_t ParseBlPwmCfg(const struct DeviceResourceNode *node, struct BlPwmDev *blPwmDev) { int32_t ret; uint32_t defBrightness; struct DeviceResourceIface *parser = NULL; if (node == NULL) { HDF_LOGE("%s: node is null", __func__); return HDF_FAILURE; } parser = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); if (parser == NULL) { HDF_LOGE("%s: instance parser failed", __func__); return HDF_FAILURE; } ret = parser->GetString(node, "backlightDevName", &blPwmDev->name, NULL); CHECK_PARSER_RET(ret, "GetString"); ret = parser->GetUint32(node, "pwmMaxPeroid", &blPwmDev->config.period, 0); CHECK_PARSER_RET(ret, "GetUint32"); ret = parser->GetUint32(node, "minBrightness", &blPwmDev->props.minBrightness, DEF_MIN_BRIGHTNESS); CHECK_PARSER_RET(ret, "GetUint32"); ret = parser->GetUint32(node, "maxBrightness", &blPwmDev->props.maxBrightness, DEF_MAX_BRIGHTNESS); CHECK_PARSER_RET(ret, "GetUint32"); // if not provided defBrightness, defBrightness = (min + max) / 2 defBrightness = (blPwmDev->props.minBrightness + blPwmDev->props.maxBrightness) / 2; ret = parser->GetUint32(node, "defBrightness", &blPwmDev->props.defBrightness, defBrightness); CHECK_PARSER_RET(ret, "GetUint32"); blPwmDev->config.duty = 1; blPwmDev->config.status = 1; return HDF_SUCCESS; } static int32_t BlPwmDevInit(struct HdfDeviceObject *object, struct BlPwmDev *blPwmDev) { if (ParsePwmNum(object->property, &blPwmDev->pwmDevNum) != HDF_SUCCESS) { HDF_LOGE("%s ParsePwmNum fail", __func__); return HDF_FAILURE; } blPwmDev->pwmHandle = PwmOpen(blPwmDev->pwmDevNum); if (blPwmDev->pwmHandle == NULL) { HDF_LOGE("%s: PwmOpen failed", __func__); return HDF_FAILURE; } if (PwmGetConfig(blPwmDev->pwmHandle, &blPwmDev->config) != HDF_SUCCESS) { HDF_LOGE("%s: PwmGetConfig fail", __func__); return HDF_FAILURE; } if (ParseBlPwmCfg(object->property, blPwmDev) != HDF_SUCCESS) { HDF_LOGE("%s: ParseBlPwmCfg fail", __func__); return HDF_FAILURE; } if (PwmSetConfig(blPwmDev->pwmHandle, &blPwmDev->config) != HDF_SUCCESS) { HDF_LOGE("%s: PwmSetConfig fail", __func__); return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t BlPwmEntryInit(struct HdfDeviceObject *object) { int32_t ret; struct BacklightDev *blDev = NULL; struct BlPwmDev *blPwmDev = NULL; blPwmDev = (struct BlPwmDev *)OsalMemCalloc(sizeof(struct BlPwmDev)); if (blPwmDev == NULL) { HDF_LOGE("%s blPwmDev malloc fail", __func__); return HDF_FAILURE; } ret = BlPwmDevInit(object, blPwmDev); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: BlPwmDevInit fail", __func__); goto FAIL; } blDev = RegisterBlDev(blPwmDev->name, &blPwmDev->props, &g_blDevOps, blPwmDev); if (blDev == NULL) { HDF_LOGE("%s: RegisterBlDev fail", __func__); goto FAIL; } if (UpdateBacklightState(blDev, FB_POWER_ON) != HDF_SUCCESS) { HDF_LOGE("%s: UpdateBacklightState fail", __func__); } if (UpdateBrightness(blDev, blPwmDev->props.defBrightness) != HDF_SUCCESS) { HDF_LOGE("%s: UpdateBrightness fail", __func__); } HDF_LOGI("%s: success", __func__); return HDF_SUCCESS; FAIL: OsalMemFree(blPwmDev); return HDF_FAILURE; } struct HdfDriverEntry g_pwmBlDevEntry = { .moduleVersion = 1, .moduleName = "PWM_BL", .Init = BlPwmEntryInit, }; HDF_INIT(g_pwmBlDevEntry);