video: tegra-dc: add 180 degree panel rotation
Unlike 90 and 270 degree rotation, 180 degree rotation is more
common and does not require scaling. Implement it for correct
grouper support.
Tested-by: Andreas Westman Dorcsak <hedmoo@yahoo.com> # Google Nexus 7 2012
Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # Google Nexus 7 2012
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c
index e004ee3..e279650 100644
--- a/drivers/video/tegra20/tegra-dc.c
+++ b/drivers/video/tegra20/tegra-dc.c
@@ -37,6 +37,7 @@
fdt_addr_t frame_buffer; /* Address of frame buffer */
unsigned pixel_clock; /* Pixel clock in Hz */
int dc_clk[2]; /* Contains clk and its parent */
+ bool rotation; /* 180 degree panel turn */
};
enum {
@@ -46,8 +47,10 @@
LCD_MAX_LOG2_BPP = VIDEO_BPP16,
};
-static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win)
+static void update_window(struct tegra_lcd_priv *priv,
+ struct disp_ctl_win *win)
{
+ struct dc_ctlr *dc = priv->dc;
unsigned h_dda, v_dda;
unsigned long val;
@@ -88,6 +91,10 @@
val = WIN_ENABLE;
if (win->bpp < 24)
val |= COLOR_EXPAND;
+
+ if (priv->rotation)
+ val |= H_DIRECTION | V_DIRECTION;
+
writel(val, &dc->win.win_opt);
writel((unsigned long)win->phys_addr, &dc->winbuf.start_addr);
@@ -224,8 +231,14 @@
static int setup_window(struct disp_ctl_win *win,
struct tegra_lcd_priv *priv)
{
- win->x = 0;
- win->y = 0;
+ if (priv->rotation) {
+ win->x = priv->width * 2;
+ win->y = priv->height;
+ } else {
+ win->x = 0;
+ win->y = 0;
+ }
+
win->w = priv->width;
win->h = priv->height;
win->out_x = 0;
@@ -298,7 +311,7 @@
if (setup_window(&window, priv))
return -1;
- update_window(priv->dc, &window);
+ update_window(priv, &window);
return 0;
}
@@ -370,6 +383,8 @@
return -EINVAL;
}
+ priv->rotation = dev_read_bool(dev, "nvidia,180-rotation");
+
rgb = fdt_subnode_offset(blob, node, "rgb");
if (rgb < 0) {
debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n",