如果使用我们提供的系统,默认情况下开启了LCD 驱动。LCD 跑起来还需要添加相应的设备节点。如何添加设备树插件以及如何修改LCD 常用配置参数。
LCD 常用参数介绍
LCD 配置参数主要包括LCD 引脚相关配置和LCD 显示参数配置。其中背光控制引脚是独立出来的,修改背光引脚的同时也要修改对应的PWM 设备信息。
LCD 引脚
设备树插件中使用到的引脚。
列表1: lcd 引脚
fragment@3 {
target=<&pinctrl>;
__overlay__{
lcd_backlight_pins_a: lcd-backlight {
pins {
pinmux = <STM32_PINMUX('A', 15, AF1)>; /* TIM2_CH1 */
bias-pull-down;
drive-push-pull;
slew-rate = <0>;
};
};
lcd_backlight_sleep_pins_a: lcd-backlight-sleep {
pins {
pinmux = <STM32_PINMUX('A', 15, ANALOG)>; /* TIM2_CH1 */
};
};
ltdc_pins_a: ltdc-a-0 {
pins {
pinmux = <STM32_PINMUX('G', 7, AF14)>, /* LCD_CLK */
<STM32_PINMUX('I', 10, AF14)>, /* LCD_HSYNC */
<STM32_PINMUX('I', 9, AF14)>, /* LCD_VSYNC */
<STM32_PINMUX('E', 13, AF14)>, /* LCD_DE */
<STM32_PINMUX('H', 2, AF14)>, /* LCD_R0 */
<STM32_PINMUX('H', 3, AF14)>, /* LCD_R1 */
<STM32_PINMUX('H', 8, AF14)>, /* LCD_R2 */
<STM32_PINMUX('B', 0, AF9)>, /* LCD_R3 */
<STM32_PINMUX('A', 5, AF14)>, /* LCD_R4 */
<STM32_PINMUX('C', 0, AF14)>, /* LCD_R5 */
<STM32_PINMUX('H', 12, AF14)>, /* LCD_R6 */
<STM32_PINMUX('E', 15, AF14)>, /* LCD_R7 */
<STM32_PINMUX('E', 14, AF13)>, /* LCD_G0 */
<STM32_PINMUX('E', 6, AF14)>, /* LCD_G1 */
<STM32_PINMUX('H', 13, AF14)>, /* LCD_G2 */
<STM32_PINMUX('H', 14, AF14)>, /* LCD_G3 */
<STM32_PINMUX('H', 15, AF14)>, /* LCD_G4 */
<STM32_PINMUX('I', 0, AF14)>, /* LCD_G5 */
<STM32_PINMUX('I', 1, AF14)>, /* LCD_G6 */
<STM32_PINMUX('I', 2, AF14)>, /* LCD_G7 */
<STM32_PINMUX('D', 9, AF14)>, /* LCD_B0 */
<STM32_PINMUX('G', 12, AF14)>, /* LCD_B1 */
<STM32_PINMUX('G', 10, AF14)>, /* LCD_B2 */
<STM32_PINMUX('D', 10, AF14)>, /* LCD_B3 */
<STM32_PINMUX('I', 4, AF14)>, /* LCD_B4 */
<STM32_PINMUX('A', 3, AF14)>, /* LCD_B5 */
<STM32_PINMUX('B', 8, AF14)>, /* LCD_B6 */
<STM32_PINMUX('D', 8, AF14)>; /* LCD_B7 */
bias-disable;
drive-push-pull;
slew-rate = <1>;
};
};
ltdc_pins_sleep_a: ltdc-a-1 {
pins {
pinmux = <STM32_PINMUX('G', 7, ANALOG)>, /* LCD_CLK */
<STM32_PINMUX('I', 10, ANALOG)>, /* LCD_HSYNC */
<STM32_PINMUX('I', 9, ANALOG)>, /* LCD_VSYNC */
<STM32_PINMUX('E', 13, ANALOG)>, /* LCD_DE */
<STM32_PINMUX('H', 2, ANALOG)>, /* LCD_R0 */
<STM32_PINMUX('H', 3, ANALOG)>, /* LCD_R1 */
<STM32_PINMUX('H', 8, ANALOG)>, /* LCD_R2 */
<STM32_PINMUX('B', 0, ANALOG)>, /* LCD_R3 */
<STM32_PINMUX('A', 5, ANALOG)>, /* LCD_R4 */
<STM32_PINMUX('C', 0, ANALOG)>, /* LCD_R5 */
<STM32_PINMUX('H', 12, ANALOG)>, /* LCD_R6 */
<STM32_PINMUX('E', 15, ANALOG)>, /* LCD_R7 */
<STM32_PINMUX('E', 14, ANALOG)>, /* LCD_G0 */
<STM32_PINMUX('E', 6, ANALOG)>, /* LCD_G1 */
<STM32_PINMUX('H', 13, ANALOG)>, /* LCD_G2 */
<STM32_PINMUX('H', 14, ANALOG)>, /* LCD_G3 */
<STM32_PINMUX('H', 15, ANALOG)>, /* LCD_G4 */
<STM32_PINMUX('I', 0, ANALOG)>, /* LCD_G5 */
<STM32_PINMUX('I', 1, ANALOG)>, /* LCD_G6 */
<STM32_PINMUX('I', 2, ANALOG)>, /* LCD_G7 */
<STM32_PINMUX('D', 9, ANALOG)>, /* LCD_B0 */
<STM32_PINMUX('G', 12, ANALOG)>, /* LCD_B1 */
<STM32_PINMUX('G', 10, ANALOG)>, /* LCD_B2 */
<STM32_PINMUX('D', 10, ANALOG)>, /* LCD_B3 */
<STM32_PINMUX('I', 4, ANALOG)>, /* LCD_B4 */
<STM32_PINMUX('A', 3, ANALOG)>, /* LCD_B5 */
<STM32_PINMUX('B', 8, ANALOG)>, /* LCD_B6 */
<STM32_PINMUX('D', 8, ANALOG)>; /* LCD_B7 */
};
};
};
};
如果修改了LCD 显示屏的引脚,需要在这里修改对应的引脚。
列表2: lcd 背光pwm 设置
fragment@1 {
target-path="/";
__overlay__{
lcd-backlight {
compatible = "pwm-backlight";
pwms = <&pwm2 0 1000000>;
brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
default-brightness-level = <90>;
status = "okay";
};
};
};
fragment@2 {
target=<&timers2>;
__overlay__{
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
pwm2: pwm {
pinctrl-0 = <&lcd_backlight_pins_a>;
pinctrl-1 = <&lcd_backlight_sleep_pins_a>;
pinctrl-names = "default", "sleep";
#pwm-cells = <2>;
status = "okay";
};
timer@1 {
status = "okay";
};
};
};
背光引脚被复用为PWM 的输出,如果修改了背光引脚也要在这里修改使用的pwm。
LCD 属性设置
通常情况我们参考官方开发板设计硬件LCD 使用的引脚和官方一致即可。我们经常要修改的是LCD 一些配置参数,例如分辨率、时钟、无效行数。
列表3: lcd 配置参数
/*-------第一组---------*/
clock-frequency = <27000000>;
hactive = <800>;
vactive = <480>;
/*-------第二组---------*/
hfront-porch = <23>;
hback-porch = <46>;
vback-porch = <22>;
vfront-porch = <22>;
/*-------第三组---------*/
hsync-len = <1>;
vsync-len = <1>;
/*-------第四组---------*/
hsync-active = <0>;
vsync-active = <0>;
de-active = <1>;
pixelclk-active = <0>;
配置参数可分为四组,第一组是设置分辨率和时钟。第二组设置“可视区域”,它们的缩写就是我们常说的HFP、hbp、vbp、vfp、行同步信号到第一个像素点的延时时间,单位(像素),一行的最后一个像素点到下一个行同步信号的延时时间(单位像素),帧同步信号到第一个有效行之间的时间,最后一行到下一个帧同步信号之间的时间。第三组,设置行同步信号和帧同步信号的脉宽。第四组,设置行同步信号、帧同步信号、数据信号、像素时钟信号的极性。以上内容要根据自己使用的显示屏说明文档配置。
由于野火的LCD 设备树以设备树插件的形式提供,我们可以使用file-config 软件配置屏幕参数。参考《fire-config 修改液晶参数》
测试程序
驱动已经编译进内核中,设备树插件加载成功后,驱动会生成“/dev/fb0”文件,这个文件就是
显示屏的设备节点文件。
测试程序通过读、写这个文件测试显示是否正常。
源码位于“linux_driver/add_lcd_device_tree/test_app”。
测试程序仅针对5 寸800*480 分辨率的显示屏,其他分辨率会出现显示异常及程序异常结束的情况。
进入源码目录,执行“make”命令可编译出测试代码,上传到开发板,使用chmod 添加执行权限后执行即可。
参考资料:嵌入式Linux 驱动开发实战指南-基于STM32MP1 系列