edp屏幕pwm不准确分析

目录

现象

现象1

现象2

示波器测量占空比

屏的占空比要求

DTS配置检查

pwm

驱动源码

源码路径

驱动确认

[panel native pwm驱动](#panel native pwm驱动)

总体流程

update_status

cabc使能状态查询

设置

backlight_set_bl_level

上层调用

cabc是个啥

查询

cabc的控制

总结


现象

现象1

通过麒麟系统界面调节屏幕亮度到100%,通过sys文件系统查看

复制代码
/sys/class/backlight/DSI-1# cat brightness
255
/sys/class/backlight/DSI-1# cat actual_brightness
158

实际示波器测量占空比为61.3%

复制代码
/sys/class/backlight/DSI-1# cat  actual_brightness
15
/sys/class/backlight/DSI-1# cat brightness
25

实际示波器测量占空比为5.3%

现象2

在桌面时,将占空比调节到50%后,自动进入锁屏后,占空比会自动变化。

示波器测量占空比

通过示波器的一个通道就可以测量亮度的占空比。一端接地,另外一端接GPIO管脚。

初始状态,虽然有波形,但没有测量项目。

1) 按 mesure键,出现测量界面,而后选择"时间测量",示例如下:

2) 而后 "旋转" 选择要测量的项目。有"周期","频率" "上升时间""正向占空比"等,这里选择占空比。

3) 测试效果

屏的占空比要求

每种屏幕的占空比有要求,需要根据具体要求配置,示例如下:

NV156

EV133

Note3: 1% duty cycle is achievable with a dimming frequency less than 1KHz

当调光频率低于1千赫兹时,可实现1%的占空比

DTS配置检查

复制代码
panel_blk { 
compatible = "panel-pwm-tx"; 
pwms = <&soct_pwm8 6 1000000 0>; 
}

pwms:第一个参数标识用哪个GPIO控制器;第二个是此组控制器的哪个GPIO管脚;

第三个参数标识 PWM 波形的时间周期,单位为ns,此处即配置为1ms,频率即为1/0.001s=1K HZ

屏幕PWM要求,上述配置完全符合。

pwm

此节点下有许多,pwmchipX节点

复制代码
/sys/class/pwm/

pwmchipX,X是从0开始编号,每次*8的;第0个为0;第1个为1*8;以此类推;

Pwm8对应 8*8=64 即: pwmchip64,对应第二章中的GPIO组。

复制代码
/sys/class/pwm/pwmchip64# cat npwm
8

通过echo 6 >export,并设置占空比等,而后再在示波器端测量。可以确认是硬件异常还是驱动异常。此操作需要修改DTS,让驱动是否此GPIO管脚,否则echo 6>export 会报忙的错误。

补充命令,及示波器的拍图。

驱动源码

源码路径

pwm 驱动:\linux\kernel\drivers\pwm\pwm_soct.c

panel pwm驱动:\bootloader\source\drivers\panel\backlight\native\drv_panel_native_pwm.c

复制代码
static const struct backlight_ops panel_genericbl_ops = {
    .options = BL_CORE_SUSPENDRESUME,
    .get_brightness = drv_panel_generic_get_intensity,
    .update_status  = drv_panel_generic_send_intensity,
};

通用背光驱动(背光入口): ./drivers/video/backlight/backlight.c

平台背光驱动:\drivers\video\backlight\pwm_bl.c (与panel_pwm为同级,类型为RAW)

适配信息:

复制代码
 static const struct of_device_id pwm_backlight_of_match[] = {
    { .compatible = "pwm-backlight" },
    { }

DRM 背光驱动: \linux\drv\drm\backlight\soc_drm_backlight.c

generic_bl背光驱动:

KERNEL_OBJ_M\drivers\video\backlight\generic_bl.ko

/vendor/thirdparty/kos/kernel/linux-5.4/drivers/video/backlight/generic_bl.c

驱动确认

采用DSI转EDP链接,DSI-1,查看驱动,名称及compitable与 panel pwm驱动一致,但是内核中没有此驱动代码。

复制代码
cat /sys/class/backlight/DSI-1/device/uevent
DRIVER=panel_backlight_generic
MODALIAS=platform:panel_backlight_generic

通过下面的检索,看起来内核用的驱动代码在上面bootloader的路径中的

复制代码
grep "panel_backlight_generic" ./ -rn
bootloader/source/drivers/panel/backlight/native/drv_panel_native_pwm.c
/out/target/obj/KERNEL_OBJ_M/drivers/drv/panel/soc_panel.o: 匹配到二进制文件
/out/target/obj/KERNEL_OBJ_M/drivers/drv/panel/soc_panel.ko: 匹配到二进制文件
/out/target/obj/KERNEL_OBJ_M/drivers/drv/panel/backlight/native/drv_panel_native_pwm.o: 匹配到二进制文件

而走读\out\target\obj\KERNEL_OBJ_M\drivers\drv\panel\backlight\native\.drv_panel_native_pwm.o.cmd,发现用的驱动路径为:

vendor/thirdparty/kos/kernel/linux-5.4/drivers/drv/panel/backlight/native/drv_panel_native_pwm.c

|----|----------------------------------------------------------------------------|
| 内核 | |
| 内核 | vendor\xxx\linux\drv\panel\backlight\native |
| 内核 | thirdparty\kos\kernel\linux-5.4\drivers\drv\panel\backlight\native |

为什么有如此多的地方有代码,这些代码是软连接还是编译拷贝,还是基于某个基础版本的修改呢?

verndor目录下的驱动:

复制代码
vendor/xxx/linux/drv$ ls -lh
 gpu -> ../../../thirdparty/gpu/drv

 panel -> ../../bootloader/source/drivers/panel

KOS目录下的驱动

复制代码
vendor/thirdparty/kos/kernel/linux-5.4/drivers$ ls -lh
 drv -> /vendor/xxx/linux/drv

 xxx -> ../../../../../xxx/linux/kernel/drivers/

至此,终于确认了内核panel驱动的路径。

panel native pwm驱动

类型值 常量 说明
1 BACKLIGHT_RAW 直接硬件控制,直接写寄存器
2 BACKLIGHT_PLATFORM 平台特定驱动(如PWM控制)
3 BACKLIGHT_FIRMWARE ACPI/固件控制(最常见)
4 BACKLIGHT_TYPE_MAX 类型数量,用于边界检查
复制代码
props.type = BACKLIGHT_FIRMWARE;
props.max_brightness = PANEL_LIGHT_LEVEL_MAX;

BACKLIGHT_FIRMWARE 指定了背光(backlight)的控制类型,表示使用固件(如ACPI)来控制背光亮度,而不是直接通过硬件寄存器。ACPI方法:_BCL(获取亮度级别列表)、_BCM(设置亮度)、_BQC(获取当前亮度)

总体流程

复制代码
用户空间请求亮度
    ↓
brightness属性 (期望亮度)
    ↓
update_status() → 驱动设置硬件
    ↓
get_brightness() ← 从硬件读取实际值
    ↓
actual_brightness属性 (实际亮度)
// 注意:这里并没有直接修改actual_brightness!
    // actual_brightness是通过get_brightness()实时读取的
    
    backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS);

即所有的背光控制 驱动都需要实现上面两个接口,接下来我们分析此驱动的这两个接口实现。

update_status

cabc使能状态查询

cat /proc/msp/panel0

复制代码
----------------------------------------------backlight info--------------------------------------------
bl_bit_depth:1           |bl_min      :0           |bl_max      :255         |bl_def      :112         |
other_freq  :30000       |bl_50_freq  :0           |bl_60_freq  :0           |            :            |
cabc_enable :1           |cabc_gain   :256         |            :            |            :            |

设置

复制代码
 data_base = panel_ctx->file_data.data_struct.un_data_info.data_base;
 panel_ctx->panel_cfg_info.cabc_gain = CABC_GAIN_MAX * bl_level / data_base->backlight_range.max;

根据经验,cabc_gain或者是寄存器,或者是由单独的线程再处理将此值写入硬件。

值计算:

复制代码
 CABC_GAIN_MAX * bl_level / data_base->backlight_range.max;
等于
 0x100*bl_level / data_base->backlight_range.max

假设bl_level为255,range.max被配置为255,那么此值即为0x100,即256

backlight_set_bl_level

drv_panel_set_ntv_pwm_bl_level

看起来这个接口更新是设置 背光的。

复制代码
panel_ntv_pwm_ctx->st_ntv_pwm_info.bl_level = level;
    level = level * bl_info->max_level / 0xff;
    duty_count = level * 30000;
    duty_ns = duty_count / 0xff;

    ret = pwm_config(panel_pwm_device, duty_ns, 30000);
    if (ret != TD_SUCCESS) {
        soc_log_err("pwm_config failled! ret = %d\n", ret);
        return TD_FAILURE;
    }

上层调用

bootloader/source/drivers/panel/backlight/drv_panel_backlight.c

drv_panel_backlight_set_bl_level

只有当cabc没有 被使能时才调用此流程。 cabc是个啥?禁掉看下效果!

cabc是个啥

动态背光控制 ,全称 Content-Adaptive Brightness Control ,通常简称为 CABC。这是一种显示设备的节能技术。回看屏幕手册资料,果然管脚1即为此功能。

CABC功能需要在LCD驱动IC内新增一个内容分析器(imagecontent analyzer)电路,当SOC传送了一张图片数据到驱动IC,内容分析器会计算并统计图片的数据后依据设定与算法自动的将其灰阶亮度提高30%(此时图片变亮),再将背光亮度降低30%(此时图片变暗)。由于我们事先已经将图片经过分析器电路补偿亮度,因此使用者可以得到与原先电路相差无几的显示效果,但减少了30%的背光功耗。

查询

复制代码
panel_ntv_pwm_contex *panel_ntv_pwm_ctx = TD_NULL;

drv_panel_get_native_pwm_ctx(&panel_ntv_pwm_ctx);
panel_ntv_pwm_ctx->st_ntv_pwm_info.bl_level

此处与set_bl_level接口中的设置部分完全对应了。

cabc的控制

通过此控制cabc的使能。有些屏幕不支持此项,无此管脚,有些有。根据具体的需要配置。配置后,cabc会有30%亮度的减少。

复制代码
 support_cabc = <1>;

总结

屏幕的背光功耗很高,而cabc作为一种功耗节省技术,在PWM上表现出与设计设置值不一致的情况,这都是合理的。

相关推荐
ベadvance courageouslyミ3 天前
51单片机相关
单片机·51单片机·定时器·pwm·蜂鸣器·中断·独立按键
YouEmbedded4 天前
解码STM32定时器:原理、配置与实战
stm32·定时器·pwm·sg90舵机
ting_zh10 天前
定时器输出PWM信号同步控制传感器开关与 ADC 采样
stm32·tim·pwm·adc
ting_zh15 天前
用定时器生成PWM信号
stm32·单片机·嵌入式硬件·tim·pwm
云雾J视界1 个月前
PWM不只是调速!深入电机驱动中的动态响应、EMI抑制与电源完整性设计
mcu·pwm·emi·电机驱动·电源完整性·mosfet
加成BUFF1 个月前
树莓派5-TB6612电机驱动模块完整实战教程
嵌入式硬件·pwm·树莓派5·tb6612·pwm波控制电机
赖small强1 个月前
【Linux 驱动开发】Linux PWM (脉冲宽度调制) 全面技术指南
linux·驱动开发·pwm
云雾J视界2 个月前
51单片机信号处理实战:C语言A/D与D/A转换应用,从传感器采集到PWM控制全解析
c语言·51单片机·信号处理·pwm·模拟信号·数字信号·a/d
sheepwjl3 个月前
《嵌入式硬件(二十一):基于IMX6ULL的脉冲宽度调制(PWM)操作》
嵌入式硬件·pwm·脉冲宽度调制