OpenHarmony南向之PWM背光

概述

之前在讲《OpenHarmony南向之LCD显示屏》时,有提到显示屏的背光,但没有展开,今天我们来详细讲讲。

背光驱动模型也是基于HDF框架开发的,整个框架如下:

现在以RK3568为例,来看看PWM背光整个驱动,这里使用的是PWM占空比控制的背光,默认基于hdf的pwm驱动已经OK!

需要注意的是:这里是基于HDF实现的PWM和PWM背光,所以Linux内核里面原生的PWM和PWM背光相关配置需要关闭

相关代码路径:

  • drivers/hdf_core/framework/model/display/driver/backlight/
  • vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs
  • vendor/hihope/rk3568/hdf_config/khdf/lcd/lcd_config.hcs

hcs

device_info

display :: host {
    hostName = "display_host";

    device_pwm_bl :: device {
        device0 :: deviceNode {
            policy = 0;
            priority = 95;
            preload = 0;
            moduleName = "PWM_BL";
            deviceMatchAttr = "pwm_bl_dev";
        }
    }
    device_backlight :: device {
        device0 :: deviceNode {
            policy = 2;
            priority = 90;
            preload = 0;
            permission = 0660;
            moduleName = "HDF_BL";
            serviceName = "hdf_bl";
        }
    }
}

config

lcd_config.hcs

root {
    backlightConfig {
        pwmBacklightConfig {
            match_attr = "pwm_bl_dev";
            pwmDevNum = 1;
            pwmMaxPeriod = 25000;
            backlightDevName = "hdf_pwm";
            minBrightness = 0;
            defBrightness = 127;
            maxBrightness = 255;
        }
    }
}

源码分析

PWM_BL驱动

PWM_BL驱动(pwm_bl.c)加载后在初始化时主要做了如下几个工作:


//初始化相关PWM模块,主要包括打开相应pwm模块,从hcs获取pwm的配置,并更新配置,
//主要调用pwm相关的驱动接口,如PwmOpen,PwmSetConfig等
ret = BlPwmDevInit(object, blPwmDev);

//注册Backlight设备,具体实现在后面的HDF_BL驱动,这里最重要的就是注册的操作函数集 g_blDevOps,后面有展开 
blDev = RegisterBlDev(blPwmDev->name, &blPwmDev->props, &g_blDevOps, blPwmDev);

//更新Backlight状态
if (UpdateBacklightState(blDev, FB_POWER_ON) != HDF_SUCCESS) {
    HDF_LOGE("%s: UpdateBacklightState fail", __func__);
}

//更新Backlight亮度
if (UpdateBrightness(blDev, blPwmDev->props.defBrightness) != HDF_SUCCESS) {
    HDF_LOGE("%s: UpdateBrightness fail", __func__);
}

g_blDevOps函数集,里面只有一个更新亮度的操作函数,该函数会调用更底层的pwm的HDF驱动接口去更新PWM的占空比,从而控制背光的亮度,具体如下:

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,
};

HDF_BL驱动

HDF_BL驱动(hdf_bl.c)功能主要有2大块:

  1. 对外提供IoService的 Dispatch 接口
    主要涉及到一些对外命令的处理,包括:
    static BlCmdHandle g_blDevCmdHandle[] = {
         HdfGetMinBrightness,    /*获取最小亮度*/
         HdfGetCurrBrightness,   /*获取当前亮度*/
         HdfGetDefBrightness,    /*获取默认亮度*/
         HdfGetMaxBrightness,    /*获取最大亮度*/
         HdfGetBlDevList,        /*获取背光设备列表*/
         HdfSetBrightness,       /*设置亮度*/
     };
  2. RegisterBlDev()函数实现
    主要是 BlDevManager 和 BacklightDev 的内存分配,赋值等,这里就略过了。

参考