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@xxxxxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel