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.wall...@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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to