video: tegra: dc: Add support to SCAN_COLUMN.
Kevin Huang [Thu, 23 Aug 2012 18:06:42 +0000 (11:06 -0700)]
SCAN_COLUMN is a new feature for display. Add support to it for
90 & 270 degree rotation.

Bug 964993
Bug 911213

Change-Id: Iff9818d901a4ae09dffb833bf2cf4a888f1ecec5
Signed-off-by: Kevin Huang <kevinh@nvidia.com>
Reviewed-on: http://git-master/r/130313
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

Rebase-Id: R631c88af2834303d46a21b87dfaba2ffb7eb5843

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/Kconfig
drivers/video/tegra/dc/dc_reg.h
drivers/video/tegra/dc/ext/dev.c
drivers/video/tegra/dc/window.c
include/video/tegra_dc_ext.h

index 73c1176..53cffd9 100644 (file)
@@ -537,6 +537,7 @@ struct tegra_dc_win {
 #define TEGRA_WIN_FLAG_TILED           (1 << 5)
 #define TEGRA_WIN_FLAG_H_FILTER                (1 << 6)
 #define TEGRA_WIN_FLAG_V_FILTER                (1 << 7)
+#define TEGRA_WIN_FLAG_SCAN_COLUMN     (1 << 9)
 
 
 #define TEGRA_WIN_BLEND_FLAGS_MASK \
index 0ba9918..bf1cf85 100644 (file)
@@ -35,6 +35,11 @@ config TEGRA_DC_CMU
     default n if ARCH_TEGRA_2x_SOC || ARCH_TEGRA_3x_SOC
     default y
 
+config TEGRA_DC_SCAN_COLUMN
+    bool
+    default y if ARCH_TEGRA_11x_SOC
+    default n
+
 config TEGRA_SD_GEN2
     bool
     default n if ARCH_TEGRA_2x_SOC || ARCH_TEGRA_3x_SOC
index 2e2567e..962bf79 100644 (file)
 #define DC_WIN_CSC_KVB                         0x618
 #define DC_WIN_V_FILTER_P(x)                   (0x619 + (x))
 #define DC_WIN_WIN_OPTIONS                     0x700
-#define  H_DIRECTION_INCREMENT         (0 << 0)
-#define  H_DIRECTION_DECREMENT         (1 << 0)
-#define  V_DIRECTION_INCREMENT         (0 << 2)
-#define  V_DIRECTION_DECREMENT         (1 << 2)
+#define  H_DIRECTION_DECREMENT(x)      ((x) << 0)
+#define  V_DIRECTION_DECREMENT(x)      ((x) << 2)
+#define  WIN_SCAN_COLUMN               (1 << 4)
 #define  COLOR_EXPAND                  (1 << 6)
-#define  H_FILTER_ENABLE               (1 << 8)
-#define  V_FILTER_ENABLE               (1 << 10)
+#define  H_FILTER_ENABLE(x)            ((x) << 8)
+#define  V_FILTER_ENABLE(x)            ((x) << 10)
 #define  CP_ENABLE                     (1 << 16)
 #define  CSC_ENABLE                    (1 << 18)
 #define  DV_ENABLE                     (1 << 20)
index 5a8adee..436d924 100644 (file)
@@ -234,6 +234,10 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext,
                win->global_alpha = flip_win->attr.global_alpha;
        else
                win->global_alpha = 255;
+#if defined(CONFIG_TEGRA_DC_SCAN_COLUMN)
+       if (flip_win->attr.flags & TEGRA_DC_EXT_FLIP_FLAG_SCAN_COLUMN)
+               win->flags |= TEGRA_WIN_FLAG_SCAN_COLUMN;
+#endif
        win->fmt = flip_win->attr.pixformat;
        win->x.full = flip_win->attr.x;
        win->y.full = flip_win->attr.y;
index f8375c5..0c10bed 100644 (file)
@@ -264,12 +264,52 @@ static inline u32 compute_initial_dda(fixed20_12 in)
        return dfixed_frac(in);
 }
 
+static inline void tegra_dc_update_scaling(struct tegra_dc *dc,
+                               struct tegra_dc_win *win, unsigned Bpp,
+                               unsigned Bpp_bw, bool scan_column)
+{
+       u32 h_dda, h_dda_init;
+       u32 v_dda, v_dda_init;
+
+       h_dda_init = compute_initial_dda(win->x);
+       v_dda_init = compute_initial_dda(win->y);
+
+       if (scan_column) {
+               tegra_dc_writel(dc,
+                       V_PRESCALED_SIZE(dfixed_trunc(win->w)) |
+                       H_PRESCALED_SIZE(dfixed_trunc(win->h) * Bpp),
+                       DC_WIN_PRESCALED_SIZE);
+
+               tegra_dc_writel(dc, v_dda_init, DC_WIN_H_INITIAL_DDA);
+               tegra_dc_writel(dc, h_dda_init, DC_WIN_V_INITIAL_DDA);
+               h_dda = compute_dda_inc(win->h, win->out_h,
+                               false, Bpp_bw);
+               v_dda = compute_dda_inc(win->w, win->out_w,
+                               true, Bpp_bw);
+       } else {
+               tegra_dc_writel(dc,
+                       V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
+                       H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
+                       DC_WIN_PRESCALED_SIZE);
+
+               tegra_dc_writel(dc, h_dda_init, DC_WIN_H_INITIAL_DDA);
+               tegra_dc_writel(dc, v_dda_init, DC_WIN_V_INITIAL_DDA);
+               h_dda = compute_dda_inc(win->w, win->out_w,
+                               false, Bpp_bw);
+               v_dda = compute_dda_inc(win->h, win->out_h,
+                               true, Bpp_bw);
+       }
+       tegra_dc_writel(dc, V_DDA_INC(v_dda) |
+               H_DDA_INC(h_dda), DC_WIN_DDA_INCREMENT);
+}
+
 /* does not support updating windows on multiple dcs in one call */
 int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
 {
        struct tegra_dc *dc;
        unsigned long update_mask = GENERAL_ACT_REQ;
        unsigned long val;
+       unsigned long win_options;
        bool update_blend_par = false;
        bool update_blend_seq = false;
        int i;
@@ -303,8 +343,7 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
 
        for (i = 0; i < n; i++) {
                struct tegra_dc_win *win = windows[i];
-               unsigned h_dda;
-               unsigned v_dda;
+               bool scan_column = 0;
                fixed20_12 h_offset, v_offset;
                bool invert_h = (win->flags & TEGRA_WIN_FLAG_INVERT_H) != 0;
                bool invert_v = (win->flags & TEGRA_WIN_FLAG_INVERT_V) != 0;
@@ -315,6 +354,9 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                unsigned Bpp_bw = Bpp * (yuvp ? 2 : 1);
                const bool filter_h = win_use_h_filter(dc, win);
                const bool filter_v = win_use_v_filter(dc, win);
+#if defined(CONFIG_TEGRA_DC_SCAN_COLUMN)
+               scan_column = (win->flags & TEGRA_WIN_FLAG_SCAN_COLUMN);
+#endif
 
                /* Update blender */
                if ((win->z != dc->blend.z[win->idx]) ||
@@ -347,27 +389,25 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                tegra_dc_writel(dc,
                        V_POSITION(win->out_y) | H_POSITION(win->out_x),
                        DC_WIN_POSITION);
-               tegra_dc_writel(dc,
-                       V_SIZE(win->out_h) | H_SIZE(win->out_w),
-                       DC_WIN_SIZE);
 
-               if (tegra_dc_feature_has_scaling(dc, win->idx)) {
-                       tegra_dc_writel(dc,
-                               V_PRESCALED_SIZE(dfixed_trunc(win->h)) |
-                               H_PRESCALED_SIZE(dfixed_trunc(win->w) * Bpp),
-                               DC_WIN_PRESCALED_SIZE);
-
-                       h_dda = compute_dda_inc(win->w, win->out_w, false,
-                               Bpp_bw);
-                       v_dda = compute_dda_inc(win->h, win->out_h, true,
-                               Bpp_bw);
-                       tegra_dc_writel(dc, V_DDA_INC(v_dda) |
-                               H_DDA_INC(h_dda), DC_WIN_DDA_INCREMENT);
-                       h_dda = compute_initial_dda(win->x);
-                       v_dda = compute_initial_dda(win->y);
-                       tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA);
-                       tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA);
+               /* Check scan_column flag to set window size and scaling. */
+               win_options = WIN_ENABLE;
+               if (scan_column) {
+                       win_options |= WIN_SCAN_COLUMN;
+                       win_options |= H_FILTER_ENABLE(filter_v);
+                       win_options |= V_FILTER_ENABLE(filter_h);
+                       val = V_SIZE(win->out_w) | H_SIZE(win->out_h);
+               } else {
+                       win_options |= H_FILTER_ENABLE(filter_h);
+                       win_options |= V_FILTER_ENABLE(filter_v);
+                       val = V_SIZE(win->out_h) | H_SIZE(win->out_w);
                }
+               tegra_dc_writel(dc, val, DC_WIN_SIZE);
+
+               /* Update scaling registers if window supports scaling. */
+               if (likely(tegra_dc_feature_has_scaling(dc, win->idx)))
+                       tegra_dc_update_scaling(dc, win, Bpp, Bpp_bw,
+                                                               scan_column);
 
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
                tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE);
@@ -419,26 +459,18 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                                        DC_WIN_BUFFER_ADDR_MODE);
                }
 
-               val = WIN_ENABLE;
                if (yuv)
-                       val |= CSC_ENABLE;
+                       win_options |= CSC_ENABLE;
                else if (tegra_dc_fmt_bpp(win->fmt) < 24)
-                       val |= COLOR_EXPAND;
+                       win_options |= COLOR_EXPAND;
 
                if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
-                       val |= CP_ENABLE;
-
-               if (filter_h)
-                       val |= H_FILTER_ENABLE;
-               if (filter_v)
-                       val |= V_FILTER_ENABLE;
+                       win_options |= CP_ENABLE;
 
-               if (invert_h)
-                       val |= H_DIRECTION_DECREMENT;
-               if (invert_v)
-                       val |= V_DIRECTION_DECREMENT;
+               win_options |= H_DIRECTION_DECREMENT(invert_h);
+               win_options |= V_DIRECTION_DECREMENT(invert_v);
 
-               tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
+               tegra_dc_writel(dc, win_options, DC_WIN_WIN_OPTIONS);
 
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
                if (win->global_alpha == 255)
index 8f9d042..86511e8 100644 (file)
@@ -60,6 +60,7 @@
 #define TEGRA_DC_EXT_FLIP_FLAG_TILED   (1 << 2)
 #define TEGRA_DC_EXT_FLIP_FLAG_CURSOR  (1 << 3)
 #define TEGRA_DC_EXT_FLIP_FLAG_GLOBAL_ALPHA    (1 << 4)
+#define TEGRA_DC_EXT_FLIP_FLAG_SCAN_COLUMN     (1 << 6)
 
 struct tegra_dc_ext_flip_windowattr {
        __s32   index;