[PATCH] drm/panel: s6d16d0: Support rotation

Linus Walleij linus.walleij at linaro.org
Sun Jul 28 10:52:23 UTC 2019


Use the standard DT "rotation" attribute from
Documentation/devicetree/bindings/display/panel/panel.txt
to handle designs where the panel is mounted rotated
90 (or 270) degrees as in the ST-Ericsson HREF520
reference design.

Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
---
 drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 38 ++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
index f75bef24e050..d4c33781ade8 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
@@ -13,6 +13,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/delay.h>
 #include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/module.h>
 
 struct s6d16d0 {
@@ -20,6 +21,7 @@ struct s6d16d0 {
 	struct drm_panel panel;
 	struct regulator *supply;
 	struct gpio_desc *reset_gpio;
+	bool flipped;
 };
 
 /*
@@ -47,6 +49,28 @@ static const struct drm_display_mode samsung_s6d16d0_mode = {
 	.height_mm = 48,
 };
 
+/* In the standing mode, things are just flipped around X/Y */
+static const struct drm_display_mode samsung_s6d16d0_standing_mode = {
+	/* HS clock, (htotal*vtotal*vrefresh)/1000 */
+	.clock = 420160,
+	.hdisplay = 480,
+	.hsync_start = 480 + 154,
+	.hsync_end = 480 + 154 + 16,
+	.htotal = 480 + 154 + 16 + 32,
+	.vdisplay = 864,
+	.vsync_start = 864 + 1,
+	.vsync_end = 864 + 1 + 1,
+	.vtotal = 864 + 1 + 1 + 1,
+	/*
+	 * This depends on the clocking HS vs LP rate, this value
+	 * is calculated as:
+	 * vrefresh = (clock * 1000) / (htotal*vtotal)
+	 */
+	.vrefresh = 816,
+	.width_mm = 48,
+	.height_mm = 84,
+};
+
 static inline struct s6d16d0 *panel_to_s6d16d0(struct drm_panel *panel)
 {
 	return container_of(panel, struct s6d16d0, panel);
@@ -145,10 +169,16 @@ static int s6d16d0_disable(struct drm_panel *panel)
 
 static int s6d16d0_get_modes(struct drm_panel *panel)
 {
+	struct s6d16d0 *s6 = panel_to_s6d16d0(panel);
 	struct drm_connector *connector = panel->connector;
 	struct drm_display_mode *mode;
 
-	mode = drm_mode_duplicate(panel->drm, &samsung_s6d16d0_mode);
+	if (s6->flipped)
+		mode = drm_mode_duplicate(panel->drm,
+					  &samsung_s6d16d0_standing_mode);
+	else
+		mode = drm_mode_duplicate(panel->drm,
+					  &samsung_s6d16d0_mode);
 	if (!mode) {
 		DRM_ERROR("bad mode or failed to add mode\n");
 		return -EINVAL;
@@ -176,6 +206,7 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi)
 {
 	struct device *dev = &dsi->dev;
 	struct s6d16d0 *s6;
+	u32 rot_angle;
 	int ret;
 
 	s6 = devm_kzalloc(dev, sizeof(struct s6d16d0), GFP_KERNEL);
@@ -215,6 +246,11 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi)
 		return ret;
 	}
 
+	/* Support rotation of the display panel */
+	ret = of_property_read_u32(dev->of_node, "rotation", &rot_angle);
+	if (!ret && (rot_angle == 90 || rot_angle == 270))
+		s6->flipped = true;
+
 	drm_panel_init(&s6->panel);
 	s6->panel.dev = dev;
 	s6->panel.funcs = &s6d16d0_drm_funcs;
-- 
2.21.0



More information about the dri-devel mailing list