[PATCH] drm/panel: panel-simple: Support panel-dpi

Maxime Ripard maxime.ripard at bootlin.com
Thu Mar 7 10:10:30 UTC 2019


The kernel has a device tree binding for panel-dpi which allows for the
panel timings to be described in the device-tree, however it wasn't
supported so far except in a (small) number of KMS drivers that had an
ad-hoc solution for this (omapdrm for example).

Just like we've seen with panel-lvds, and even though the current dogma is
to set the timings within the driver, having them in the device tree
provides a number of benefits.

The first is that it allows third party users to enable a random panel
without having to modify and recompile their kernel of choice. This might
sound like what we're trying to avoid in the first place, but it
significantly lowers the barrier of entry, both technical and practical.

Indeed, users might not have the knowledge on how to recompile and modify a
kernel by their own, or might not have any documentation on the panel
itself which would prevent any inclusion.

But moderns systems also tend to move to mechanisms like secure boot which
would prevent that kernel, provided that the kernel was able to do that,
from running in the system, unless you would know how (and be able) to
install custom keys into your system.

While the DT itself might have the same constraints, mechanisms like the
overlays allows to circumvent it.

Another thing that panel-dpi allows to address is EMC, where even though
the timings described in the driver could be functional on the board and
for the panel, it would be better to use another arbitrary frequency on a
particular board to increase the spread of the EM emissions.

Signed-off-by: Maxime Ripard <maxime.ripard at bootlin.com>
---
 drivers/gpu/drm/panel/panel-simple.c | 47 +++++++++++++++++++++++++---
 1 file changed, 42 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 9e8218f6a3f2..9aee02f05a1d 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -34,6 +34,7 @@
 #include <drm/drm_panel.h>
 
 #include <video/display_timing.h>
+#include <video/of_display_timing.h>
 #include <video/videomode.h>
 
 struct panel_desc {
@@ -396,6 +397,30 @@ static void panel_simple_shutdown(struct device *dev)
 	panel_simple_unprepare(&panel->base);
 }
 
+static struct panel_desc *panel_simple_of_parse(struct device *dev)
+{
+	struct display_timing *timings;
+	struct panel_desc *desc;
+	int ret;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return NULL;
+
+	timings = devm_kzalloc(dev, sizeof(*timings), GFP_KERNEL);
+	if (!timings)
+		return NULL;
+
+	ret = of_get_display_timing(dev->of_node, "panel-timing", timings);
+	if (ret)
+		return NULL;
+
+	desc->timings = timings;
+	desc->num_timings = 1;
+
+	return desc;
+}
+
 static const struct drm_display_mode ampire_am_480272h3tmqw_t01h_mode = {
 	.clock = 9000,
 	.hdisplay = 480,
@@ -2808,6 +2833,8 @@ static const struct of_device_id platform_of_match[] = {
 	}, {
 		.compatible = "winstar,wf35ltiacd",
 		.data = &winstar_wf35ltiacd,
+	}, {
+		.compatible = "panel-dpi",
 	}, {
 		/* sentinel */
 	}
@@ -2816,13 +2843,23 @@ MODULE_DEVICE_TABLE(of, platform_of_match);
 
 static int panel_simple_platform_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *id;
+	const struct panel_desc *desc;
 
-	id = of_match_node(platform_of_match, pdev->dev.of_node);
-	if (!id)
-		return -ENODEV;
+	if (of_device_is_compatible(pdev->dev.of_node, "panel-dpi")) {
+		desc = panel_simple_of_parse(&pdev->dev);
+		if (!desc)
+			return -EINVAL;
+	} else {
+		const struct of_device_id *id;
 
-	return panel_simple_probe(&pdev->dev, id->data);
+		id = of_match_node(platform_of_match, pdev->dev.of_node);
+		if (!id)
+			return -ENODEV;
+
+		desc = id->data;
+	}
+
+	return panel_simple_probe(&pdev->dev, desc);
 }
 
 static int panel_simple_platform_remove(struct platform_device *pdev)
-- 
2.20.1



More information about the dri-devel mailing list