@@ -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;
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@linaro.org> --- drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)