STM32MP157 Linux系統(tǒng)移植開發(fā)篇11:Linux HDMI驅(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.1實(shí)驗(yàn)原理
STM32MP157A系列SoC中默認(rèn)沒有HDMI相關(guān)控制器,F(xiàn)S-MP1A使用SiI9022芯片將RGB信號(hào)轉(zhuǎn)化為HDMI信號(hào)。STM32MP157A集成LTDC(LCD-TFT Display Controller),提供一個(gè)24bit RGB并行接口用于連接到各種LCD和TFT面板。

SiI9022芯片通過I2C5總線與SoC進(jìn)行交互,通過SoC的LCD_PCLK、LCD_VSYNC、LCD_HSYNC、LCD_DEN與RGB信號(hào)線來進(jìn)行圖像信號(hào)的傳輸,通過I2S2總線進(jìn)行音頻數(shù)據(jù)的傳輸。

查看原理圖確認(rèn)I2C5、中斷、復(fù)位管腳對(duì)應(yīng)關(guān)系:

原理圖網(wǎng)絡(luò)編號(hào)對(duì)應(yīng)管腳管腳功能管腳功能碼I2C5_SCLPA11I2C5_SCLAF4I2C5_SDAPA12I2C5_SDAAF4HDMI_RSTPA13GPIOHDMI_INTPA14INT
LCD接口管腳對(duì)應(yīng)關(guān)系:

原理圖網(wǎng)絡(luò)編號(hào)對(duì)應(yīng)管腳管腳功能管腳功能碼LCD_R0PI15LCD_R0AF14LCD_R1PJ0LCD_R1AF14LCD_R2PJ1LCD_R2AF14LCD_R3PJ2LCD_R3AF14LCD_R4PJ3LCD_R4AF14LCD_R5PJ4LCD_R5AF14LCD_R6PJ5LCD_R6AF14LCD_R7PJ6LCD_R7AF14LCD_G0PJ8LCD_G0AF14LCD_G1PJ7LCD_G1AF14LCD_G2PJ10LCD_G2AF14LCD_G3PJ19LCD_G3AF14LCD_G4PJ11LCD_G4AF14LCD_G5PK0LCD_G5AF14LCD_G6PK1LCD_G6AF14LCD_G7PK2LCD_G7AF14LCD_B0PJ12LCD_B0AF14LCD_B1PJ13LCD_B1AF14LCD_B2PJ14LCD_B2AF14LCD_B3PJ15LCD_B3AF14LCD_B4PK3LCD_B4AF14LCD_B5PK4LCD_B5AF14LCD_B6PK5LCD_B6AF14LCD_B7PK6LCD_B7AF14LCD_PCLKPI14LCD_PCLKAF14LCD_DENPK7LCD_DENAF14LCD_HSYNCPI12LCD_HSYNCAF14LCD_VSYNCPI13LCD_VSYNCAF14
I2C5設(shè)備樹節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/i2c/i2c-stm32.txt
內(nèi)核中ST對(duì)STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
arch/arm/boot/dts/stm32mp151.dtsi
stm32mp151中i2c5定義如下:
i2c5: i2c@40015000 {
compatible = "st,stm32mp15-i2c";
reg = <0x40015000 0x400>;
interrupt-names = "event", "error";
interrupts-extended = <&exti 25 IRQ_TYPE_LEVEL_HIGH>,
<&intc GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc I2C5_K>;
resets = <&rcc I2C5_R>;
#address-cells = <1>;
#size-cells = <0>;
dmas = <&dmamux1 115 0x400 0x80000001>,
<&dmamux1 116 0x400 0x80000001>;
dma-names = "rx", "tx";
power-domains = <&pd_core>;
st,syscfg-fmp = <&syscfg 0x4 0x10>;
wakeup-source;
status = "disabled";
};
上述代碼只對(duì)i2c5做了基本的初始化,并沒有針對(duì)不同的硬件設(shè)計(jì)做適配,所以需結(jié)合硬件補(bǔ)全設(shè)備樹節(jié)點(diǎn)信息。
參考stm32mp15xx-dkx.dtsi對(duì)于i2c設(shè)備節(jié)點(diǎn)的描述,修改i2c5內(nèi)容如下:
&i2c5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_pins_a>;
pinctrl-1 = <&i2c5_pins_sleep_a>;
i2c-scl-rising-time-ns = <100>;
i2c-scl-falling-time-ns = <7>;
clock-frequency = <100000>;
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
};
由于stm32mp15-pinctrl.dtsi中對(duì)于i2c5_pins_a和i2c5_pins_sleep_a的定義與板子實(shí)際使用管腳一致,所以無需修改,內(nèi)容如下:
i2c5_pins_a: i2c5-0 {
pins {
pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
<STM32_PINMUX('A', 12, AF4)>; /* I2C5_SDA */
bias-disable;
drive-open-drain;
slew-rate = <0>;
};
};
i2c5_pins_sleep_a: i2c5-1 {
pins {
pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* I2C5_SCL */
<STM32_PINMUX('A', 12, ANALOG)>; /* I2C5_SDA */
};
};
I2S2設(shè)備樹節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/i2c/sound/st,stm32-i2s.txt
LTDC設(shè)備樹節(jié)點(diǎn)
SiI9022實(shí)現(xiàn)HDMI輸出需要RGB信號(hào)作為數(shù)據(jù)源,LTDC為STM32MP157的LCD顯示控制器,可以輸出24bit的并行數(shù)據(jù),HDMI顯示首先需要驅(qū)動(dòng)LTDC。
參考文檔:
Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
內(nèi)核中ST對(duì)STM32MP15x系列芯片的設(shè)備樹資源了做了定義,可參見:
arch/arm/boot/dts/stm32mp151.dtsi
stm32mp151中l(wèi)tdc定義如下:
ltdc: display-controller@5a001000 {
compatible = "st,stm32-ltdc";
reg = <0x5a001000 0x400>;
interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc LTDC_PX>;
clock-names = "lcd";
resets = <&rcc LTDC_R>;
status = "disabled";
};
上述代碼只對(duì)ltdc做了基本的初始化,并沒有針對(duì)不同的硬件設(shè)計(jì)做適配,所以需結(jié)合硬件補(bǔ)全設(shè)備樹節(jié)點(diǎn)信息。
參考stm32mp15xx-dkx.dtsi對(duì)于ltdc設(shè)備節(jié)點(diǎn)的描述,需增加內(nèi)容如下:
<dc {
pinctrl-names = "default", "sleep";
pinctrl-0 = <<dc_pins_b>;
pinctrl-1 = <<dc_pins_sleep_b>;
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep0_out: endpoint@0 {
reg = <0>;
/*圖像輸出通道,需對(duì)接顯示設(shè)備*/
remote-endpoint = <&sii9022_in>;
};
};
};
由于stm32mp15-pinctrl.dtsi中對(duì)于ltdc_pins_b和ltdc_pins_b的定于與板子實(shí)際使用管腳一致,所以無需修改,內(nèi)容如下:
ltdc_pins_b: ltdc-b-0 {
pins {
pinmux = <STM32_PINMUX('I', 14, AF14)>, /* LCD_CLK */
<STM32_PINMUX('I', 12, AF14)>, /* LCD_HSYNC */
<STM32_PINMUX('I', 13, AF14)>, /* LCD_VSYNC */
<STM32_PINMUX('K', 7, AF14)>, /* LCD_DE */
<STM32_PINMUX('I', 15, AF14)>, /* LCD_R0 */
<STM32_PINMUX('J', 0, AF14)>, /* LCD_R1 */
<STM32_PINMUX('J', 1, AF14)>, /* LCD_R2 */
<STM32_PINMUX('J', 2, AF14)>, /* LCD_R3 */
<STM32_PINMUX('J', 3, AF14)>, /* LCD_R4 */
<STM32_PINMUX('J', 4, AF14)>, /* LCD_R5 */
<STM32_PINMUX('J', 5, AF14)>, /* LCD_R6 */
<STM32_PINMUX('J', 6, AF14)>, /* LCD_R7 */
<STM32_PINMUX('J', 7, AF14)>, /* LCD_G0 */
<STM32_PINMUX('J', 8, AF14)>, /* LCD_G1 */
<STM32_PINMUX('J', 9, AF14)>, /* LCD_G2 */
<STM32_PINMUX('J', 10, AF14)>, /* LCD_G3 */
<STM32_PINMUX('J', 11, AF14)>, /* LCD_G4 */
<STM32_PINMUX('K', 0, AF14)>, /* LCD_G5 */
<STM32_PINMUX('K', 1, AF14)>, /* LCD_G6 */
<STM32_PINMUX('K', 2, AF14)>, /* LCD_G7 */
<STM32_PINMUX('J', 12, AF14)>, /* LCD_B0 */
<STM32_PINMUX('J', 13, AF14)>, /* LCD_B1 */
<STM32_PINMUX('J', 14, AF14)>, /* LCD_B2 */
<STM32_PINMUX('J', 15, AF14)>, /* LCD_B3 */
<STM32_PINMUX('K', 3, AF14)>, /* LCD_B4 */
<STM32_PINMUX('K', 4, AF14)>, /* LCD_B5 */
<STM32_PINMUX('K', 5, AF14)>, /* LCD_B6 */
<STM32_PINMUX('K', 6, AF14)>; /* LCD_B7 */
bias-disable;
drive-push-pull;
slew-rate = <1>;
};
};
ltdc_pins_sleep_b: ltdc-b-1 {
pins {
pinmux = <STM32_PINMUX('I', 14, ANALOG)>, /* LCD_CLK */
<STM32_PINMUX('I', 12, ANALOG)>, /* LCD_HSYNC */
<STM32_PINMUX('I', 13, ANALOG)>, /* LCD_VSYNC */
<STM32_PINMUX('K', 7, ANALOG)>, /* LCD_DE */
<STM32_PINMUX('I', 15, ANALOG)>, /* LCD_R0 */
<STM32_PINMUX('J', 0, ANALOG)>, /* LCD_R1 */
<STM32_PINMUX('J', 1, ANALOG)>, /* LCD_R2 */
<STM32_PINMUX('J', 2, ANALOG)>, /* LCD_R3 */
<STM32_PINMUX('J', 3, ANALOG)>, /* LCD_R4 */
<STM32_PINMUX('J', 4, ANALOG)>, /* LCD_R5 */
<STM32_PINMUX('J', 5, ANALOG)>, /* LCD_R6 */
<STM32_PINMUX('J', 6, ANALOG)>, /* LCD_R7 */
<STM32_PINMUX('J', 7, ANALOG)>, /* LCD_G0 */
<STM32_PINMUX('J', 8, ANALOG)>, /* LCD_G1 */
<STM32_PINMUX('J', 9, ANALOG)>, /* LCD_G2 */
<STM32_PINMUX('J', 10, ANALOG)>, /* LCD_G3 */
<STM32_PINMUX('J', 11, ANALOG)>, /* LCD_G4 */
<STM32_PINMUX('K', 0, ANALOG)>, /* LCD_G5 */
<STM32_PINMUX('K', 1, ANALOG)>, /* LCD_G6 */
<STM32_PINMUX('K', 2, ANALOG)>, /* LCD_G7 */
<STM32_PINMUX('J', 12, ANALOG)>, /* LCD_B0 */
<STM32_PINMUX('J', 13, ANALOG)>, /* LCD_B1 */
<STM32_PINMUX('J', 14, ANALOG)>, /* LCD_B2 */
<STM32_PINMUX('J', 15, ANALOG)>, /* LCD_B3 */
<STM32_PINMUX('K', 3, ANALOG)>, /* LCD_B4 */
<STM32_PINMUX('K', 4, ANALOG)>, /* LCD_B5 */
<STM32_PINMUX('K', 5, ANALOG)>, /* LCD_B6 */
<STM32_PINMUX('K', 6, ANALOG)>; /* LCD_B7 */
};
};
SiI9022設(shè)備樹節(jié)點(diǎn)
參考文檔:
Documentation/devicetree/bindings/display/arm,hdlcd.txt
由于SiI9002只是I2C5總線上的一個(gè)外設(shè),所以STM32MP157A的通用設(shè)備樹文件中并沒有相關(guān)的定義,結(jié)合arm,hdlcd.txt和stm32mp15xx-dkx.dtsi對(duì)于HDMI的描述,增加SiI9002的支持,需在I2C5節(jié)點(diǎn)下添加相關(guān)信息,添加內(nèi)容為:
hdmi-transmitter@39 {
compatible = "sil,sii9022";
reg = <0x39>;
iovcc-supply = <&v3v3_hdmi>;
cvcc12-supply = <&v1v2_hdmi>;
reset-gpios = <&gpioa 10 GPIO_ACTIVE_LOW>;
interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpiog>;
#sound-dai-cells = <0>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
sii9022_in: endpoint {
/*視頻輸入端口,與LTDC輸出端口對(duì)接*/
remote-endpoint = <<dc_ep0_out>;
};
};
port@3 {
reg = <3>;
sii9022_tx_endpoint: endpoint {
/*音頻輸入端口,與聲卡輸出端口對(duì)接*/
remote-endpoint = <&i2s2_endpoint>;
};
};
};
};
電源節(jié)點(diǎn)添加
由于內(nèi)核中很多驅(qū)動(dòng)會(huì)根據(jù)電源的方位調(diào)整設(shè)備的工作方式,所以在設(shè)備樹中需要傳遞相關(guān)電源電壓參數(shù),如sii9022驅(qū)動(dòng)中需要兩個(gè)電源分別是iovcc和cvcc12,但是在設(shè)備樹中并沒有這兩個(gè)電源的定義,官方參考板DK1使用的是MPU作為電源管理,而FS-MP1A使用的分離元器件的形式,所以stm32mp15xx-dkx.dtsi中對(duì)于電源的定義就不實(shí)用了。參考內(nèi)核中相關(guān)文檔添加固定電源節(jié)點(diǎn)的形式添加iovcc和cvcc12即可,根據(jù)sii9022的需求,iovcc和cvcc12電壓分別為3.3v和1.2v。
參考文檔
Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
需在設(shè)備樹根節(jié)點(diǎn)下添加,內(nèi)容如下:
v3v3_hdmi: regulator-v3v3-hdmi {
compatible = "regulator-fixed";
regulator-name = "v3v3_hdmi ";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v2_hdmi: regulator-v1v2-hdmi {
compatible = "regulator-fixed";
regulator-name = "v1v2_hdmi";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
};
1.2實(shí)驗(yàn)?zāi)康?/h1>
熟悉基于Linux操作系統(tǒng)下的HDMI設(shè)備驅(qū)動(dòng)移植配置過程。
1.3實(shí)驗(yàn)平臺(tái)
華清遠(yuǎn)見開發(fā)環(huán)境,F(xiàn)S-MP1A平臺(tái);
1.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
添加i2c5及sii9022內(nèi)容
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下內(nèi)容:
&i2c5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&i2c5_pins_a>;
pinctrl-1 = <&i2c5_pins_sleep_a>;
i2c-scl-rising-time-ns = <100>;
i2c-scl-falling-time-ns = <7>;
clock-frequency = <100000>;
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
hdmi-transmitter@39 {
compatible = "sil,sii9022";
reg = <0x39>;
iovcc-supply = <&v3v3_hdmi>;
cvcc12-supply = <&v1v2_hdmi>;
reset-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
interrupts = <14 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpioa>;
#sound-dai-cells = <0>;
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
sii9022_in: endpoint {
remote-endpoint = <<dc_ep0_out>;
};
};
};
};
};
添加ltdc內(nèi)容
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下內(nèi)容:
<dc {
pinctrl-names = "default", "sleep";
pinctrl-0 = <<dc_pins_b>;
pinctrl-1 = <<dc_pins_sleep_b>;
status = "okay";
port {
#address-cells = <1>;
#size-cells = <0>;
ltdc_ep0_out: endpoint@0 {
reg = <0>;
remote-endpoint = <&sii9022_in>;
};
};
};
添加電源內(nèi)容
修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在根節(jié)點(diǎn)末尾添加如下內(nèi)容:
v3v3_hdmi: regulator-v3v3-hdmi {
compatible = "regulator-fixed";
regulator-name = "v3v3_hdmi ";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
v1v2_hdmi: regulator-v1v2-hdmi {
compatible = "regulator-fixed";
regulator-name = "v1v2_hdmi";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-always-on;
regulator-boot-on;
};
配置內(nèi)核
由于內(nèi)核源碼默認(rèn)配置以及支持sii902x,本節(jié)列出主要選項(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
Display Interface Bridges --->
<*> Silicon Image sii902x RGB/HDMI bridge
編譯內(nèi)核及設(shè)備樹:
linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
重啟測試
將編譯好的設(shè)備樹和內(nèi)核鏡像拷貝到/tftpboot目錄下,通過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,群文件里有。
淘寶購買鏈接:https://item.taobao.com/item.htm?id=622457259672
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?