[PATCH 2/3] drm/panel: Add display_timing support to simple panel driver

Philipp Zabel p.zabel at pengutronix.de
Thu Dec 11 09:32:45 PST 2014


Many panel data sheets additionally to typical values list allowed ranges for
timings such as hsync/vsync lengths, porches, and the pixel clock rate. This
patch allows simple panels to store a struct display_timing in place of the
struct drm_display_mode used before.
The get_modes panel_ops callback calculates the drm_display_mode list from
the typical timings and the get_timings callback returns the timings to
the connected encoder for mode fixup and validation.

Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 drivers/gpu/drm/panel/panel-simple.c | 40 ++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index c4b6167..895af09 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -33,9 +33,14 @@
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_panel.h>
 
+#include <video/display_timing.h>
+#include <video/videomode.h>
+
 struct panel_desc {
 	const struct drm_display_mode *modes;
 	unsigned int num_modes;
+	const struct display_timing *timings;
+	unsigned int num_timings;
 
 	unsigned int bpc;
 
@@ -92,6 +97,25 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel)
 	if (!panel->desc)
 		return 0;
 
+	for (i = 0; i < panel->desc->num_timings; i++) {
+		const struct display_timing *dt = &panel->desc->timings[i];
+		struct videomode vm;
+
+		videomode_from_timing(dt, &vm);
+		mode = drm_mode_create(drm);
+		if (!mode) {
+			dev_err(drm->dev, "failed to add mode %ux%u\n",
+				dt->hactive.typ, dt->vactive.typ);
+			continue;
+		}
+
+		drm_display_mode_from_videomode(&vm, mode);
+		drm_mode_set_name(mode);
+
+		drm_mode_probed_add(connector, mode);
+		num++;
+	}
+
 	for (i = 0; i < panel->desc->num_modes; i++) {
 		const struct drm_display_mode *m = &panel->desc->modes[i];
 
@@ -221,12 +245,28 @@ static int panel_simple_get_modes(struct drm_panel *panel)
 	return num;
 }
 
+static int panel_simple_get_timings(struct drm_panel *panel,
+				    unsigned int num_timings,
+				    struct display_timing *timings)
+{
+	struct panel_simple *p = to_panel_simple(panel);
+	int i;
+
+	if (timings) {
+		for (i = 0; i < min(num_timings, p->desc->num_timings); i++)
+			timings[i] = p->desc->timings[i];
+	}
+
+	return p->desc->num_timings;
+}
+
 static const struct drm_panel_funcs panel_simple_funcs = {
 	.disable = panel_simple_disable,
 	.unprepare = panel_simple_unprepare,
 	.prepare = panel_simple_prepare,
 	.enable = panel_simple_enable,
 	.get_modes = panel_simple_get_modes,
+	.get_timings = panel_simple_get_timings,
 };
 
 static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
-- 
2.1.3



More information about the dri-devel mailing list