STM32MP157 Linux系統(tǒng)移植開發(fā)篇12:Linux內(nèi)核MIPI LCD驅(qū)動(dòng)移植
本文章為《STM32MP157 Linux系統(tǒng)移植開發(fā)篇》系列中的一篇,筆者使用的開發(fā)平臺(tái)為華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157開發(fā)板)。stm32mp157是ARM雙核,2個(gè)A7核,1個(gè)M4核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實(shí)時(shí)操作系統(tǒng),STM32MP157開發(fā)板所以既可以學(xué)嵌入式linux,也可以學(xué)stm32單片機(jī)。
針對(duì)FS-MP1A開發(fā)板,除了Linux系統(tǒng)移植篇外,還包括其他多系列教程,包括Cortex-A7開發(fā)篇、Cortex-M4開發(fā)篇、擴(kuò)展板驅(qū)動(dòng)移植篇、Linux應(yīng)用開發(fā)篇、FreeRTOS系統(tǒng)移植篇、Linux驅(qū)動(dòng)開發(fā)篇、硬件設(shè)計(jì)篇、人工智能機(jī)器視覺篇、Qt應(yīng)用編程篇、Qt綜合項(xiàng)目實(shí)戰(zhàn)篇等。歡迎關(guān)注,更多stm32mp157開發(fā)教程及視頻,可加技術(shù)交流Q群459754978,感謝關(guān)注。
關(guān)于FS-MP1A開發(fā)板:
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?
鏈接:https://item.taobao.com/item.htm?id=622457259672
1.實(shí)驗(yàn)原理
DSI(Display Serial Interface),是有MIPI聯(lián)盟定義的一組通信協(xié)議的一部分,MIPI DSI主機(jī)控制器是一個(gè)數(shù)字核心,實(shí)現(xiàn)MIPI DSI規(guī)范中定義的所有協(xié)議功能。它提供了系統(tǒng)和MIPI D_PHY中間的接口,允許用戶和符合DSI的顯示器進(jìn)行通信。STM32MP157A系列芯片集成MIPI DSI主機(jī)控制器。
MIPI?DSI主機(jī)包括內(nèi)部連接到LTDC的專用視頻接口以及一個(gè)通用的APB接口,可用于向顯示器傳輸信息。

FS-MP1A提供兩組LCD顯示接口,分別是RGB和MIPI接口,本節(jié)介紹如何在Linux中完成MIPI LCD的支持。

上圖為MIPI LCD的接口,接口信號(hào)線分為兩組,分別是由DSI_D0P、DSI_D0N、DSI_D1P、DSI_D1N、DSI_CKP、DSI_CKN、DSI_TE、DSI_RST、LCD_PWM組成的LCD接口和由I2C2_SCL、I2C2_SDA、TP_RST、TP_IRQ組成的觸摸屏接口,本節(jié)介紹LCD的支持。
DSI_D0P、DSI_D0N、DSI_D1P、DSI_D1N、DSI_CKP、DSI_CKN是DSI-MIPI的信號(hào)線,DSI_TE未使用,DSI_RST是LCD屏復(fù)位信號(hào)LCD_PWM是背光控制信號(hào)。
MIPI LCD接口管腳對(duì)應(yīng)關(guān)系:




原理圖網(wǎng)絡(luò)編號(hào)對(duì)應(yīng)管腳管腳功能管腳功能碼DSI_D0PDSI_D0PDSI_D0PDSI信號(hào)線對(duì)應(yīng)管腳為單一功能管腳DSI_D0NDSI_D0NDSI_D0NDSI_D1PDSI_D1PDSI_D1PDSI_D1NDSI_D1NDSI_D1NDSI_CKPDSI_CKPDSI_CKPDSI_CKNDSI_CKNDSI_CKNDSI_TEPC6IODSI_RSTPG9IOLCD_PWMPA5TIM2_CH1AF1
PWM設(shè)備節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/pwm/pwm-stm32.txt
內(nèi)核中ST對(duì)STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
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";
};
};
上述代碼只對(duì)timers5做了基本的初始化,并沒有針對(duì)不同的硬件設(shè)計(jì)做適配,所以需結(jié)合硬件補(bǔ)全設(shè)備樹節(jié)點(diǎn)信息。
參考文檔或stm32mp15xx-dkx.dtsi對(duì)于i2c設(shè)備節(jié)點(diǎn)的描述,增加timers內(nèi)容如下:
&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對(duì)于pwm2的描述與FS-MP1A所使用管腳不一致,所以無(wú)法直接使用,需參考其增加如下內(nèi)容:
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 */
};
};
背光設(shè)備節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
Documentation/devicetree/bindings/leds/backlight/gpio-backlight.txt
FS-MP1A背光可以通過(guò)GPIO驅(qū)動(dòng)也可通過(guò)PWM2的通道1驅(qū)動(dòng),可以對(duì)比參考文檔或內(nèi)核中其他設(shè)備樹關(guān)于背光的定義。
GPIO驅(qū)動(dòng)背光節(jié)點(diǎn)內(nèi)容如下:
panel_backlight: panel-backlight {
compatible = "gpio-backlight";
gpios = <&gpiod 13 GPIO_ACTIVE_LOW>;
default-on;
status = "okay";
};
PWM驅(qū)動(dòng)背光節(jié)點(diǎn)內(nèi)容如下:
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";
};
LTDC設(shè)備節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
由于前面章節(jié)已經(jīng)對(duì)LTDC做了講解,并且已經(jīng)增加了LTDC的設(shè)備節(jié)點(diǎn),本節(jié)只需在原有基礎(chǔ)上增加DSI對(duì)應(yīng)的數(shù)據(jù)通道即可。
<dc {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep1_out: endpoint@1 {
reg = <1>;
remote-endpoint = <&dsi_in>;
};
};
};
Panel設(shè)備樹節(jié)點(diǎn)
參考文檔
Documentation/devicetree/bindings/display/panel/panel-dsi-cm.txt
結(jié)合參考文檔及內(nèi)核中STM32MP157其他設(shè)備樹文件,Panel設(shè)備樹節(jié)點(diǎn)為:
panel: panel@0 {
compatible = "sitronix,st7701";
reg = <0>;
reset-gpios = <&gpiog 9 GPIO_ACTIVE_HIGH>;
power-supply = <&v3v3>;
status = "okay";
port {
panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
};
DSI設(shè)備樹節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/display/mipi-dsi-bus.txt
內(nèi)核中ST對(duì)STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
arch/arm/boot/dts/stm32mp157.dtsi
stm32mp157中dsi定義如下:
dsi: dsi@5a000000 {
compatible = "st,stm32-dsi";
reg = <0x5a000000 0x800>;
phy-dsi-supply = <®18>;
clocks = <&rcc DSI_K>, <&scmi0_clk CK_SCMI0_HSE>, <&rcc DSI_PX>;
clock-names = "pclk", "ref", "px_clk";
resets = <&rcc DSI_R>;
reset-names = "apb";
status = "disabled";
};
上述代碼只對(duì)dsi做了基本的初始化,并沒有針對(duì)不同的硬件設(shè)計(jì)做適配,所以需結(jié)合硬件補(bǔ)全設(shè)備樹節(jié)點(diǎn)信息。補(bǔ)齊后內(nèi)容如下:
&dsi {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi_in: endpoint {
remote-endpoint = <<dc_ep1_out>;
};
};
port@1 {
reg = <1>;
dsi_out: endpoint {
remote-endpoint = <&dsi_panel_in>;
};
};
};
panel_dsi: panel-dsi@0 {
compatible = "sitronix,st7701";
reg = <0>;
reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>;
backlight = <&panel_backlight>;
power-supply = <&v3v3>;
status = "okay";
port {
dsi_panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
};
};
2.實(shí)驗(yàn)?zāi)康?/h1>
熟悉基于Linux操作系統(tǒng)下的MIPI-LCD設(shè)備驅(qū)動(dòng)移植配置過(guò)程。
3.實(shí)驗(yàn)平臺(tái)
華清遠(yuǎn)見開發(fā)環(huán)境,F(xiàn)S-MP1A平臺(tái);
4.實(shí)驗(yàn)步驟
導(dǎo)入交叉編譯工具鏈
linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
添加MIPI-LCD驅(qū)動(dòng)
FS-MP1A配套MIPI屏幕主控芯片是st7701,內(nèi)核中并沒有提供其的驅(qū)動(dòng),所以需要移植st7701的驅(qū)動(dòng)
將【華清遠(yuǎn)見-FS-MP1A開發(fā)資料\02-程序源碼\04-Linux系統(tǒng)移植\04-移植相關(guān)文件\02-Linux內(nèi)核移植\st7701驅(qū)動(dòng)】下的panel-sitronix-st7701.c復(fù)制到內(nèi)核源碼下的drivers/gpu/drm/panel/目錄下。
linux@ubuntu $> cp panel-sitronix-st7701.c drivers/gpu/drm/panel/
添加pwm2內(nèi)容
修改stm32mp15xx-fsmp1x.dtsi,在stm32mp15xx-fsmp1x.dtsi文件末尾添加如下內(nèi)容:
&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 */
};
};
};
添加背光內(nèi)容
修改stm32mp15xx-fsmp1x.dtsi,在根節(jié)點(diǎn)中添加如下內(nèi)容:
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";
};
增加設(shè)備樹文件
由于MIPI LCD并非FS-MP1A必須配置,本節(jié)增加一個(gè)設(shè)備樹文件,對(duì)應(yīng)增加了屏幕的設(shè)備。
在內(nèi)核的arch/arm/boot/dts目錄下新建文件stm32mp157a-fsmp1a-mipi050.dts文件并添加如下內(nèi)容:
#include "stm32mp157a-fsmp1a.dts"
/ {
model = "HQYJ STM32MP157 FSMP1A MIPI Discovery Board";
compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
};
由于增加了新的設(shè)備樹文件需修改arch/arm/boot/dts/Makefile,在文件中增加新的條目,紅色字體部分為增加內(nèi)容
dtb-$(CONFIG_ARCH_STM32) += \
…..
stm32mp157a-dk1.dtb \
stm32mp157a-fsmp1a.dtb \
stm32mp157a-fsmp1a-mipi050.dtb \
stm32mp157d-dk1.dtb \
添加ltdc內(nèi)容
修改stm32mp157a-fsmp1a-mipi050.dts,在文件末尾添加如下內(nèi)容:
<dc {
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep1_out: endpoint@1 {
reg = <1>;
remote-endpoint = <&dsi_in>;
};
};
};
添加dts內(nèi)容
修改stm32mp157a-fsmp1a-mipi050.dts,在文件末尾添加如下內(nèi)容:
&dsi {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
dsi_in: endpoint {
remote-endpoint = <<dc_ep1_out>;
};
};
port@1 {
reg = <1>;
dsi_out: endpoint {
remote-endpoint = <&dsi_panel_in>;
};
};
};
panel_dsi: panel-dsi@0 {
compatible = "sitronix,st7701";
reg = <0>;
reset-gpios = <&gpiog 9 GPIO_ACTIVE_HIGH>;
power-supply = <&v3v3>;
status = "okay";
port {
dsi_panel_in: endpoint {
remote-endpoint = <&dsi_out>;
};
};
};
};
配置內(nèi)核
配置內(nèi)核支持st7701,并列出主要選項(xiàng),如下:
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
<*> STMicroelectronics specific extensions for Synopsys MIPI DSI
Display Panels --->
<*> Sitronix ST7701 panel driver
Backlight & LCD device support --->
<*> Generic PWM based Backlight Driver
<*> Generic GPIO based Backlight Driver
增加啟動(dòng)項(xiàng)
在虛擬機(jī)/tftpboot /tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17末尾添加
LABEL stm32mp157a-fsmp1a-mipi
KERNEL /uImage
FDT /stm32mp157a-fsmp1a-mipi050.dtb
APPEND root=/dev/mmcblk1p4 rootwait rw console=ttySTM0,115200
編譯內(nèi)核及設(shè)備樹
linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
重啟測(cè)試
將編譯好的設(shè)備樹和內(nèi)核鏡像拷貝到/tftpboot目錄下,通過(guò)tftp引導(dǎo)內(nèi)核,設(shè)備連接HDMI顯示器,重啟設(shè)備后查看/sys/class/drm會(huì)多出HMID的信息,同時(shí)顯示器會(huì)有顯示。
硬件平臺(tái):華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157)
部分開發(fā)教程下載:加QQ群459754978,群文件里有。
淘寶購(gòu)買鏈接:華清遠(yuǎn)見stm32mp157 linux開發(fā)板stm32單片機(jī)arm開發(fā)嵌入式學(xué)習(xí)板
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?