I’m using an HDMI display panel and have connected GPIOAO_11 to the EN pin on the display backlight control IC. I wrote a device tree overlay to enable the pwm-backlight device control in Linux, and it is working exactly as intended.
The downside is that the backlight remains off until the point in the boot process where my custom script is called and the backlight is powered on. I would like to enable the pwm-backlight support in U-Boot so that the backlight will be enabled earlier in the boot process, and so I can further have U-Boot display a nice boot logo within moments of power-up.
I have (finally) successfully built and flashed mainline U-Boot with the related config options enabled and with a modified .dtsi that includes the pwm backlight and associates it with a “simple-panel.” As a result, U-Boot does recognize the simple-panel and pwm-backlight uclass objects, and it does output the console framebuffer on the HDMI display, but the pwm-backlight pin is not actually enabled/driven high as I would expect.
I will update this later to post my defconfig, dtsi changes, and console outputs when I have access to my machine. But in general, it looks like I am having the same issue as this fellow on SO who does not appear to have gotten an answer to his question.
If anyone here has experience with the inner workings of U-Boot, I could use some help understanding what I should be expecting. Various things I have read suggest that if the panel and associated backlight are properly defined, the backlight will be enabled automatically when the device is probed. On the other hand, I’ve noticed that some devices have a board.c that includes an explicit function to enable the backlight. So I’m not quite sure what tree I should be barking up. Should I be trying to figure out how to get U-Boot to “probe” the panel because doing so will automatically enable the backlight? Or should I be trying to cobble together some function for board.c to explicitly enable the backlight? Or am I not even on the right track at all?
Okay, as my initial attempt to enable PWM backlight in U-Boot, here are the changes I made to U-Boot: https://github.com/theophile/u-boot-amlogic/commit/6d279d72c7f4118c82252972ee34a26e8d5639ec
Here is the (truncated) output of the ‘dm tree’ command:
Class Index Probed Driver Name
-----------------------------------------------------------
root 0 [ + ] root_driver root_driver
firmware 0 [ ] psci |-- psci
simple_bus 0 [ + ] simple_bus |-- soc
simple_bus 1 [ + ] simple_bus | |-- bus@ff600000
display 0 [ + ] meson_dw_hdmi | | |-- hdmi-tx@0
simple_bus 2 [ ] simple_bus | | |-- bus@30000
rng 0 [ ] meson-rng | | | `-- rng@218
simple_bus 3 [ + ] simple_bus | | |-- bus@34400
pinctrl 0 [ + ] meson-g12a-pinctrl | | | `-- pinctrl@40
pinconfig 0 [ ] pinconfig | | | |-- cec_ao_a_h
pinconfig 1 [ ] pinconfig | | | | `-- mux
[***SNIP***]
gpio 0 [ + ] meson-axg-gpio | | | `-- meson-gpio
phy 0 [ ] meson_g12a_usb2_phy | | |-- phy@36000
simple_bus 4 [ ] simple_bus | | |-- bus@38000
phy 1 [ ] meson_g12a_usb2_phy | | |-- phy@3a000
simple_bus 5 [ + ] simple_bus | | |-- bus@3c000
simple_bus 6 [ + ] simple_bus | | | `-- system-controller@0
clk 0 [ + ] meson_clk_g12a | | | |-- clock-controller
power_doma 0 [ + ] meson_ee_pwrc | | | |-- power-controller
syscon 1 [ + ] syscon | | | `-- system-controller@0
clk 3 [ ] meson_clk_g12a | | | |-- clock-controller
power_doma 1 [ ] meson_ee_pwrc | | | `-- power-controller
phy 2 [ ] meson_g12a_usb3_pcie | | |-- phy@46000
simple_bus 7 [ ] simple_bus | | `-- bus@42000
simple_bus 8 [ + ] simple_bus | |-- bus@ff800000
simple_bus 9 [ + ] simple_bus | | |-- sys-ctrl@0
clk 1 [ ] meson_clk_g12a_ao | | | |-- clock-controller
pinctrl 1 [ + ] meson-g12a-pinctrl | | | |-- pinctrl@14
pinconfig 275 [ ] pinconfig | | | | |-- i2c_ao_sck_pins
pinconfig 276 [ ] pinconfig | | | | | `-- mux
pinconfig 277 [ ] pinconfig | | | | |-- i2c_ao_sda
pinconfig 278 [ ] pinconfig | | | | | `-- mux
pinconfig 279 [ ] pinconfig | | | | |-- i2c_ao_sck_e
pinconfig 280 [ ] pinconfig | | | | | `-- mux
pinconfig 281 [ ] pinconfig | | | | |-- i2c_ao_sda_e
pinconfig 282 [ ] pinconfig | | | | | `-- mux
pinconfig 283 [ ] pinconfig | | | | |-- mclk0-ao
pinconfig 284 [ ] pinconfig | | | | | `-- mux
pinconfig 285 [ ] pinconfig | | | | |-- tdm-ao-b-din0
pinconfig 286 [ ] pinconfig | | | | | `-- mux
pinconfig 287 [ ] pinconfig | | | | |-- spdif-ao-out
pinconfig 288 [ ] pinconfig | | | | | `-- mux
pinconfig 289 [ ] pinconfig | | | | |-- tdm-ao-b-din1
pinconfig 290 [ ] pinconfig | | | | | `-- mux
pinconfig 291 [ ] pinconfig | | | | |-- tdm-ao-b-din2
pinconfig 292 [ ] pinconfig | | | | | `-- mux
pinconfig 293 [ ] pinconfig | | | | |-- tdm-ao-b-dout0
pinconfig 294 [ ] pinconfig | | | | | `-- mux
pinconfig 295 [ ] pinconfig | | | | |-- tdm-ao-b-dout1
pinconfig 296 [ ] pinconfig | | | | | `-- mux
pinconfig 297 [ ] pinconfig | | | | |-- tdm-ao-b-dout2
pinconfig 298 [ ] pinconfig | | | | | `-- mux
pinconfig 299 [ ] pinconfig | | | | |-- tdm-ao-b-fs
pinconfig 300 [ ] pinconfig | | | | | `-- mux
pinconfig 301 [ ] pinconfig | | | | |-- tdm-ao-b-sclk
pinconfig 302 [ ] pinconfig | | | | | `-- mux
pinconfig 303 [ ] pinconfig | | | | |-- tdm-ao-b-slv-fs
pinconfig 304 [ ] pinconfig | | | | | `-- mux
pinconfig 305 [ ] pinconfig | | | | |-- tdm-ao-b-slv-sclk
pinconfig 306 [ ] pinconfig | | | | | `-- mux
pinconfig 307 [ + ] pinconfig | | | | |-- uart-a-ao
pinconfig 308 [ ] pinconfig | | | | | `-- mux
pinconfig 309 [ ] pinconfig | | | | |-- uart-ao-a-cts-rts
pinconfig 310 [ ] pinconfig | | | | | `-- mux
pinconfig 311 [ ] pinconfig | | | | |-- pwm-a-e
pinconfig 312 [ ] pinconfig | | | | | `-- mux
pinconfig 313 [ ] pinconfig | | | | |-- pwm-ao-a
pinconfig 314 [ ] pinconfig | | | | | `-- mux
pinconfig 315 [ ] pinconfig | | | | |-- pwm-ao-b
pinconfig 316 [ ] pinconfig | | | | | `-- mux
pinconfig 317 [ ] pinconfig | | | | |-- pwm-ao-c-4
pinconfig 318 [ ] pinconfig | | | | | `-- mux
pinconfig 319 [ ] pinconfig | | | | |-- pwm-ao-c-6
pinconfig 320 [ ] pinconfig | | | | | `-- mux
pinconfig 321 [ ] pinconfig | | | | |-- pwm-ao-d-5
pinconfig 322 [ ] pinconfig | | | | | `-- mux
pinconfig 323 [ ] pinconfig | | | | |-- pwm-ao-d-10
pinconfig 324 [ ] pinconfig | | | | | `-- mux
pinconfig 325 [ ] pinconfig | | | | |-- pwm-ao-d-e
pinconfig 326 [ ] pinconfig | | | | | `-- mux
pinconfig 327 [ ] pinconfig | | | | |-- remote-input-ao
pinconfig 328 [ ] pinconfig | | | | | `-- mux
gpio 1 [ ] meson-axg-gpio | | | | `-- meson-gpio
syscon 2 [ + ] syscon | | | `-- sys-ctrl@0
clk 4 [ ] meson_clk_g12a_ao | | | |-- clock-controller
pinctrl 2 [ ] meson-g12a-pinctrl | | | `-- pinctrl@14
pinconfig 329 [ ] pinconfig | | | |-- i2c_ao_sck_pins
pinconfig 330 [ ] pinconfig | | | | `-- mux
pinconfig 331 [ ] pinconfig | | | |-- i2c_ao_sda
pinconfig 332 [ ] pinconfig | | | | `-- mux
pinconfig 333 [ ] pinconfig | | | |-- i2c_ao_sck_e
pinconfig 334 [ ] pinconfig | | | | `-- mux
pinconfig 335 [ ] pinconfig | | | |-- i2c_ao_sda_e
pinconfig 336 [ ] pinconfig | | | | `-- mux
pinconfig 337 [ ] pinconfig | | | |-- mclk0-ao
pinconfig 338 [ ] pinconfig | | | | `-- mux
pinconfig 339 [ ] pinconfig | | | |-- tdm-ao-b-din0
pinconfig 340 [ ] pinconfig | | | | `-- mux
pinconfig 341 [ ] pinconfig | | | |-- spdif-ao-out
pinconfig 342 [ ] pinconfig | | | | `-- mux
pinconfig 343 [ ] pinconfig | | | |-- tdm-ao-b-din1
pinconfig 344 [ ] pinconfig | | | | `-- mux
pinconfig 345 [ ] pinconfig | | | |-- tdm-ao-b-din2
pinconfig 346 [ ] pinconfig | | | | `-- mux
pinconfig 347 [ ] pinconfig | | | |-- tdm-ao-b-dout0
pinconfig 348 [ ] pinconfig | | | | `-- mux
pinconfig 349 [ ] pinconfig | | | |-- tdm-ao-b-dout1
pinconfig 350 [ ] pinconfig | | | | `-- mux
pinconfig 351 [ ] pinconfig | | | |-- tdm-ao-b-dout2
pinconfig 352 [ ] pinconfig | | | | `-- mux
pinconfig 353 [ ] pinconfig | | | |-- tdm-ao-b-fs
pinconfig 354 [ ] pinconfig | | | | `-- mux
pinconfig 355 [ ] pinconfig | | | |-- tdm-ao-b-sclk
pinconfig 356 [ ] pinconfig | | | | `-- mux
pinconfig 357 [ ] pinconfig | | | |-- tdm-ao-b-slv-fs
pinconfig 358 [ ] pinconfig | | | | `-- mux
pinconfig 359 [ ] pinconfig | | | |-- tdm-ao-b-slv-sclk
pinconfig 360 [ ] pinconfig | | | | `-- mux
pinconfig 361 [ ] pinconfig | | | |-- uart-a-ao
pinconfig 362 [ ] pinconfig | | | | `-- mux
pinconfig 363 [ ] pinconfig | | | |-- uart-ao-a-cts-rts
pinconfig 364 [ ] pinconfig | | | | `-- mux
pinconfig 365 [ ] pinconfig | | | |-- pwm-a-e
pinconfig 366 [ ] pinconfig | | | | `-- mux
pinconfig 367 [ ] pinconfig | | | |-- pwm-ao-a
pinconfig 368 [ ] pinconfig | | | | `-- mux
pinconfig 369 [ ] pinconfig | | | |-- pwm-ao-b
pinconfig 370 [ ] pinconfig | | | | `-- mux
pinconfig 371 [ ] pinconfig | | | |-- pwm-ao-c-4
pinconfig 372 [ ] pinconfig | | | | `-- mux
pinconfig 373 [ ] pinconfig | | | |-- pwm-ao-c-6
pinconfig 374 [ ] pinconfig | | | | `-- mux
pinconfig 375 [ ] pinconfig | | | |-- pwm-ao-d-5
pinconfig 376 [ ] pinconfig | | | | `-- mux
pinconfig 377 [ ] pinconfig | | | |-- pwm-ao-d-10
pinconfig 378 [ ] pinconfig | | | | `-- mux
pinconfig 379 [ ] pinconfig | | | |-- pwm-ao-d-e
pinconfig 380 [ ] pinconfig | | | | `-- mux
pinconfig 381 [ ] pinconfig | | | `-- remote-input-ao
pinconfig 382 [ ] pinconfig | | | `-- mux
syscon 0 [ ] syscon | | |-- ao-secure@140
pwm 0 [ ] meson_pwm | | |-- pwm@2000
serial 0 [ + ] serial_meson | | |-- serial@3000
pwm 1 [ ] meson_pwm | | `-- pwm@7000
video 0 [ + ] meson_vpu | |-- vpu@ff900000
vidconsole 0 [ + ] vidconsole0 | | `-- [email protected]
simple_bus 10 [ + ] simple_bus | |-- bus@ffd00000
reset 0 [ + ] meson_reset | | |-- reset-controller@1004
pwm 2 [ ] meson_pwm | | |-- pwm@19000
serial 1 [ ] serial_meson | | `-- serial@24000
mmc 0 [ + ] meson_gx_mmc | |-- sd@ffe03000
blk 0 [ ] mmc_blk | | |-- [email protected]
bootdev 0 [ ] mmc_bootdev | | `-- [email protected]
mmc 1 [ + ] meson_gx_mmc | |-- sd@ffe05000
blk 1 [ ] mmc_blk | | |-- [email protected]
bootdev 1 [ ] mmc_bootdev | | `-- [email protected]
mmc 2 [ + ] meson_gx_mmc | |-- mmc@ffe07000
blk 2 [ ] mmc_blk | | |-- [email protected]
bootdev 2 [ ] mmc_bootdev | | `-- [email protected]
simple_bus 11 [ ] dwc3-meson-g12a | `-- usb@ffe09000
usb 0 [ ] xhci-dwc3 | `-- usb@ff500000
clk 2 [ ] fixed_clock |-- xtal-clk
backlight 0 [ ] pwm_backlight |-- backlight
panel 0 [ ] simple_panel |-- panel
pwrseq 0 [ + ] mmc_pwrseq_emmc |-- emmc-pwrseq
regulator 0 [ ] regulator_fixed |-- regulator-ao_5v
regulator 1 [ ] regulator_fixed |-- regulator-vcc_1v8
regulator 2 [ ] regulator_fixed |-- regulator-vcc_3v3
regulator 3 [ + ] regulator_fixed |-- regulator-hdmi_pw
regulator 4 [ ] regulator_fixed |-- regulator-vddao_1v8
regulator 5 [ ] regulator_fixed |-- regulator-vddao_3v3
bootstd 0 [ ] bootstd_drv `-- bootstd
bootmeth 0 [ ] bootmeth_distro |-- distro
bootmeth 1 [ ] bootmeth_efi |-- efi
bootmeth 2 [ ] bootmeth_pxe |-- pxe
bootdev 3 [ ] system_bootdev `-- system-bootdev
As you can see, the “panel” and “backlight” classes are created but the devices are not probed. It feels like there is a further step that must be necessary to initialize this device but I’m not sure what it is.
On further reflection, I think I might have an idea what’s going on. The U-Boot console is outputting on vidconsole0, which is using the meson_vpu video uclass. There is also an hdmi-tx node using the meson_dw_hdmi driver and the display uclass. The regulator-hdmi_pw regulator is also in use. Notably, the vidconsole, meson_vpu, meson_dw_hdmi, and hdmi_pw regulator devices are all probed at boot.
So I think that although I have defined simple_panel and pwm_backlight nodes, they are not being used to display anything, U-Boot doesn’t know what they’re for and has no reason to probe them.
My instinct is to try to modify the .dts to link the backlight node to the hdmi-tx node (display uclass). However, the Kconfig entry for the pwm_backlight driver suggests that the pwm_backlight driver can be used with the simple_panel driver, which in turn uses the panel uclass driver. The panel uclass driver has methods specifically for enabling and setting the backlight. Conversely, the display uclass driver does not have backlight methods.
All of this makes me suspect that it’s simply not possible to link a pwm-backlight device to an HDMI monitor on this hardware without modifying/rewriting the drivers. This could explain why the kernel does not turn the backlight on at boot, even though the backlight device exists. Just like U-Boot, the kernel can set up the backlight device but has no idea it’s for the HDMI display. The difference is that in Linux I can manually enable and configure the backlight in userspace (which is why a custom boot script is needed to enable it), whereas U-Boot does not have such userspace tools (as far as I have been able to figure out so far).
All this to say, I suspect what I’m going to have to do is forget about trying to use the pwm-backlight driver and instead just use the regular pwm uclass and see if I can control it using environment variables or custom board.c code.
I spent some time trying to get the regular “pwm” command to work, but even after removing the backlight and panel notes from the device tree, I found that I would still get “‘synchronous abort’ handler error” and accompanying hard reboot every time I would attempt to run the pwm command on the pwm device. On the other hand, the ‘gpio set’ command would successfully drive the pin high, which of course has the effect of turning on the backlight. However, I discovered that when u-boot hands off to the kernel, the gpio is reset anyway (presumably) because I have that pin configured in the kernel device tree as a backlight. So after all that, even though I was able to get u-boot to turn my backlight pin on, the only effect in practice was making it blink on and then off barely a second later.
Instead, I set up an init.d script to run early in the boot process to load the pwm_bl module and enable the backlight. It doesn’t turn as as early as u-boot, but I’m going to call it close enough for now.