xref: /linux/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx-connector-fixup.c (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
173cb588aSLuca Ceresoli // SPDX-License-Identifier: GPL-2.0
273cb588aSLuca Ceresoli /*
373cb588aSLuca Ceresoli  * Add an hdmi-connector node to boards using the imx8mp hdmi_tx which
473cb588aSLuca Ceresoli  * don't have one. This is needed for the i.MX LCDIF to work with
573cb588aSLuca Ceresoli  * DRM_BRIDGE_ATTACH_NO_CONNECTOR.
673cb588aSLuca Ceresoli  *
773cb588aSLuca Ceresoli  * Copyright (C) 2026 GE HealthCare
873cb588aSLuca Ceresoli  * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
973cb588aSLuca Ceresoli  */
1073cb588aSLuca Ceresoli 
1173cb588aSLuca Ceresoli #include <linux/cleanup.h>
1273cb588aSLuca Ceresoli #include <linux/init.h>
1373cb588aSLuca Ceresoli #include <linux/of.h>
1473cb588aSLuca Ceresoli #include <linux/of_graph.h>
1573cb588aSLuca Ceresoli 
1673cb588aSLuca Ceresoli /* Embedded dtbo symbols created by cmd_wrap_S_dtb in scripts/Makefile.dtbs */
1773cb588aSLuca Ceresoli extern char __dtbo_imx8mp_hdmi_tx_connector_fixup_begin[];
1873cb588aSLuca Ceresoli extern char __dtbo_imx8mp_hdmi_tx_connector_fixup_end[];
1973cb588aSLuca Ceresoli 
2073cb588aSLuca Ceresoli static int __init imx8mp_hdmi_tx_connector_fixup_init(void)
2173cb588aSLuca Ceresoli {
2273cb588aSLuca Ceresoli 	struct device_node *soc      __free(device_node) = NULL;
2373cb588aSLuca Ceresoli 	struct device_node *hdmi_tx  __free(device_node) = NULL;
2473cb588aSLuca Ceresoli 	struct device_node *endpoint __free(device_node) = NULL;
2573cb588aSLuca Ceresoli 	void *dtbo_start;
2673cb588aSLuca Ceresoli 	u32 dtbo_size;
2773cb588aSLuca Ceresoli 	int ovcs_id;
2873cb588aSLuca Ceresoli 	int err;
2973cb588aSLuca Ceresoli 
3073cb588aSLuca Ceresoli 	soc = of_find_node_by_path("/soc@0");
3173cb588aSLuca Ceresoli 	if (!soc)
3273cb588aSLuca Ceresoli 		return 0;
3373cb588aSLuca Ceresoli 
3473cb588aSLuca Ceresoli 	/* This applies to i.MX8MP only, do nothing on other systems */
3573cb588aSLuca Ceresoli 	if (!of_device_is_compatible(soc, "fsl,imx8mp-soc"))
3673cb588aSLuca Ceresoli 		return 0;
3773cb588aSLuca Ceresoli 
3873cb588aSLuca Ceresoli 	hdmi_tx = of_find_node_by_path("/soc@0/bus@32c00000/hdmi@32fd8000");
3973cb588aSLuca Ceresoli 	if (!of_device_is_available(hdmi_tx))
4073cb588aSLuca Ceresoli 		return 0;
4173cb588aSLuca Ceresoli 
4273cb588aSLuca Ceresoli 	/* If endpoint exists, assume an hdmi-connector exists already */
4373cb588aSLuca Ceresoli 	endpoint = of_graph_get_endpoint_by_regs(hdmi_tx, 1, -1);
4473cb588aSLuca Ceresoli 	if (endpoint)
4573cb588aSLuca Ceresoli 		return 0;
4673cb588aSLuca Ceresoli 
47*1148ef0cSLuca Ceresoli 	/*
48*1148ef0cSLuca Ceresoli 	 * Boards with an HDMI connector should describe it in a device
49*1148ef0cSLuca Ceresoli 	 * tree node with compatible = "hdmi-connector".
50*1148ef0cSLuca Ceresoli 	 *
51*1148ef0cSLuca Ceresoli 	 * If you see this warning, it means such a node was not found and
52*1148ef0cSLuca Ceresoli 	 * a fallback one is added using a device tree overlay. Please add
53*1148ef0cSLuca Ceresoli 	 * one in your device tree, also describing the exact connector
54*1148ef0cSLuca Ceresoli 	 * type (the added overlay assumes Type A as a fallback, but it
55*1148ef0cSLuca Ceresoli 	 * might be wrong).
56*1148ef0cSLuca Ceresoli 	 *
57*1148ef0cSLuca Ceresoli 	 * This node is necessary for modern DRM, where bridge drivers do
58*1148ef0cSLuca Ceresoli 	 * not create a connector (see the DRM_BRIDGE_ATTACH_NO_CONNECTOR
59*1148ef0cSLuca Ceresoli 	 * flag). See https://docs.kernel.org/gpu/drm-kms-helpers.html for
60*1148ef0cSLuca Ceresoli 	 * more info.
61*1148ef0cSLuca Ceresoli 	 */
62*1148ef0cSLuca Ceresoli 	pr_warn("Please add a hdmi-connector DT node for imx8mp-hdmi-tx.\n");
63*1148ef0cSLuca Ceresoli 
6473cb588aSLuca Ceresoli 	dtbo_start = __dtbo_imx8mp_hdmi_tx_connector_fixup_begin;
6573cb588aSLuca Ceresoli 	dtbo_size = __dtbo_imx8mp_hdmi_tx_connector_fixup_end -
6673cb588aSLuca Ceresoli 		    __dtbo_imx8mp_hdmi_tx_connector_fixup_begin;
6773cb588aSLuca Ceresoli 
6873cb588aSLuca Ceresoli 	err = of_overlay_fdt_apply(dtbo_start, dtbo_size, &ovcs_id, NULL);
6973cb588aSLuca Ceresoli 	if (err)
7073cb588aSLuca Ceresoli 		err = of_overlay_remove(&ovcs_id);
7173cb588aSLuca Ceresoli 
7273cb588aSLuca Ceresoli 	return err;
7373cb588aSLuca Ceresoli }
7473cb588aSLuca Ceresoli 
7573cb588aSLuca Ceresoli subsys_initcall(imx8mp_hdmi_tx_connector_fixup_init);
76