* 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");
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);