STM32MP157 Linux系统移植开发篇14:Linux内核RGB LCD驱动移植

本文章为《STM32MP157 Linux系统移植开发篇》系列中的一篇,笔者使用的开发平台为华清远见FS-MP1A开发板(STM32MP157开发板)。stm32mp157是ARM双核,2个A7核,1个M4核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统,STM32MP157开发板所以既可以学嵌入式linux,也可以学stm32单片机。

针对FS-MP1A开发板,除了Linux系统移植篇外,还包括其他多系列教程,包括Cortex-A7开发篇、Cortex-M4开发篇、扩展板驱动移植篇、Linux应用开发篇、FreeRTOS系统移植篇、Linux驱动开发篇、硬件设计篇、人工智能机器视觉篇、Qt应用编程篇、Qt综合项目实战篇等。欢迎关注,更多stm32mp157开发教程及视频,可加技术交流Q群459754978,感谢关注。

关于FS-MP1A开发板:
手机淘宝分享码:复制本行文字打开手淘₤T4FPXn3YYJ2₤
链接:https://item.taobao.com/item.htm?id=622457259672

1.实验原理

前文介绍过LTDC的内容,本节只需为LTDC添加一个面板即可。内核中包含一个通用的面板驱动,驱动之包含大量各种各样的面板。

  1. 驱动修改

驱动路径为:drivers/gpu/drm/panel/panel-simple.c

移植时可以在驱动中支持新的面板的内容,也可以找到一个与自己面板相仿的内容进行修改,本节即使用在原有面板修改的方法。如本节参考面板名称为zj070na-01p,对于一个面板最关键的内容在驱动通过drm_display_mode的结构体描述,zj070na-01p的描述如下:

static const struct drm_display_mode innolux_zj070na_01p_mode = {

.clock = 51501,

.hdisplay = 1024,

.hsync_start = 1024 + 128,

.hsync_end = 1024 + 128 + 64,

.htotal = 1024 + 128 + 64 + 128,

.vdisplay = 600,

.vsync_start = 600 + 16,

.vsync_end = 600 + 16 + 4,

.vtotal = 600 + 16 + 4 + 16,

.vrefresh = 60,

};

这个结构体主要用来描述面板的时序相关信息,时序框图如下:

hdisplay:有效显示区水平像素数量,对应Active Width

hsync_start:水平同步开始,对应hdispay + HFP

hsync_end:水平同步结束,对应hdisplay + HFP + HSYNC width(HPW)

htotal:水平总像素,对应hdisplay + HFP + HSYNC width + HBP

vdisplay:垂直显示像素,对应Active Height

vsync_start:垂直同步开始,对应vdispay + VFP

vsync_end:垂直像素结束,对应vdisplay + VFP + VSYNC width(VPW)

vtotal:垂直总像素,对应vdisplay + VFP + VSYNC width + VBP

vrefresh:刷新率

面板芯片手册中关于时序的描述如下:

表中可以确认HBP=140、HPW=20、HFP=160、VBP=20、VPW=3、VFP=12,修改面板信息如下:

static const struct drm_display_mode innolux_zj070na_01p_mode = {

.clock = 51501,

.hdisplay = 1024,

.hsync_start = 1024 + 160,

.hsync_end = 1024 + 160 + 20,

.htotal = 1024 + 160 + 20 + 140,

.vdisplay = 600,

.vsync_start = 600 + 12,

.vsync_end = 600 + 12 + 3,

.vtotal = 600 + 12 + 3 + 12,

.vrefresh = 60,

};

  1. 设备树修改

增加ltdc输出端口:

&ltdc {

status = "okay";

port {

#address-cells = <1>;

#size-cells = <0>;

ltdc_ep1_out: endpoint@1 {

reg = <1>;

remote-endpoint = <&panel_in_rgb>;

};

};

};

增加面板节点:

panel: panel-rgb {

compatible = "innolux,zj070na-01p";

pinctrl-names = "default", "sleep";

backlight = <&panel_backlight>;

status = "okay";

port {

panel_in_rgb: endpoint {

remote-endpoint = <&ltdc_ep1_out>;

};

};

};

  1. PWM设备节点

参考文档:

Documentation/devicetree/bindings/pwm/pwm-stm32.txt

内核中ST对STM32MP15x系列芯片的设备树资源了做了定义,可参见:

arch/arm/boot/dts/stm32mp151.dtsi

stm32mp151中timers2定义如下:

timers2: timer@40000000 {

#address-cells = <1>;

#size-cells = <0>;

compatible = "st,stm32-timers";

reg = <0x40000000 0x400>;

clocks = <&rcc TIM2_K>;

clock-names = "int";

dmas = <&dmamux1 18 0x400 0x80000001>,

<&dmamux1 19 0x400 0x80000001>,

<&dmamux1 20 0x400 0x80000001>,

<&dmamux1 21 0x400 0x80000001>,

<&dmamux1 22 0x400 0x80000001>;

dma-names = "ch1", "ch2", "ch3", "ch4", "up";

status = "disabled";

pwm {

compatible = "st,stm32-pwm";

#pwm-cells = <3>;

status = "disabled";

};

timer@1 {

compatible = "st,stm32h7-timer-trigger";

reg = <1>;

status = "disabled";

};

counter {

compatible = "st,stm32-timer-counter";

status = "disabled";

};

};

上述代码只对timers5做了基本的初始化,并没有针对不同的硬件设计做适配,所以需结合硬件补全设备树节点信息。

参考文档或stm32mp15xx-dkx.dtsi对于i2c设备节点的描述,增加timers内容如下:

&timers2 {

/* spare dmas for other usage */

/delete-property/dmas;

/delete-property/dma-names;

status = "okay";

pwm2: pwm {

pinctrl-0 = <&pwm2_pins_b>;

pinctrl-1 = <&pwm2_sleep_pins_b>;

pinctrl-names = "default", "sleep";

#pwm-cells = <2>;

status = "okay";

};

timer@2 {

status = "disabled";

};

};

stm32mp15-pinctrl.dtsi对于pwm2的描述与FS-MP1A所使用管脚不一致,所以无法直接使用,需参考其增加如下内容:

pwm2_pins_b: pwm2-0 {

pins {

pinmux = <STM32_PINMUX('A', 5, AF1)>; /* TIM2_CH1 */

bias-pull-down;

drive-push-pull;

slew-rate = <0>;

};

};

pwm2_sleep_pins_b: pwm1-sleep-0 {

pins {

pinmux = <STM32_PINMUX('A', 5, ANALOG)>; /* TIM2_CH1 */

};

};

  1. 背光设备节点

参考文档:

Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt

Documentation/devicetree/bindings/leds/backlight/gpio-backlight.txt

FS-MP1A背光可以通过GPIO驱动也可通过PWM2的通道1驱动,可以对比参考文档或内核中其他设备树关于背光的定义。

GPIO驱动背光节点内容如下:

panel_backlight: panel-backlight {

compatible = "gpio-backlight";

gpios = <&gpiod 13 GPIO_ACTIVE_LOW>;

default-on;

status = "okay";

};

PWM驱动背光节点内容如下:

panel_backlight: panel-backlight {

compatible = "pwm-backlight";

pwms = <&pwm2 0 5000000>;

brightness-levels = <0 4 8 16 32 64 128 255>;

default-brightness-level = <6>;

status = "okay";

};

2.实验目的

熟悉基于Linux操作系统下的摄像头设备驱动移植配置过程。

3.实验平台

华清远见开发环境,FS-MP1A平台;

4.实验步骤

  1. 导入交叉编译工具链

linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

  1. 增加设备树文件

由于RGB LCD并非FS-MP1A必须配置,本节增加一个设备树文件,对应增加了屏幕的设备。

在内核的arch/arm/boot/dts目录下新建文件stm32mp157a-fsmp1a-rgb070.dts文件并添加如下内容:

#include "stm32mp157a-fsmp1a.dts"

/ {

model = "HQYJ STM32MP157 FSMP1A RGB Discovery Board";

compatible = "st,stm32mp157a-dk1", "st,stm32mp157";

};

由于增加了新的设备树文件需修改arch/arm/boot/dts/Makefile,在文件中增加新的条目,红色字体部分为增加内容

dtb-$(CONFIG_ARCH_STM32) += \

…..

stm32mp157a-dk1.dtb \

stm32mp157a-fsmp1a.dtb \

stm32mp157a-fsmp1a-mipi050.dtb \

stm32mp157a-fsmp1a-rgb070.dtb \

stm32mp157d-dk1.dtb \

  1. 添加pwm2内容

修改stm32mp15xx-fsmp1x.dtsi,在stm32mp15xx-fsmp1x.dtsi文件末尾添加如下内容:

&timers2 {

/* spare dmas for other usage */

/delete-property/dmas;

/delete-property/dma-names;

status = "okay";

pwm2: pwm {

pinctrl-0 = <&pwm2_pins_b>;

pinctrl-1 = <&pwm2_sleep_pins_b>;

pinctrl-names = "default", "sleep";

#pwm-cells = <2>;

status = "okay";

};

timer@2 {

status = "disabled";

};

};

&pinctrl {

pwm2_pins_b: pwm2-0 {

pins {

pinmux = <STM32_PINMUX('A', 5, AF1)>; /* TIM2_CH1 */

bias-pull-down;

drive-push-pull;

slew-rate = <0>;

};

};

pwm2_sleep_pins_b: pwm1-sleep-0 {

pins {

pinmux = <STM32_PINMUX('A', 5, ANALOG)>; /* TIM2_CH1 */

};

};

};

  1. 添加背光内容

修改stm32mp15xx-fsmp1x.dtsi,在根节点中添加如下内容:

panel_backlight: panel-backlight {

compatible = "pwm-backlight";

pwms = <&pwm2 0 5000000>;

brightness-levels = <0 4 8 16 32 64 128 255>;

default-brightness-level = <6>;

status = "okay";

};

  1. 添加ltdc端口

修改文件arm/arm/boot/dts/stm32mp157a-fsmp1a-rgb070.dts,在文件末尾添加如下内容:

&ltdc {

status = "okay";

port {

#address-cells = <1>;

#size-cells = <0>;

ltdc_ep1_out: endpoint@1 {

reg = <1>;

remote-endpoint = <&panel_in_rgb>;

};

};

};

  1. 添加面板信息

修改文件arm/arm/boot/dts/stm32mp157a-fsmp1a-rgb070.dts,在根节点中添加如下内容:

panel: panel-rgb {

compatible = "innolux,zj070na-01p";

pinctrl-names = "default", "sleep";

backlight = <&panel_backlight>;

status = "okay";

port {

panel_in_rgb: endpoint {

remote-endpoint = <&ltdc_ep1_out>;

};

};

};

  1. 修改面板驱动,修改面板时序参数

修改文件drivers/gpu/drm/panel/panel-simple.c,修改zj070na-01p面板信息,对照面板芯片手册修改原有内容,红色字体部分为修改内容:

static const struct drm_display_mode innolux_zj070na_01p_mode = {

.clock = 51501,

.hdisplay = 1024,

.hsync_start = 1024 + 160,

.hsync_end = 1024 + 160 + 20,

.htotal = 1024 + 160 + 20 + 140,

.vdisplay = 600,

.vsync_start = 600 + 12,

.vsync_end = 600 + 12 + 3,

.vtotal = 600 + 12 + 3 + 12,

.vrefresh = 60,

};

  1. 配置内核

由于内核默认支持通用面板驱动,本节列出主要选项,如下

linux@ubuntu:$ make menuconfig

Device Drivers --->

Graphics support --->

<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->

<*> DRM Support for STMicroelectronics SoC Series

Display Panels --->

<*> support for simple panels

Backlight & LCD device support --->

<*> Generic PWM based Backlight Driver

  1. 增加启动项

在虚拟机/tftpboot /tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17末尾添加

LABEL stm32mp157a-fsmp1a-mipi
KERNEL /uImage
FDT /stm32mp157a-fsmp1a-rgb070.dtb
APPEND root=/dev/mmcblk1p4 rootwait rw console=ttySTM0,115200

  1. 编译内核及设备树

linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040

  1. 重启测试

安装上7寸LCD面板,将编译好的设备树和内核镜像拷贝到/tftpboot目录下,通过tftp引导内核,启动后可正常显示,如果屏幕显示不正可适当调节面板参数。

硬件平台:华清远见FS-MP1A开发板(STM32MP157)

部分开发教程下载:加QQ群459754978,群文件里有。

部分视频课程收看:华清远见研发中心的个人空间_哔哩哔哩_Bilibili

淘宝购买链接:华清远见stm32mp157 linux开发板stm32单片机arm开发嵌入式学习板

手机淘宝分享码:复制本行文字打开手淘₤T4FPXn3YYJ2₤

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值