🔨 整理中 · 这一篇讲 LCD/backlight 子系统——"屏幕本身的开关 + 背光亮度调节"两个轻量框架。素材以 6.19 源码 + kernel.org 文档为权威。它不是 19 DRM 那种完整显示管线,只是给"屏通断电/调亮度"的简单抽象。
做什么
嵌入式产品的"显示"分几层:显示管线(把 framebuffer 内容扫到屏幕,这是 DRM/KMS 的活)、屏幕通断电(LCD 本身的电源开关)、背光亮度调节(LED 背光的明暗)。后两者简单(就开/关/调亮度),内核给它们单独的轻量框架:lcd_class(屏幕开关/对比度)和 backlight_class(背光亮度),都挂在 drivers/video/backlight/。用户态 /sys/class/lcd/lcd0/、/sys/class/backlight/backlight0/ 操作。这一篇拆这两个框架怎么写驱动。
要了解什么
一、lcd 子系统:屏幕通断电 + 对比度
struct lcd_device(include/linux/lcd.h:71)+ struct lcd_ops(:42)。核心回调:
set_power/get_power:开/关 LCD 本身的电源(FB_BLANK_UNBLANK正常/POWERDOWN关)。set_contrast/get_contrast:调对比度(如果硬件支持)。check_fb:判断这个 lcd_device 关联哪个 framebuffer(给 fbdev)。
注册:devm_lcd_device_register(dev, "lcd0", dev, &my_data, &my_lcd_ops)(lcd.h:123)。用户态 /sys/class/lcd/lcd0/{power,contrast} 操作。
二、backlight 子系统:背光亮度
struct backlight_device(include/linux/backlight.h:245)+ struct backlight_ops(:100)。核心回调:
update_status:把"当前亮度/电源状态"写进硬件(bd->props.brightness/power)。get_brightness:读当前实际亮度。check_fb:关联哪个 fb。
注册:devm_backlight_device_register(dev, "backlight0", dev, &data, &bl_ops, &bl_props),props 里设 max_brightness/brightness(初始)。用户态 /sys/class/backlight/backlight0/{brightness,max_brightness,actual_brightness,bl_power}——Android/Linux 调亮度就是 echo 128 > .../brightness。
三、典型用法:PWM 背光 + GPIO LCD 电源
- 背光:背光 LED 常由 PWM 驱动(占空比 = 亮度)。内核有
pwm-backlight.c驱动——设备树pwms = <&pwm 0 50000>;+brightness-levels = <0 64 128 192 255>;,驱动把"亮度档位 → PWM 占空比"映射好,注册成 backlight_device。用户态写 brightness → 驱动update_status改 PWM 占空比。 - LCD 电源:LCD 模组本身的电源常是一个 regulator(
vcc-lcd-supply = <&ldo5>)——lcd_ops.set_power里regulator_enable/disable那个 regulator,实现"屏通电/断电"。
四、和 DRM/fbdev 的关系
- 老 fbdev 框架:
/dev/fb0(framebuffer)给用户态写像素,lcd/backlight 配套管"屏本身的电和亮度"。老式嵌入式显示(LCD 模组直接接)用这套。 - 现代 DRM/KMS:19 DRM 一站式管理显示管线(CRTC/encoder/connector/plane),DRM 自己有
drm_panel(面板的开关/时序) + backlight 接口。所以现代显示用 DRM 时,backlight 可能仍走 backlight_class(DRM backlight bridge 复用它),但屏开关/时序归 drm_panel。新代码用 DRM,lcd/backlight 子系统主要是老 fbdev 时代的产物,仍广泛存在于现有 BSP。
动手试试
ls /sys/class/lcd///sys/class/backlight/看设备;cat .../backlight0/max_brightness/actual_brightness;echo 50 > .../brightness调亮度(若有真实背光)- 读
drivers/video/backlight/pwm-bl.c(PWM 背光,最常见)看backlight_ops/update_status怎么调 PWM - 读
drivers/video/backlight/lcd.c/backlight.c看两个框架的 core - 设备树
backlight { compatible = "pwm-backlight"; pwms = <&pwm 0 ...>; brightness-levels = <...>; };加一个,验证/sys/class/backlight/出现 - 思考题:为什么 lcd/backlight 单独成子系统,不归 DRM?(提示:历史 + 它们比 DRM 简单早,且可独立于显示管线存在)
延伸阅读
- 源码(本仓库
third_party/linux/,6.19.9):include/linux/lcd.h:42 struct lcd_ops、:71 struct lcd_device、:123 devm_lcd_device_register;include/linux/backlight.h:100 struct backlight_ops、:245 struct backlight_device;core + 驱动drivers/video/backlight/(lcd.c/backlight.ccore、pwm-bl.cPWM 背光、gpio_backlight.c、各面板*-bl.c)。 - kernel.org:LEDs & backlight、
Documentation/devicetree/bindings/video/backlight/、Documentation/ABI/stable/sysfs-class-backlight。 - 关联本站:19 DRM 现代显示管线(DRM backlight bridge 复用 backlight_class)、29 regulator LCD 电源、16 pinctrl PWM 可能走它复用。