video: tegra: dc: Add support to sequential blending.
Kevin Huang [Wed, 30 May 2012 17:10:24 +0000 (10:10 -0700)]
Add support to different blenders.

Bug 962353

Change-Id: Ie9530969a11dd0c329012aa54b90e3e62765c44c
Signed-off-by: Kevin Huang <kevinh@nvidia.com>
Reviewed-on: http://git-master/r/102406
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
GVS: Gerrit_Virtual_Submit

Rebase-Id: R98b3510aab3c9e3fc2645903a1269a8d179bd300

drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/dc_config.c
drivers/video/tegra/dc/dc_config.h
drivers/video/tegra/dc/dc_priv.h
drivers/video/tegra/dc/dc_reg.h
drivers/video/tegra/host/host1x/host1x_syncpt.h

index cef2855..672bdd6 100644 (file)
@@ -705,11 +705,11 @@ struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win)
 }
 EXPORT_SYMBOL(tegra_dc_get_window);
 
-static int get_topmost_window(u32 *depths, unsigned long *wins)
+static int get_topmost_window(u32 *depths, unsigned long *wins, int win_num)
 {
        int idx, best = -1;
 
-       for_each_set_bit(idx, wins, DC_N_WINDOWS) {
+       for_each_set_bit(idx, wins, win_num) {
                if (best == -1 || depths[idx] < depths[best])
                        best = idx;
        }
@@ -747,11 +747,12 @@ static u32 blend_topwin(u32 flags)
                return BLEND(NOKEY, FIX, 0xff, 0xff);
 }
 
-static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
+static u32 blend_2win(int idx, unsigned long behind_mask,
+                                               u32* flags, int xy, int win_num)
 {
        int other;
 
-       for (other = 0; other < DC_N_WINDOWS; other++) {
+       for (other = 0; other < win_num; other++) {
                if (other != idx && (xy-- == 0))
                        break;
        }
@@ -763,13 +764,14 @@ static u32 blend_2win(int idx, unsigned long behind_mask, u32* flags, int xy)
                return BLEND(NOKEY, FIX, 0x00, 0x00);
 }
 
-static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
+static u32 blend_3win(int idx, unsigned long behind_mask,
+                                               u32* flags, int win_num)
 {
        unsigned long infront_mask;
        int first;
 
        infront_mask = ~(behind_mask | BIT(idx));
-       infront_mask &= (BIT(DC_N_WINDOWS) - 1);
+       infront_mask &= (BIT(win_num) - 1);
        first = ffs(infront_mask) - 1;
 
        if (!infront_mask)
@@ -780,12 +782,13 @@ static u32 blend_3win(int idx, unsigned long behind_mask, u32* flags)
                return BLEND(NOKEY, FIX, 0x0, 0x0);
 }
 
-static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *blend)
+static void tegra_dc_set_gen1_blending(struct tegra_dc *dc, struct tegra_dc_blend *blend)
 {
-       unsigned long mask = BIT(DC_N_WINDOWS) - 1;
+       int win_num = dc->gen1_blend_num;
+       unsigned long mask = BIT(win_num) - 1;
 
        while (mask) {
-               int idx = get_topmost_window(blend->z, &mask);
+               int idx = get_topmost_window(blend->z, &mask, win_num);
 
                tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
                                DC_CMD_DISPLAY_WINDOW_HEADER);
@@ -793,12 +796,69 @@ static void tegra_dc_set_blending(struct tegra_dc *dc, struct tegra_dc_blend *bl
                                DC_WIN_BLEND_NOKEY);
                tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
                                DC_WIN_BLEND_1WIN);
-               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0),
-                               DC_WIN_BLEND_2WIN_X);
-               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1),
-                               DC_WIN_BLEND_2WIN_Y);
-               tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags),
-                               DC_WIN_BLEND_3WIN_XY);
+               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0,
+                               win_num), DC_WIN_BLEND_2WIN_X);
+               tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1,
+                               win_num), DC_WIN_BLEND_2WIN_Y);
+               tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags,
+                               win_num), DC_WIN_BLEND_3WIN_XY);
+       }
+}
+
+static void tegra_dc_set_gen2_blending(struct tegra_dc *dc,
+                                               struct tegra_dc_blend *blend)
+{
+       long val;
+       int i = 0;
+
+       for (i = 0; i < DC_N_WINDOWS; i++) {
+               if (!tegra_dc_feature_is_gen2_blender(dc, i))
+                       continue;
+
+               tegra_dc_writel(dc, WINDOW_A_SELECT << i,
+                               DC_CMD_DISPLAY_WINDOW_HEADER);
+
+               if (blend->flags[i] & TEGRA_WIN_FLAG_BLEND_COVERAGE) {
+                       tegra_dc_writel(dc,
+                                       WIN_K1(0xff) |
+                                       WIN_K2(0xff) |
+                                       WIN_BLEND_ENABLE,
+                                       DC_WINBUF_BLEND_LAYER_CONTROL);
+
+                       tegra_dc_writel(dc,
+                       WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC |
+                       WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC |
+                       WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 |
+                       WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO,
+                       DC_WINBUF_BLEND_MATCH_SELECT);
+
+                       tegra_dc_writel(dc,
+                                       WIN_ALPHA_1BIT_WEIGHT0(0) |
+                                       WIN_ALPHA_1BIT_WEIGHT1(0xff),
+                                       DC_WINBUF_BLEND_ALPHA_1BIT);
+               } else if (blend->flags[i] & TEGRA_WIN_FLAG_BLEND_PREMULT) {
+                       tegra_dc_writel(dc,
+                                       WIN_K1(0xff) |
+                                       WIN_K2(0xff) |
+                                       WIN_BLEND_ENABLE,
+                                       DC_WINBUF_BLEND_LAYER_CONTROL);
+
+                       tegra_dc_writel(dc,
+                       WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 |
+                       WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 |
+                       WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 |
+                       WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO,
+                       DC_WINBUF_BLEND_MATCH_SELECT);
+
+                       tegra_dc_writel(dc,
+                                       WIN_ALPHA_1BIT_WEIGHT0(0) |
+                                       WIN_ALPHA_1BIT_WEIGHT1(0xff),
+                                       DC_WINBUF_BLEND_ALPHA_1BIT);
+               } else {
+                       tegra_dc_writel(dc,
+                                       WIN_BLEND_BYPASS,
+                                       DC_WINBUF_BLEND_LAYER_CONTROL);
+               }
        }
 }
 
@@ -1127,7 +1187,8 @@ 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;
-       bool update_blend = false;
+       bool update_gen1_blend = false;
+       bool update_gen2_blend = false;
        int i;
 
        dc = windows[0]->dc;
@@ -1170,13 +1231,19 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
 
                if (win->z != dc->blend.z[win->idx]) {
                        dc->blend.z[win->idx] = win->z;
-                       update_blend = true;
+                       if (tegra_dc_feature_is_gen2_blender(dc, win->idx))
+                               update_gen2_blend = true;
+                       else
+                               update_gen1_blend = true;
                }
                if ((win->flags & TEGRA_WIN_BLEND_FLAGS_MASK) !=
                        dc->blend.flags[win->idx]) {
                        dc->blend.flags[win->idx] =
                                win->flags & TEGRA_WIN_BLEND_FLAGS_MASK;
-                       update_blend = true;
+                       if (tegra_dc_feature_is_gen2_blender(dc, win->idx))
+                               update_gen2_blend = true;
+                       else
+                               update_gen1_blend = true;
                }
 
                tegra_dc_writel(dc, WINDOW_A_SELECT << win->idx,
@@ -1311,8 +1378,11 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n)
                        dfixed_trunc(win->h), win->out_w, win->out_h, win->fmt);
        }
 
-       if (update_blend) {
-               tegra_dc_set_blending(dc, &dc->blend);
+       if (update_gen1_blend || update_gen2_blend) {
+               if (update_gen1_blend)
+                       tegra_dc_set_gen1_blending(dc, &dc->blend);
+               if (update_gen2_blend)
+                       tegra_dc_set_gen2_blending(dc, &dc->blend);
                for (i = 0; i < DC_N_WINDOWS; i++) {
                        if (!no_vsync)
                                dc->windows[i].dirty = 1;
index a40712f..55ab537 100644 (file)
@@ -230,8 +230,20 @@ int tegra_dc_feature_has_filter(struct tegra_dc *dc, int win_idx, int operation)
                return addr[H_FILTER];
 }
 
+int tegra_dc_feature_is_gen2_blender(struct tegra_dc *dc, int win_idx)
+{
+       long *addr = tegra_dc_parse_feature(dc, win_idx, HAS_GEN2_BLEND);
+
+       if (addr[BLEND_GENERATION] == 2)
+               return 1;
+
+       return 0;
+}
+
 void tegra_dc_feature_register(struct tegra_dc *dc)
 {
+       int i;
+       struct tegra_dc_feature_entry *entry;
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC)
        if (!dc->ndev->id)
                dc->feature = &t20_feature_table_a;
@@ -243,4 +255,12 @@ void tegra_dc_feature_register(struct tegra_dc *dc)
        else
                dc->feature = &t30_feature_table_b;
 #endif
+       /* Count the number of windows using gen1 blender. */
+       dc->gen1_blend_num = 0;
+       for (i = 0; i < dc->feature->num_entries; i++) {
+               entry = &dc->feature->entries[i];
+               if (entry->option == TEGRA_DC_FEATURE_BLEND_TYPE &&
+                                                       entry->arg[0] == 1)
+                       dc->gen1_blend_num++;
+       }
 }
index 4cc9241..7ffefdc 100644 (file)
                                ~(1 << TEGRA_WIN_FMT_B8G8R8A8) & \
                                ~(1 << TEGRA_WIN_FMT_R8G8B8A8))
 
+#define TEGRA_WIN_FMT_SIMPLE   ((1 << TEGRA_WIN_FMT_B4G4R4A4) | \
+                               (1 << TEGRA_WIN_FMT_B5G5R5A) | \
+                               (1 << TEGRA_WIN_FMT_B5G6R5) | \
+                               (1 << TEGRA_WIN_FMT_B8G8R8A8) | \
+                               (1 << TEGRA_WIN_FMT_R8G8B8A8))
 
 
 /* For each entry, we define the offset to read specific feature. Define the
 #define PITCHED_LAYOUT 0
 #define TILED_LAYOUT   1
 
+/* Define the offset for TEGRA_DC_FEATURE_BLEND_TYPE. */
+#define BLEND_GENERATION       0
+
 /* Available operations on feature table. */
 enum {
        HAS_SCALE,
@@ -142,6 +150,7 @@ struct tegra_dc_feature {
 int tegra_dc_feature_has_scaling(struct tegra_dc *dc, int win_idx);
 int tegra_dc_feature_has_tiling(struct tegra_dc *dc, int win_idx);
 int tegra_dc_feature_has_filter(struct tegra_dc *dc, int win_idx, int operation);
+int tegra_dc_feature_is_gen2_blender(struct tegra_dc *dc, int win_idx);
 
 long *tegra_dc_parse_feature(struct tegra_dc *dc, int win_idx, int operation);
 void tegra_dc_feature_register(struct tegra_dc *dc);
index d4a47f5..df55ae0 100644 (file)
@@ -140,6 +140,7 @@ struct tegra_dc {
        struct tegra_dc_ext             *ext;
 
        struct tegra_dc_feature         *feature;
+       int                             gen1_blend_num;
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry                   *debugdir;
index f009e0b..16b0b4f 100644 (file)
 #define DC_WIN_LINE_STRIDE                     0x70a
 #define  LINE_STRIDE(x)                (x)
 #define  UV_LINE_STRIDE(x)     (((x) & 0xffff) << 16)
+
+#define DC_WINBUF_BLEND_LAYER_CONTROL          0x716
+#define  WIN_K1(x)                     (((x) & 0xff) << 8)
+#define  WIN_K2(x)                     (((x) & 0xff) << 16)
+#define  WIN_BLEND_ENABLE              (0 << 24)
+#define  WIN_BLEND_BYPASS              (1 << 24)
+
+#define DC_WINBUF_BLEND_MATCH_SELECT           0x717
+#define  WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ZERO \
+                                       (0 << 0)
+#define  WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_ONE \
+                                       (1 << 0)
+#define  WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 \
+                                       (2 << 0)
+#define  WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_DST \
+                                       (3 << 0)
+#define  WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_NEG_K1_TIMES_DST \
+                                       (4 << 0)
+#define  WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC \
+                                       (5 << 0)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ZERO \
+                                       (0 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_ONE \
+                                       (1 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1 \
+                                       (2 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K2 \
+                                       (3 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_K1_TIMES_DST \
+                                       (4 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_DST \
+                                       (5 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC \
+                                       (6 << 4)
+#define  WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 \
+                                       (7 << 4)
+#define  WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_ZERO \
+                                       (0 << 8)
+#define  WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K1 \
+                                       (1 << 8)
+#define  WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 \
+                                       (2 << 8)
+#define  WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO \
+                                       (0 << 12)
+#define  WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ONE \
+                                       (1 << 12)
+#define  WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_NEG_K1_TIMES_SRC \
+                                       (2 << 12)
+#define  WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_K2 \
+                                       (3 << 12)
+
+#define DC_WINBUF_BLEND_ALPHA_1BIT             0x719
+#define  WIN_ALPHA_1BIT_WEIGHT0(x)     (((x) & 0xff) << 0)
+#define  WIN_ALPHA_1BIT_WEIGHT1(x)     (((x) & 0xff) << 8)
+
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
 #define  GET_LINE_STRIDE(x)    ((x) & 0xffff)
 #define  GET_UV_LINE_STRIDE(x) (((x) >> 16) & 0xffff)
+#endif
 
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
 #define DC_WIN_BUF_STRIDE                      0x70b
index 1e94a2b..25e5b19 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef __NVHOST_HOST1X_HOST1X_SYNCPT_H
 #define __NVHOST_HOST1X_HOST1X_SYNCPT_H
 
+#define NVSYNCPT_DISP0_D                    (5)
+#define NVSYNCPT_DISP0_H                    (6)
+#define NVSYNCPT_DISP1_H                    (7)
 #define NVSYNCPT_DISP0_A                    (8)
 #define NVSYNCPT_DISP1_A                    (9)
 #define NVSYNCPT_AVP_0                      (10)