drivers/gpu/drm/xlnx/zynqmp_dpsub.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xlnx/zynqmp_dpsub.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xlnx/zynqmp_dpsub.c
Extension
.c
Size
7717 bytes
Lines
317
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (IS_ERR(dpsub->vid_clk)) {
			dev_err(dpsub->dev, "failed to init any video clock\n");
			return PTR_ERR(dpsub->vid_clk);
		}
		dpsub->vid_clk_from_ps = true;
	}

	/*
	 * Try the live PL audio clock, and fall back to the PS clock if the
	 * live PL audio clock isn't valid. Missing audio clock disables audio
	 * but isn't an error.
	 */
	dpsub->aud_clk = devm_clk_get(dpsub->dev, "dp_live_audio_aclk");
	if (!IS_ERR(dpsub->aud_clk)) {
		dpsub->aud_clk_from_ps = false;
		return 0;
	}

	dpsub->aud_clk = devm_clk_get(dpsub->dev, "dp_aud_clk");
	if (!IS_ERR(dpsub->aud_clk)) {
		dpsub->aud_clk_from_ps = true;
		return 0;
	}

	dev_info(dpsub->dev, "audio disabled due to missing clock\n");
	return 0;
}

static int zynqmp_dpsub_parse_dt(struct zynqmp_dpsub *dpsub)
{
	struct device_node *np;
	unsigned int i;

	/*
	 * For backward compatibility with old device trees that don't contain
	 * ports, consider that only the DP output port is connected if no
	 * ports child no exists.
	 */
	np = of_get_child_by_name(dpsub->dev->of_node, "ports");
	of_node_put(np);
	if (!np) {
		dev_warn(dpsub->dev, "missing ports, update DT bindings\n");
		dpsub->connected_ports = BIT(ZYNQMP_DPSUB_PORT_OUT_DP);
		dpsub->dma_enabled = true;
		return 0;
	}

	/* Check which ports are connected. */
	for (i = 0; i < ZYNQMP_DPSUB_NUM_PORTS; ++i) {
		struct device_node *np;

		np = of_graph_get_remote_node(dpsub->dev->of_node, i, -1);
		if (np) {
			dpsub->connected_ports |= BIT(i);
			of_node_put(np);
		}
	}

	/* Sanity checks. */
	if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) &&
	    (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
		dev_err(dpsub->dev, "only one live video input is supported\n");
		return -EINVAL;
	}

	if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) ||
	    (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
		if (dpsub->vid_clk_from_ps) {
			dev_err(dpsub->dev,
				"live video input requires PL clock\n");
			return -EINVAL;
		}
	} else {
		dpsub->dma_enabled = true;
	}

	if (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_AUDIO))
		dev_warn(dpsub->dev, "live audio unsupported, ignoring\n");

	if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_OUT_VIDEO)) ||
	    (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_OUT_AUDIO)))
		dev_warn(dpsub->dev, "output to PL unsupported, ignoring\n");

	if (!(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_OUT_DP))) {
		dev_err(dpsub->dev, "DP output port not connected\n");
		return -EINVAL;
	}

	return 0;
}

Annotation

Implementation Notes