[RK3399][Android7.1] Display中的Component System

OS: Android 7.1
Board: Firefly-RK3399
Kernel: v4.4.55

上一篇文章介绍了DRM的概念,有CRTC, Encoder, Connector等好多个模块,各个模块都作为一个组件添加到组件系统中,通过组件驱动来管理。

关于component system,下面是作者的一段话:

Subsystems such as ALSA, DRM and others require a single card-level
device structure to represent a subsystem.  However, firmware tends to
describe the individual devices and the connections between them.

Therefore, we need a way to gather up the individual component devices
together, and indicate when we have all the component devices.

We do this in DT by providing a "superdevice" node which specifies
the components, eg:

	imx-drm {
		compatible = "fsl,drm";
		crtcs = <&ipu1>;
		connectors = <&hdmi>;
	};

The superdevice is declared into the component support, along with the
subcomponents.  The superdevice receives callbacks to locate the
subcomponents, and identify when all components are present.  At this
point, we bind the superdevice, which causes the appropriate subsystem
to be initialised in the conventional way.

When any of the components or superdevice are removed from the system,
we unbind the superdevice, thereby taking the subsystem down.

也就是说DRM类似ALSA框架那样有一个代表整个子系统的东西,作者称它为"superdevice", superdevice管理components。平台上对应的dts node就是:
rk3399.dtsi

	display_subsystem: display-subsystem {
		compatible = "rockchip,display-subsystem";
		ports = <&vopl_out>, <&vopb_out>;
		status = "disabled";
	};

rk3399-android.dtsi中被打开:

&display_subsystem {
	status = "okay";
	ports = <&vopb_out>, <&vopl_out>;
	memory-region = <&drm_logo>;
	route {
		......
		route_edp: route-edp {
			.....
			connect = <&vopb_out_edp>;
		};
	};
};

把各个component连接起来的枢纽是驱动文件 rockchip_drm_drv.c
在驱动中superdevice通过component_master_add_with_match()执行,成为一个master。其中的变量match列表,它从dts中找到有效的component, 如VOP(CRTC),edp(Connector)然后添加进来。这样就有了所有应该加载的component列表了。另一方面,每个component对应的驱动在加载后会添加到component_list这个变量中。
最终通过find_components()比较match和component_list是否全部匹配,并决定是否执行后面的绑定动作。

static int rockchip_drm_platform_probe(struct platform_device *pdev)
{

	/*添加CRTC到match列表中,这样Encoder在调用bind回调的时候能通过
	drm_of_find_possible_crtcs()找到它, 这里的CRTC是"vopb"和"vopl".*/
	component_match_add(dev, &match, compare_of, port->parent);
	......
	/*添加远程endpoint到match上,内部也是调用component_match_add()实现
	只有有效的endpoint才会被添加到match中,这里只有edp(Connector)被添加进去了。*/
	rockchip_add_endpoints(dev, &match, port);
	......
	//把match添加到master中管理
	return component_master_add_with_match(dev, &rockchip_drm_ops, match);
}

上面提到的endpoint,目前的dts中有如下这些:

	vopb: vop@ff900000 {
		......
		vopb_out: port {
			#address-cells = <1>;
			#size-cells = <0>;
			vopb_out_edp: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&edp_in_vopb>;
			};
			vopb_out_mipi: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&mipi_in_vopb>;
			};
			vopb_out_hdmi: endpoint@2 {
				reg = <2>;
				remote-endpoint = <&hdmi_in_vopb>;
			};
			vopb_out_dp: endpoint@3 {
				reg = <3>;
				remote-endpoint = <&dp_in_vopb>;
			};
		};
	};

vopl里也有四个,通过remote-endpoint node找到parent node分别是

  • edp: edp@ff970000
  • mipi_dsi: mipi@ff960000
  • hdmi: hdmi@ff940000
  • cdn_dp: dp@fec00000

在所有components被found后会调用rockchip_drm_ops中的bind回调函数开始执行绑定后各个模块初始化。

static const struct component_master_ops rockchip_drm_ops = {
	.bind = rockchip_drm_bind,
	.unbind = rockchip_drm_unbind,
};

绑定调用过程:
component_master_add_with_match -> try_to_bring_up_master -> find_components ->
master->ops->bind

component_master_add_with_match()第一次不一定会成功,当且仅当所有的component都ready之后,master才会被bring up。因此在开机log中刚开始看到“failed to bind xxx”的信息是正常的。

那么这时没有ready下次什么时候会再执行这个动作呢?
答案:每个component在被add的时候都会去重新调用try_to_bring_up_master()去判断是否所有component全部被添加进来。

find_components()就是用来寻找并判断所有match列表中的components是不是都被add即初始化了,如果没有ready,那么就不会再去走后面bring up master的流程。

拿edp驱动举例, analogix_dp-rockchip.c中有如下调用:
rockchip_dp_probe -> component_add -> try_to_bring_up_masters

master就会被bring up,master->bind就会被调用,最终也会调用各个component的bind回调函数。
rockchip_drm_bind -> component_bind_all -> component_bind -> component->ops->bind

借用rk drm作者的一张流程加载图可以对加载过程有更清晰的了解。

[RK3399][Android7.1] Display中的Component System_第1张图片


参考
Patchwork [RFC,26/46] drivers/base: provide an infrastructure for componentised subsystems
[PATCH 2/2] component: add kernel-docs in the header
rockchip_drm_integration_helper-zh.pdf

你可能感兴趣的:(RK3399,子类__Display)