Device Tree Bindings Media Entities
Trace the mux and CSI pipeline from the previous lecture back to the .dtsi and .dts source files that declare it in the first place.
Device tree bindings for media entities are what turn a block of silicon on your SoC into a named, linkable entity that media-ctl can see at all. In this lecture of our free linux kernel development course, we open up the device tree source behind the mux and CSI pipeline you configured in the previous lecture, and show exactly how ports, endpoints, and the remote-endpoint property describe hardware wiring in a way the V4L2 async framework can parse automatically. By the end you will be able to read any vendor’s camera device tree and know exactly which entity each node will become at runtime.
What You Will Learn
- How SoC-level entities are declared in a vendor .dtsi and enabled per board
- The port/endpoint/remote-endpoint pattern that describes physical hardware links
- How to declare an external camera sensor node with a matching endpoint
- How these device tree nodes map directly onto the media-ctl entities from earlier lectures
Prerequisites
- Basic device tree syntax (nodes, properties, phandles, labels)
- The mux + CSI pipeline entities introduced in the previous lecture
Ports and Endpoints: The Wiring Diagram of the Device Tree
Every entity that participates in a media graph exposes one or more port nodes, each representing a physical pad. Inside a port, an endpoint subnode carries a remote-endpoint phandle pointing at the endpoint on the other side of the physical connection. This is exactly the same information media-ctl later reports as a link between two pads — the device tree is simply the source of truth the async framework parses at boot to build that graph automatically.
| Device tree concept | Media controller equivalent |
|---|---|
port@N | Pad number N on the entity |
endpoint subnode | One end of a physical link |
remote-endpoint phandle | The matching pad on the connected entity |
data-lanes / clock-lanes | MIPI CSI-2 physical lane assignment for that link |
SoC-Level Declaration: the Mux and the CSI Receiver
The video mux and CSI receiver are part of the SoC itself, so they live in the chip-wide .dtsi file, typically disabled by default until a board file opts in. Continuing with our original entity names:
ep_vmux: video-mux@0 {
compatible = "video-mux";
mux-controls = ;
#address-cells = ;
#size-cells = ;
status = "disabled";
port@0 {
reg = ;
/* reserved for a parallel camera input */
};
port@1 {
reg = ;
ep_vmux_from_mipi: endpoint {
remote-endpoint = ;
};
};
port@2 {
reg = ;
ep_vmux_to_csi: endpoint {
remote-endpoint = ;
};
};
};
ep_mipi_rx: mipi-csi@30750000 {
compatible = "epsoc,mipi-csi2";
reg = ;
status = "disabled";
port@0 {
reg = ;
/* sink: connected to the external sensor in the board file */
};
port@1 {
reg = ;
ep_mipi_to_vmux: endpoint {
remote-endpoint = ;
};
};
};
ep_csi: csi@30710000 {
compatible = "epsoc,csi";
reg = ;
status = "disabled";
port {
ep_csi_from_vmux: endpoint {
remote-endpoint = ;
};
};
};
Notice how the remote-endpoint phandles cross-reference each other: ep_vmux_from_mipi points at ep_mipi_to_vmux, and that same label’s endpoint points right back. This mutual reference is what lets the kernel walk the graph in either direction starting from any single node.
Board-Level Declaration: Enabling Nodes and Adding the Sensor
Chip-level nodes are disabled by default because not every board wires up every SoC peripheral. The board .dts file enables exactly the nodes it uses, and adds the camera sensor itself, since the sensor is a board-specific component, never part of the SoC:
&ep_vmux {
status = "okay";
};
&ep_mipi_rx {
clock-frequency = ;
status = "okay";
port@0 {
reg = ;
ep_mipi_from_sensor: endpoint {
remote-endpoint = ;
data-lanes = ;
};
};
};
&i2c1 {
status = "okay";
ep_camsensor: camera@36 {
compatible = "epvendor,camsensor";
reg = ;
clocks = ;
status = "okay";
port {
ep_camsensor_to_mipi: endpoint {
remote-endpoint = ;
clock-lanes = ;
data-lanes = ;
};
};
};
};
Once this board file is compiled into the DTB and the kernel boots, the V4L2 async framework we studied earlier in this course parses every one of these endpoint pairs and builds the exact graph media-ctl reported in the previous lecture — without a single line of board-specific probing code in any driver.
Device Tree to Media Graph Mapping
camera@36 endpoint ↔ mipi-csi@… endpoint ↔ video-mux@0 endpoint ↔ csi@… endpoint
Common Mistakes and Troubleshooting
- Forgetting to set status = “okay”: a node left disabled never probes, even if its endpoints are correctly wired.
- Mismatched remote-endpoint phandles: both sides of a physical link must point at each other; a one-way reference breaks graph parsing silently.
- Wrong data-lanes count: a mismatch between what the sensor declares and what the receiver expects is one of the most common causes of a blank or corrupted first frame on real hardware.
- Declaring the sensor in the SoC .dtsi: sensors are always board components and belong in the board .dts file, never the shared chip file.
Best Practices
- Keep SoC-level nodes disabled by default; let each board opt in explicitly
- Give every endpoint a clear, matching label pair so remote-endpoint references stay readable
- Double check data-lanes and clock-lanes against your sensor’s datasheet, not the reference design
- Use
dtcwith-I dts -O dtsto sanity-check a compiled DTB matches your intent before flashing
Real-World Use Case
This exact split — SoC peripherals declared once in a shared .dtsi, boards enabling and wiring only what they use — is precisely why the same Linux kernel image can support dozens of different camera-equipped boards built around one SoC family. Board bring-up teams typically only ever touch the board .dts file, never the vendor .dtsi, which keeps camera support portable and reviewable.
Summary and Key Takeaways
- Media entities are declared as normal device tree nodes with port/endpoint subnodes
- remote-endpoint phandles form the mutual references that describe a physical link
- SoC peripherals live in the shared .dtsi and are disabled by default
- Sensors and other board-specific components are always declared in the board .dts
Conclusion
Device tree bindings for media entities are the missing link between the abstract graph media-ctl reports and the physical wiring of a real board. With ports, endpoints, and remote-endpoint phandles now demystified, the final lecture in this chapter of our free linux kernel development course closes the loop — reading a live topology back out of the running kernel and interpreting exactly what it tells you.
Frequently Asked Questions
Why are SoC media nodes disabled by default?
Not every board wires up every peripheral on a given SoC, so leaving nodes disabled by default and letting each board opt in keeps the shared .dtsi reusable across many boards.
What does the remote-endpoint property actually do?
It is a phandle pointing at the endpoint node on the other side of a physical connection, letting the kernel resolve which two pads are wired together.
Where should the camera sensor node be declared?
Always in the board-level .dts file, since the sensor is a board component, not part of the SoC itself.
What do data-lanes and clock-lanes describe?
They describe the physical MIPI CSI-2 lane assignment for a given endpoint, and must match between the sensor and the receiver it is connected to.
Do I need a driver to walk the graph manually?
No, the V4L2 async framework covered earlier in this course parses these endpoints automatically at probe time using the fwnode graph API.
How can I check my device tree compiled correctly?
Decompile the resulting DTB with dtc -I dtb -O dts and confirm the port, endpoint, and remote-endpoint nodes look exactly as you intended.
Read the Live Topology Next
Finish this chapter of our free linux kernel development course by interpreting a real media-ctl topology dump end to end.
Next Lecture Browse Full Course Index