Subject: Re: [PATCH] drm/armada: add reserved memory support

From: Russell King <[email-masked]>
Date: Fri, 18 Oct 2024 11:07:41 +0100

From: Russell King <[email-masked]>

Existing Armada DRM makes use of reserved memory for allocating
contiguous screen buffers, which currently prevents its use with
DT systems.  Add support for this for DT systems.

Signed-off-by: Russell King <[email-masked]>
---
 drivers/gpu/drm/armada/armada_drv.c | 52 ++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e8d2fe955909..9200ede96427 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 
 #include <drm/drm_aperture.h>
@@ -56,11 +57,40 @@ static const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
 	.atomic_commit		= drm_atomic_helper_commit,
 };
 
-static int armada_drm_bind(struct device *dev)
+static struct reserved_mem *armada_drm_get_rmem(struct device *dev,
+	const char *compatible)
+{
+	struct device_node *np;
+	struct reserved_mem *rmem;
+
+	np = of_find_compatible_node(NULL, NULL, compatible);
+	if (!np)
+		return NULL;
+
+	rmem = of_reserved_mem_lookup(np);
+	of_node_put(np);
+
+	return rmem;
+}
+
+static struct resource *armada_drm_get_mem(struct device *dev)
 {
-	struct armada_private *priv;
 	struct resource *mem = NULL;
-	int ret, n;
+	struct reserved_mem *rmem;
+	int n;
+
+	rmem = armada_drm_get_rmem(dev, "marvell,armada-framebuffer");
+	if (rmem) {
+		mem = devm_kzalloc(dev, sizeof(*mem), GFP_KERNEL);
+		if (!mem)
+			return ERR_PTR(-ENOMEM);
+
+		mem->start = rmem->base;
+		mem->end = rmem->base + rmem->size - 1;
+		mem->flags = IORESOURCE_MEM;
+
+		return mem;
+	}
 
 	for (n = 0; ; n++) {
 		struct resource *r = platform_get_resource(to_platform_device(dev),
@@ -72,11 +102,21 @@ static int armada_drm_bind(struct device *dev)
 		if (resource_size(r) > SZ_64K)
 			mem = r;
 		else
-			return -EINVAL;
+			return ERR_PTR(-EINVAL);
 	}
 
-	if (!mem)
-		return -ENXIO;
+	return mem ? : ERR_PTR(-ENXIO);
+}
+
+static int armada_drm_bind(struct device *dev)
+{
+	struct armada_private *priv;
+	struct resource *mem;
+	int ret;
+
+	mem = armada_drm_get_mem(dev);
+	if (IS_ERR(mem))
+		return PTR_ERR(mem);
 
 	if (!devm_request_mem_region(dev, mem->start, resource_size(mem),
 				     "armada-drm"))

---

From: Russell King <[email-masked]>
Date: Fri, 18 Oct 2024 11:07:42 +0100

Using a virtual device is deprecated, so we have no option but to
detect the presence of available LCD controllers in DT and probe
all LCD controllers together within one DRM device.

Signed-off-by: Russell King <[email-masked]>
---
 drivers/gpu/drm/armada/armada_drv.c | 52 ++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 9200ede96427..ad3393f2c813 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -231,11 +231,6 @@ static int armada_drm_probe(struct platform_device *pdev)
 {
 	struct component_match *match = NULL;
 	struct device *dev = &pdev->dev;
-	int ret;
-
-	ret = drm_of_component_probe(dev, component_compare_dev_name, &armada_master_ops);
-	if (ret != -EINVAL)
-		return ret;
 
 	if (dev->platform_data) {
 		char **devices = dev->platform_data;
@@ -258,6 +253,22 @@ static int armada_drm_probe(struct platform_device *pdev)
 				armada_add_endpoints(dev, &match, d->of_node);
 			put_device(d);
 		}
+	} else {
+		struct device_node *np;
+
+		for_each_compatible_node(np, NULL, "marvell,armada-lcdc") {
+			if (!of_device_is_available(np))
+				continue;
+
+			drm_of_component_match_add(dev, &match, component_compare_of, np);
+		}
+
+		for_each_compatible_node(np, NULL, "marvell,armada-lcdc") {
+			if (!of_device_is_available(np))
+				continue;
+
+			armada_add_endpoints(dev, &match, np);
+		}
 	}
 
 	return component_master_add_with_match(&pdev->dev, &armada_master_ops,
@@ -289,8 +300,11 @@ static struct platform_driver armada_drm_platform_driver = {
 	.id_table = armada_drm_platform_ids,
 };
 
+static struct platform_device *armada_device;
+
 static int __init armada_drm_init(void)
 {
+	struct device_node *np;
 	int ret;
 
 	if (drm_firmware_drivers_only())
@@ -298,16 +312,40 @@ static int __init armada_drm_init(void)
 
 	ret = platform_driver_register(&armada_lcd_platform_driver);
 	if (ret)
-		return ret;
+		goto err_lcd;
+
 	ret = platform_driver_register(&armada_drm_platform_driver);
 	if (ret)
-		platform_driver_unregister(&armada_lcd_platform_driver);
+		goto err_drm;
+
+	for_each_compatible_node(np, NULL, "marvell,armada-lcdc") {
+		if (!of_device_is_available(np))
+			continue;
+
+		of_node_put(np);
+		armada_device = platform_device_register_simple(
+					"armada-drm", -1, NULL, 0);
+		if (IS_ERR(armada_device)) {
+			ret = PTR_ERR(armada_device);
+			goto err_dev;
+		}
+		break;
+	}
+	return 0;
+
+ err_dev:
+	platform_driver_unregister(&armada_drm_platform_driver);
+ err_drm:
+	platform_driver_unregister(&armada_lcd_platform_driver);
+ err_lcd:
 	return ret;
 }
 module_init(armada_drm_init);
 
 static void __exit armada_drm_exit(void)
 {
+	if (armada_device)
+		platform_device_unregister(armada_device);
 	platform_driver_unregister(&armada_drm_platform_driver);
 	platform_driver_unregister(&armada_lcd_platform_driver);
 }

---

From: Russell King <[email-masked]>
Date: Fri, 18 Oct 2024 11:07:42 +0100

From: Russell King <[email-masked]>

Add DT configuration for the HDMI display output on the Dove Cubox.
This adds support for the LCD0 controller which is connected to a
TDA19988 HDMI encoder.

Signed-off-by: Russell King <[email-masked]>
---
 arch/arm/boot/dts/marvell/dove-cubox.dts | 37 ++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/marvell/dove.dtsi      |  4 ++--
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/marvell/dove-cubox.dts b/arch/arm/boot/dts/marvell/dove-cubox.dts
index bfde99486a87..9ef4dcb58e3c 100644
--- a/arch/arm/boot/dts/marvell/dove-cubox.dts
+++ b/arch/arm/boot/dts/marvell/dove-cubox.dts
@@ -60,6 +60,19 @@ ir_recv: ir-receiver {
 	gpu-subsystem {
 		status = "okay";
 	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		framebuffer {
+			compatible = "marvell,armada-framebuffer";
+			size = <0x02000000>;
+			alignment = <0x02000000>;
+			no-map;
+		};
+	};
 };
 
 &uart0 { status = "okay"; };
@@ -117,6 +130,30 @@ clkout2 {
 			silabs,pll-master;
 		};
 	};
+
+	tda998x: hdmi-encoder@70 {
+		compatible = "nxp,tda998x";
+		reg = <0x70>;
+		video-ports = <0x234501>;
+		interrupts-extended = <&gpio0 27 IRQ_TYPE_LEVEL_LOW>;
+
+		port {
+			tda998x_video: endpoint {
+				remote-endpoint = <&lcd0_rgb>;
+			};
+		};
+	};
+};
+
+&lcd0 {
+	status = "okay";
+	clocks = <&si5351 0>;
+	clock-names = "ext_ref_clk1";
+	lcd0_port: port {
+		lcd0_rgb: endpoint {
+			remote-endpoint = <&tda998x_video>;
+		};
+	};
 };
 
 &sdio0 {
diff --git a/arch/arm/boot/dts/marvell/dove.dtsi b/arch/arm/boot/dts/marvell/dove.dtsi
index 062c86361640..b0865d28a646 100644
--- a/arch/arm/boot/dts/marvell/dove.dtsi
+++ b/arch/arm/boot/dts/marvell/dove.dtsi
@@ -785,14 +785,14 @@ gpio2: gpio-ctrl@e8400 {
 			};
 
 			lcd1: lcd-controller@810000 {
-				compatible = "marvell,dove-lcd";
+				compatible = "marvell,dove-lcd", "marvell,armada-lcdc";
 				reg = <0x810000 0x1000>;
 				interrupts = <46>;
 				status = "disabled";
 			};
 
 			lcd0: lcd-controller@820000 {
-				compatible = "marvell,dove-lcd";
+				compatible = "marvell,dove-lcd", "marvell,armada-lcdc";
 				reg = <0x820000 0x1000>;
 				interrupts = <47>;
 				status = "disabled";