RK3588平台(显示篇) DRM显示框架

一.简介

显示子系统是 Rockchip 平台显示输出相关软硬件系统的统称,它包括 VOP(比较老的平台叫 LCDC,比如 RK3188、RK3066)和 RGB、BT1120、BT656、I8080(MCU 显示接口),LVDS、MIPI DSI、EDP、DP、HDMI 等显示信号输 出模块以及与之对应的软件驱动。

从上面的 DSS 框图可以看到,在整个显示通路的最后端,是由 RGA,GPU、VPU 组成的显示图形加速模块,他们是专 门针对图像处理优化设计的硬件 IP,能够高效的进行图像的生成和进一步处理(比如 GPU 通过 opengl 功能提供图像 渲染功能,RGA 可以对图像数据进行缩放,旋转,合成等 2D 处理,VPU 可以高效的进行视频解码),从而减轻 CPU

负担。 经过这些图像加速模块处理后的数据会存放在 DDR 中,然后由 VOP 读取,根据应用需求进行 Alpha 叠加,颜色空间 转换,gamma 矫正,HDR 转换 等处理后,再发送到对应的显示接口模块(HDMI/DP/DSI/RGB/LVDS), 这些接口模 块会把接收到的数据转换成符合各自协议的数据流,发送到显示器或者屏幕上,呈现在最终用户眼前。

二.DRM 驱动和 libdrm 的交互过程

三.DRM显示框架的DTS配置

在一颗 SOC 上,可能有多个 VOP,HDMI,eDP,DP,MIPI,Panel 模块,根据具体产品定义,一款产品可能只需要 使用到其中一部分模块来组成显示通路。具体使用哪些模块,以及这些模块之间如何衔接则通过 dts 配置。

display_subsystem: display-subsystem {
		compatible = "rockchip,display-subsystem";
		ports = <&vop_out>;

		route {
			route_dp0: route-dp0 {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
				connect = <&vp1_out_dp0>;
			};

			route_dsi0: route-dsi0 {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
				connect = <&vp3_out_dsi0>;
			};

			route_dsi1: route-dsi1 {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
				connect = <&vp3_out_dsi1>;
			};

			route_edp0: route-edp0 {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
				connect = <&vp2_out_edp0>;
			};

			route_edp1: route-edp1 {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
			};

			route_hdmi0: route-hdmi0 {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
				connect = <&vp0_out_hdmi0>;
			};

			route_rgb: route-rgb {
				status = "disabled";
				logo,uboot = "logo.bmp";
				logo,kernel = "logo_kernel.bmp";
				logo,mode = "center";
				charge_logo,mode = "center";
				connect = <&vp3_out_rgb>;
			};
		};
	};

VOP: 

vop: vop@fdd90000 {
		compatible = "rockchip,rk3588-vop";
		reg = <0x0 0xfdd90000 0x0 0x4200>, <0x0 0xfdd95000 0x0 0x1000>;
		reg-names = "regs", "gamma_lut";
		interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&cru ACLK_VOP>,
			 <&cru HCLK_VOP>,
			 <&cru DCLK_VOP0>,
			 <&cru DCLK_VOP1>,
			 <&cru DCLK_VOP2>,
			 <&cru DCLK_VOP3>,
			 <&cru PCLK_VOP_ROOT>,
			 <&cru DCLK_VOP0_SRC>,
			 <&cru DCLK_VOP1_SRC>,
			 <&cru DCLK_VOP2_SRC>;
		clock-names = "aclk_vop",
			      "hclk_vop",
			      "dclk_vp0",
			      "dclk_vp1",
			      "dclk_vp2",
			      "dclk_vp3",
			      "pclk_vop",
			      "dclk_src_vp0",
			      "dclk_src_vp1",
			      "dclk_src_vp2";
		assigned-clocks = <&cru ACLK_VOP>;
		assigned-clock-rates = <500000000>;
		resets = <&cru SRST_A_VOP>,
			 <&cru SRST_H_VOP>,
			 <&cru SRST_D_VOP0>,
			 <&cru SRST_D_VOP1>,
			 <&cru SRST_D_VOP2>,
			 <&cru SRST_D_VOP3>;
		reset-names = "axi",
			      "ahb",
			      "dclk_vp0",
			      "dclk_vp1",
			      "dclk_vp2",
			      "dclk_vp3";
		iommus = <&vop_mmu>;
		power-domains = <&power RK3588_PD_VOP>;
		rockchip,grf = <&sys_grf>;
		rockchip,vop-grf = <&vop_grf>;
		rockchip,vo1-grf = <&vo1_grf>;
		rockchip,pmu = <&pmu>;

		status = "disabled";

		vop_out: ports {
			#address-cells = <1>;
			#size-cells = <0>;

			vp0: port@0 {
				#address-cells = <1>;
				#size-cells = <0>;
				reg = <0>;

				vp0_out_dp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&dp0_in_vp0>;
				};

				vp0_out_edp0: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&edp0_in_vp0>;
				};

				vp0_out_hdmi0: endpoint@2 {
					reg = <2>;
					remote-endpoint = <&hdmi0_in_vp0>;
				};
			};

			vp1: port@1 {
				#address-cells = <1>;
				#size-cells = <0>;
				reg = <1>;

				vp1_out_dp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&dp0_in_vp1>;
				};

				vp1_out_edp0: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&edp0_in_vp1>;
				};

				vp1_out_hdmi0: endpoint@2 {
					reg = <2>;
					remote-endpoint = <&hdmi0_in_vp1>;
				};
			};

			vp2: port@2 {
				#address-cells = <1>;
				#size-cells = <0>;
				reg = <2>;

				assigned-clocks = <&cru DCLK_VOP2_SRC>;
				assigned-clock-parents = <&cru PLL_V0PLL>;

				vp2_out_dp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&dp0_in_vp2>;
				};

				vp2_out_edp0: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&edp0_in_vp2>;
				};

				vp2_out_hdmi0: endpoint@2 {
					reg = <2>;
					remote-endpoint = <&hdmi0_in_vp2>;
				};

				vp2_out_dsi0: endpoint@3 {
					reg = <3>;
					remote-endpoint = <&dsi0_in_vp2>;
				};

				vp2_out_dsi1: endpoint@4 {
					reg = <4>;
					remote-endpoint = <&dsi1_in_vp2>;
				};
			};

			vp3: port@3 {
				#address-cells = <1>;
				#size-cells = <0>;
				reg = <3>;

				vp3_out_dsi0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&dsi0_in_vp3>;
				};

				vp3_out_dsi1: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&dsi1_in_vp3>;
				};

				vp3_out_rgb: endpoint@2 {
					reg = <2>;
					remote-endpoint = <&rgb_in_vp3>;
				};
			};
		};
	};

该节点描述 VOP 硬件资源,控制着 vop 驱动的加载 rockchip_drm_vop.c/rockchip_drm_vop2.c , 它描述了如下 的显示通路连接关系:

vop_out: ports 节点描述 VOP 的输出通道,vp0/1/2 对应 VOP 上 Video Port0/1/2 三个独立的输出通路。

vp0/1/2 : port 下的 endpoint 节点描述 VP 和显示接口的连接关系,以上面的 dts 描述为例:vp0 节点下有

vp0_out_dsi0 , vp0_out_dsi1 , vp0_out_edp , vp0_out_hdmi 四个节点,说明 vp0 可以和 dsi0、dsi1、

edp、hdmi、四个显示接口连接。 每个 endpoint 通过 remote-endpoint 属性和对应的显示接口组成一个连接通路 ,比如和 hdmi 显示接口的连接:

hdmi0: hdmi@fde80000 {
		compatible = "rockchip,rk3588-dw-hdmi";
		reg = <0x0 0xfde80000 0x0 0x20000>;
		interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
			     <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&cru PCLK_HDMITX0>,
			 <&cru CLK_HDMIHDP0>,
			 <&cru CLK_HDMITX0_EARC>,
			 <&cru CLK_HDMITX0_REF>,
			 <&cru MCLK_I2S5_8CH_TX>,
			 <&cru DCLK_VOP0>,
			 <&cru DCLK_VOP1>,
			 <&cru DCLK_VOP2>,
			 <&cru DCLK_VOP3>,
			 <&hclk_vo1>,
			 <&hdptxphy_hdmi_clk0>;
		clock-names = "pclk",
			      "hpd",
			      "earc",
			      "hdmitx_ref",
			      "aud",
			      "dclk_vp0",
			      "dclk_vp1",
			      "dclk_vp2",
			      "dclk_vp3",
			      "hclk_vo1",
			      "link_clk";
		resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>;
		reset-names = "ref", "hdp";
		power-domains = <&power RK3588_PD_VO1>;
		pinctrl-names = "default";
		pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd &hdmim0_tx0_scl &hdmim0_tx0_sda>;
		reg-io-width = <4>;
		rockchip,grf = <&sys_grf>;
		rockchip,vo1_grf = <&vo1_grf>;
		phys = <&hdptxphy_hdmi0>;
		phy-names = "hdmi";
		#sound-dai-cells = <0>;
		status = "disabled";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			hdmi0_in: port@0 {
				reg = <0>;
				#address-cells = <1>;
				#size-cells = <0>;

				hdmi0_in_vp0: endpoint@0 {
					reg = <0>;
					remote-endpoint = <&vp0_out_hdmi0>;
					status = "disabled";
				};

				hdmi0_in_vp1: endpoint@1 {
					reg = <1>;
					remote-endpoint = <&vp1_out_hdmi0>;
					status = "disabled";
				};

				hdmi0_in_vp2: endpoint@2 {
					reg = <2>;
					remote-endpoint = <&vp2_out_hdmi0>;
					status = "disabled";
				};
			};
		};
	};

结合上面的 dts 描述我们可以知道,在 rk3568 上,hdmi 可以和 vop 的 vp0,vp1 连接。 需要注意的是,一个显示接口在同一个时刻只能和一个 vp 连接,所以在具体的板级配置中,需要在 dts 中把要使用的 通路打开,把不使用的通路设置为 disabled 状态。

&hdmi {
        status = "okay";
};

&hdmi_in_vp0 {
        status = "okay";
};

&hdmi_in_vp1 {
        status = "disabled";
};

&route_hdmi {
        status = "okay";
        connect = <&vp0_out_hdmi>;
};

四.调试手段

调试命令:

cat /sys/kernel/debug/dri/0/summary

 参数说明:

1. 两个红色方框表示两个显示设备使用的 vop 分别是 ff900000.vop 和 ff8f0000.vop;

2. 绿色部分表示 connector 信息,两个显示设备分别为 eDP 屏和 MIPI 屏;

3. 粉色部分为显示模式,可以知道具体的时序、DCLK 以及帧率,上图中两个设备分别为分辨率为 1536x2048p60的 eDP 屏和分辨率 1280x720p29 的 MIPI 屏;

4. 蓝色部分是 VOP 图层信息,第一个显示设备打开 win0 图层,大小为 1536x2048 格式为 XRGB 第二个显示设备 打开 win0 图层,大小 1280x720 格式为 XRGB, src 和 dst 表示源数据和显示的大小和位置,如果 src 和 dst 的 大小不一致,VOP 会进行缩放处理。

查看vop时钟命令:

cat /sys/kernel/debug/clk/clk_summary | grep vop

  • 10
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式_笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值