Linux内核-HDMI驱动移植

来自华清远见研发中心
跳转至: 导航搜索

实验原理

STM32MP157A系列SoC中默认没有HDMI相关控制器,FS-MP1A使用SiI9022芯片将RGB信号转化为HDMI信号。STM32MP157A集成LTDC(LCD-TFT Display Controller),提供一个24bit RGB并行接口用于连接到各种LCD和TFT面板。

51-1-1-1.png

SiI9022芯片通过I2C5总线与SoC进行交互,通过SoC的LCD_PCLK、LCD_VSYNC、LCD_HSYNC、LCD_DEN与RGB信号线来进行图像信号的传输,通过I2S2总线进行音频数据的传输。

51-1-1-2.png

查看原理图确认I2C5、中断、复位管脚对应关系:

51-1-1-3.png

原理图网络编号 对应管脚 管脚功能 管脚功能码
I2C5_SCL PA11 I2C5_SCL AF4
I2C5_SDA PA12 I2C5_SDA AF4
HDMI_RST PA13 GPIO
HDMI_INT PA14 INT

LCD接口管脚对应关系:

51-1-1-4.png

原理图网络编号 对应管脚 管脚功能 管脚功能码
LCD_R0 PI15 LCD_R0 AF14
LCD_R1 PJ0 LCD_R1 AF14
LCD_R2 PJ1 LCD_R2 AF14
LCD_R3 PJ2 LCD_R3 AF14
LCD_R4 PJ3 LCD_R4 AF14
LCD_R5 PJ4 LCD_R5 AF14
LCD_R6 PJ5 LCD_R6 AF14
LCD_R7 PJ6 LCD_R7 AF14
LCD_G0 PJ8 LCD_G0 AF14
LCD_G1 PJ7 LCD_G1 AF14
LCD_G2 PJ10 LCD_G2 AF14
LCD_G3 PJ19 LCD_G3 AF14
LCD_G4 PJ11 LCD_G4 AF14
LCD_G5 PK0 LCD_G5 AF14
LCD_G6 PK1 LCD_G6 AF14
LCD_G7 PK2 LCD_G7 AF14
LCD_B0 PJ12 LCD_B0 AF14
LCD_B1 PJ13 LCD_B1 AF14
LCD_B2 PJ14 LCD_B2 AF14
LCD_B3 PJ15 LCD_B3 AF14
LCD_B4 PK3 LCD_B4 AF14
LCD_B5 PK4 LCD_B5 AF14
LCD_B6 PK5 LCD_B6 AF14
LCD_B7 PK6 LCD_B7 AF14
LCD_PCLK PI14 LCD_PCLK AF14
LCD_DEN PK7 LCD_DEN AF14
LCD_HSYNC PI12 LCD_HSYNC AF14
LCD_VSYNC PI13 LCD_VSYNC AF14
  1. I2C5设备树节点

  2. 参考文档:

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

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

    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";
    };
    

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

    参考stm32mp15xx-dkx.dtsi对于i2c设备节点的描述,修改i2c5内容如下:

    &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中对于i2c5_pins_a和i2c5_pins_sleep_a的定义与板子实际使用管脚一致,所以无需修改,内容如下:

    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 */
    	};
    };
    
  3. I2S2设备树节点

  4. 参考文档:

    Documentation/devicetree/bindings/i2c/sound/st,stm32-i2s.txt
    
  5. LTDC设备树节点

  6. SiI9022实现HDMI输出需要RGB信号作为数据源,LTDC为STM32MP157的LCD显示控制器,可以输出24bit的并行数据,HDMI显示首先需要驱动LTDC。

    参考文档:

    Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
    

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

    arch/arm/boot/dts/stm32mp151.dtsi
    

    stm32mp151中ltdc定义如下:

    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";
    };
    

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

    参考stm32mp15xx-dkx.dtsi对于ltdc设备节点的描述,需增加内容如下:

    &ltdc {
    	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&ltdc_pins_b>;
    	pinctrl-1 = <&ltdc_pins_sleep_b>;
    	status = "okay";
    
    	port {
    		#address-cells = <1>;
    		#size-cells = <0>;
    
    		ltdc_ep0_out: endpoint@0 {
    			reg = <0>;
    			/*图像输出通道,需对接显示设备*/
    			remote-endpoint = <&sii9022_in>;
    		};
    	};
    };
    

    由于stm32mp15-pinctrl.dtsi中对于ltdc_pins_b和ltdc_pins_b的定于与板子实际使用管脚一致,所以无需修改,内容如下:

    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 */
    	};
    };
    
  7. SiI9022设备树节点

  8. 参考文档:

    Documentation/devicetree/bindings/display/arm,hdlcd.txt
    

    由于SiI9002只是I2C5总线上的一个外设,所以STM32MP157A的通用设备树文件中并没有相关的定义,结合arm,hdlcd.txt和stm32mp15xx-dkx.dtsi对于HDMI的描述,增加SiI9002的支持,需在I2C5节点下添加相关信息,添加内容为:

    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输出端口对接*/
    				remote-endpoint = <&ltdc_ep0_out>;
    			};
    		};
    
    		port@3 {
    			reg = <3>;
    			sii9022_tx_endpoint: endpoint {
    				/*音频输入端口,与声卡输出端口对接*/
    				remote-endpoint = <&i2s2_endpoint>;
    			};
    		};
    	};
    };
    
  9. 电源节点添加

  10. 由于内核中很多驱动会根据电源的方位调整设备的工作方式,所以在设备树中需要传递相关电源电压参数,如sii9022驱动中需要两个电源分别是iovcc和cvcc12,但是在设备树中并没有这两个电源的定义,官方参考板DK1使用的是MPU作为电源管理,而FS-MP1A使用的分离元器件的形式,所以stm32mp15xx-dkx.dtsi中对于电源的定义就不实用了。参考内核中相关文档添加固定电源节点的形式添加iovcc和cvcc12即可,根据sii9022的需求,iovcc和cvcc12电压分别为3.3v和1.2v。

    参考文档:

    Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
    

    需在设备树根节点下添加,内容如下:

    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;
    };
    

实验目的

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

实验平台

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

实验步骤

  1. 导入交叉编译工具链
  2. linux@ubuntu:$ source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
    
  3. 添加i2c5及sii9022内容

  4. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下内容:

     &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 = <&ltdc_ep0_out>;
    				};
    			};
    		};
    	};
    };
    
    
  5. 添加ltdc内容

  6. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在文件末尾添加如下内容:

    &ltdc {
    	pinctrl-names = "default", "sleep";
    	pinctrl-0 = <&ltdc_pins_b>;
    	pinctrl-1 = <&ltdc_pins_sleep_b>;
    	status = "okay";
    
    	port {
    		#address-cells = <1>;
    		#size-cells = <0>;
    
    		ltdc_ep0_out: endpoint@0 {
    			reg = <0>;
    			remote-endpoint = <&sii9022_in>;
    		};
    	};
    };
    
    
  7. 添加电源内容

  8. 修改arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi文件,在根节点末尾添加如下内容:

    
    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;
    };
    
    
  9. 配置内核

  10. 由于内核源码默认配置以及支持sii902x,本节列出主要选项,如下:

    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
    
  11. 编译内核及设备树:
  12. linux@ubuntu:$ make -j4 uImage dtbs LOADADDR=0xC2000040
    
  13. 重启测试

  14. 将编译好的设备树和内核镜像拷贝到/tftpboot目录下,通过tftp引导内核,设备连接HDMI显示器,重启设备后查看/sys/class/drm会多出HMID的信息,同时显示器会有显示。

    51-1-4-1.png