On 21-10-2026 14:15, Jayant Shekhar wrote:
On 15-10-2026 17:47, Dmitry Baryshkov wrote:
On Thu, Oct 15, 2026 at 01:08:21PM +0530, Jayant Shekhar wrote:
DCP platforms place the display pipeline under firmware control, so
Linux
cannot discover display resources through direct register access.
The DRM
driver therefore needs device-tree descriptions of the firmware
transport,
display topology, IOMMU contexts, and panel connections.
Add bindings for the Qualcomm DCP VirtIO display function, including
the
INTF graph and DSI host outputs. Document the framebuffer IOMMU
context,
IPCC power-notify mailbox and interrupts, firmware display topology,
and
firmware-visible IOVA window supplied by the parent VirtIO-MMIO
transport.
Signed-off-by: Jayant Shekhar <[email protected]>
Assisted-by: LLM
---
.../bindings/display/msm/qcom,dcp-dsi.yaml | 75
+++++++++++++
.../bindings/display/msm/qcom,dcp-virtio.yaml | 113
+++++++++++++++++++
.../devicetree/bindings/display/msm/qcom,dcp.yaml | 119
+++++++++++++++++++++
3 files changed, 307 insertions(+)
diff --git
a/Documentation/devicetree/bindings/display/msm/qcom,dcp-dsi.yaml
b/Documentation/devicetree/bindings/display/msm/qcom,dcp-dsi.yaml
new file mode 100644
index 000000000000..f7178c66c09e
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,dcp-dsi.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,dcp-dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm DCP DSI host
+
+maintainers:
+ - Jayant Shekhar <[email protected]>
+
+description: |
+ A MIPI DSI host exposed by the Qualcomm DCP VirtIO device (see
+ qcom,dcp.yaml). DCP is a firmware protocol shared across multiple
+ Qualcomm SoCs, not specific to any one of them; Hawi is its first
+ platform. The DSI host and its connection to a panel are described
+ using the standard DSI controller and OF graph properties.
+
+allOf:
+ - $ref: /schemas/display/dsi-controller.yaml#
+
+properties:
+ reg:
+ maxItems: 1
+ description: Index of this DSI host among its siblings.
+
+ status: true
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: |
+ port@0: Input from the DCP virtio device's DPU INTF output port.
+ port@1: Output to the attached panel.
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
Why do we need OF graph here? Would it be enough to link one of the
ports of the root node with the panel's input?
+
+required:
+ - reg
+ - ports
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ dcp-subsystem {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dsi@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dcp_dsi0_in: endpoint {
+ remote-endpoint = <&dcp_intf1_out>;
+ };
+ };
+
+ };
+ };
+ };
diff --git
a/Documentation/devicetree/bindings/display/msm/qcom,dcp-virtio.yaml
b/Documentation/devicetree/bindings/display/msm/qcom,dcp-virtio.yaml
new file mode 100644
index 000000000000..018694310dfb
--- /dev/null
+++
b/Documentation/devicetree/bindings/display/msm/qcom,dcp-virtio.yaml
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,dcp-virtio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm DCP VirtIO host
+
+maintainers:
+ - Jayant Shekhar <[email protected]>
+
+description: |
+ Qualcomm's DCP VirtIO host provides the generic VirtIO-MMIO
transport and
+ the host-side IPCC channel used to wake the DCP firmware.
+
+properties:
+ compatible:
+ contains:
+ const: qcom,dcp-virtio
+
+ reg:
+ maxItems: 1
+
+ iommus:
+ maxItems: 1
+
+ iommu-ranges:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+
+ interrupts-extended:
+ minItems: 2
+
+ interrupt-names:
+ items:
+ - const: virtio
+ - const: dcp_power_notify_irq
+
+ dma-coherent: true
+
+ mboxes:
+ maxItems: 1
+
+ mbox-names:
+ const: dcp-power-tx
+
+ dcp-subsystem:
+ $ref: qcom,dcp.yaml#
+
+required:
+ - compatible
+ - reg
+ - interrupts-extended
+ - interrupt-names
+ - iommus
+ - dcp-subsystem
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/mailbox/qcom-ipcc.h>
+
+ virtio@9be8000 {
+ compatible = "qcom,dcp-virtio", "virtio,mmio";
Is it really compatible with virtio,mmio? Can it be handled completely
by virtio,mmio?
There are two possible approaches:
Option 1 — Use the standard VirtIO-MMIO parent (preferred)
Keep the parent as:
compatible = "virtio,mmio";
reg = <...>;
interrupts = <...>;
iommus = <...>;
iommu-ranges = <...>;
dma-coherent;
The generic virtio/mmio.yaml binding would be extended only to
document the generic iommu-ranges property.
The DCP-specific resources would be placed on the virtio,deviceXX child:
dcp-subsystem {
compatible = "virtio,deviceXX";
iommus = <...>;
interrupts-extended = <&ipcc ...>;
mboxes = <&ipcc ...>;
mbox-names = "dcp-power-tx";
};
The parent uses the standard VirtIO-MMIO interrupts property. The
child has one DCP-specific interrupt, so interrupt-names is
unnecessary and the driver uses interrupt index 0.
Option 2 — Add a Qualcomm-specific VirtIO-MMIO parent binding
Keep a Qualcomm-specific compatible such as:
compatible = "qcom,dcp-virtio", "virtio,mmio";
and extend the parent binding to describe iommu-ranges, the additional
IPCC interrupt, mailbox, and related DCP resources.
However, this approach duplicates the generic VirtIO-MMIO binding and
is only justified if the transport requires Qualcomm-specific
handling. Since the DCP transport is handled completely by the
standard VirtIO-MMIO driver.
Which one do you prefer?
I will be addressing other comments in v2.
Thanks
Jayant
I think Option 1 is not suitable because the IPCC power-notify sequence
is required before the first VirtIO-MMIO register access. The standard
VirtIO-MMIO driver would otherwise probe the DT node directly and access
the registers before Qualcomm-specific initialization is complete.
Would the following Qualcomm-specific transport approach be acceptable?
- qcom,dcp-virtio is the DT-compatible Qualcomm wrapper. It
initializes IPCC and sends the required power notification before
creating a synthetic virtio-mmio platform device.
- The unchanged generic VirtIO-MMIO driver probes the synthetic
child, accesses the MMIO registers, creates the VirtIO queues, and
registers the VirtIO device.
- The DCP VirtIO driver binds to the resulting VirtIO device through
its VirtIO device/vendor ID table and initializes HFI, firmware
capabilities, and DRM/KMS.
- The virtio,deviceXX DT child is discovered by the VirtIO core and
describes the DCP-specific IOMMU context, DSI hosts, display graph, and
panels.
The flow is:
qcom,dcp-virtio
→ IPCC power-up
→ synthetic virtio-mmio device
→ generic VirtIO-MMIO driver
→ virtio,deviceXX DT child
→ DCP HFI/DRM driver
Since the Qualcomm wrapper creates and owns the synthetic VirtIO-MMIO
device, the parent node uses only:
compatible = "qcom,dcp-virtio";
It should not also advertise "virtio,mmio", because the generic
driver must not probe the parent directly before IPCC initialization.
+ reg = <0x09be8000 0x1000>;
+ interrupts-extended = <&intc GIC_ESPI 956
IRQ_TYPE_LEVEL_HIGH>,
+ <&ipcc 13 5 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "virtio", "dcp_power_notify_irq";
Why do you need names? Can they be dropped in favour of using indices?
+ iommus = <&apps_smmu 0x15a3 0x0>;
+ iommu-ranges = <0x0 0x84000000 0x0 0x04000000>;
+ dma-coherent;
+ mboxes = <&ipcc 13 5>;
+ mbox-names = "dcp-power-tx";
+
+ dcp-subsystem {
+ compatible = "virtio,device34";
+ iommus = <&apps_smmu 0x400 0x2>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+ dcp_intf1_out: endpoint {
+ remote-endpoint = <&dcp_dsi0_in>;
Can this point directly to the panel_in? What's the point of describing
internal paths in the DT?
+ };
+ };
+ };
+
+ dsi@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dcp_dsi0_in: endpoint {
+ remote-endpoint = <&dcp_intf1_out>;
+ };
+ };
+ };
+ };
+ };
+ };