video: tegra: dc: add API for selecting PREMULT_ALPHA cursor blending
Andy Ritger [Fri, 23 Aug 2013 23:24:48 +0000 (16:24 -0700)]
Add TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_RGBA_PREMULT_ALPHA flag for
tegra_dc_ext_cursor_image::flags to select premultiplied alpha.

For consistency, rename

    TEGRA_DC_EXT_CURSOR_FLAGS_2BIT_LEGACY
    TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL

to

    TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_2BIT_LEGACY
    TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_RGBA_NON_PREMULT_ALPHA

(but retain the old names as aliases, for source-level backwards
compatibility).

Add new caps bits to be reported in tegra_dc_ext_control_capabilities::caps

    TEGRA_DC_EXT_CAPABILITIES_CURSOR_TWO_COLOR
    TEGRA_DC_EXT_CAPABILITIES_CURSOR_RGBA_NON_PREMULT_ALPHA
    TEGRA_DC_EXT_CAPABILITIES_CURSOR_RGBA_PREMULT_ALPHA

Note that before this change the default RGBA cursor behavior on T114 was
non-premultipled alpha, while on T124 it was premultipled alpha.  Now,
the default RGBA cursor behavior is consistently non-premultipled alpha.
Existing T124 RGBA cursor users will need to use the new PREMULT_ALPHA
flag.

Update the cursor image format documentation in tegra_dc_ext.h

Bug 1354320

Change-Id: I82b04c97dea1830ce2659c966ae2a1b59fa06028
Signed-off-by: Andy Ritger <aritger@nvidia.com>
Reviewed-on: http://git-master/r/271749
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jon Mayo <jmayo@nvidia.com>

drivers/video/tegra/dc/ext/control.c
drivers/video/tegra/dc/ext/cursor.c
drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
include/video/tegra_dc_ext.h

index 260480e..e2c52b5 100644 (file)
@@ -138,7 +138,18 @@ static int set_event_mask(struct tegra_dc_ext_control_user *user, u32 mask)
 
 static int get_capabilities(struct tegra_dc_ext_control_capabilities *caps)
 {
-       caps->caps = TEGRA_DC_EXT_CAPABILITIES;
+       caps->caps = TEGRA_DC_EXT_CAPABILITIES_CURSOR_MODE |
+                       TEGRA_DC_EXT_CAPABILITIES_BLOCKLINEAR |
+                       TEGRA_DC_EXT_CAPABILITIES_CURSOR_TWO_COLOR;
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || \
+       defined(CONFIG_ARCH_TEGRA_12x_SOC) || \
+       defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       caps->caps |= TEGRA_DC_EXT_CAPABILITIES_CURSOR_RGBA_NON_PREMULT_ALPHA;
+#endif
+
+#if defined(CONFIG_ARCH_TEGRA_12x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       caps->caps |= TEGRA_DC_EXT_CAPABILITIES_CURSOR_RGBA_PREMULT_ALPHA;
+#endif
        return 0;
 }
 
index 459da48..6028333 100644 (file)
@@ -148,18 +148,28 @@ static int set_cursor_enable(struct tegra_dc *dc, bool enable)
        return 0;
 }
 
-static int set_cursor_blend(struct tegra_dc *dc, bool rgba)
+static int set_cursor_blend(struct tegra_dc *dc, u32 format)
 {
        u32 val = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
 
        u32 newval = WINH_CURS_SELECT(0);
 
-       if (rgba)
-               newval |= (CURSOR_MODE_SELECT(1) | CURSOR_ALPHA |
-                          CURSOR_SRC_BLEND_FACTOR_SELECT(0) |
-                          CURSOR_DST_BLEND_FACTOR_SELECT(2));
-       else
+       switch (format) {
+       case TEGRA_DC_EXT_CURSOR_FORMAT_2BIT_LEGACY:
                newval |= CURSOR_MODE_SELECT(0);
+               break;
+       case TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_NON_PREMULT_ALPHA:
+       case TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_PREMULT_ALPHA:
+               newval |= CURSOR_MODE_SELECT(1);
+#if defined(CONFIG_ARCH_TEGRA_12x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+               newval |= CURSOR_ALPHA | CURSOR_DST_BLEND_FACTOR_SELECT(2);
+               if (format == TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_PREMULT_ALPHA)
+                       newval |= CURSOR_SRC_BLEND_FACTOR_SELECT(0);
+               else
+                       newval |= CURSOR_SRC_BLEND_FACTOR_SELECT(1);
+#endif
+               break;
+       }
 
        if (val != newval) {
                tegra_dc_writel(dc, newval, DC_DISP_BLEND_CURSOR_CONTROL);
@@ -220,7 +230,7 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
        u32 size;
        int ret;
        int need_general_update = 0;
-       bool rgba = !!(args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL);
+       u32 format = TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS(args->flags);
 
        if (!user->nvmap)
                return -EFAULT;
@@ -230,10 +240,22 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
        if (!check_cursor_size(dc, size))
                return -EINVAL;
 
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
-       if (args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL)
-               return -EINVAL;
+       switch (format) {
+       case TEGRA_DC_EXT_CURSOR_FORMAT_2BIT_LEGACY:
+               break;
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || \
+       defined(CONFIG_ARCH_TEGRA_12x_SOC) || \
+       defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       case TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_NON_PREMULT_ALPHA:
+               break;
+#endif
+#if defined(CONFIG_ARCH_TEGRA_12x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       case TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_PREMULT_ALPHA:
+               break;
 #endif
+       default:
+               return -EINVAL;
+       }
 
        mutex_lock(&ext->cursor.lock);
 
@@ -262,7 +284,7 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
 
        need_general_update |= set_cursor_fg_bg(dc, args);
 
-       need_general_update |= set_cursor_blend(dc, rgba);
+       need_general_update |= set_cursor_blend(dc, format);
 
        if (need_general_update) {
                tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
index b2e8538..8934cb8 100644 (file)
@@ -102,10 +102,6 @@ struct tegra_dc_ext_event_list {
        struct list_head                list;
 };
 
-#define TEGRA_DC_EXT_CAPABILITIES \
-       (TEGRA_DC_EXT_CAPABILITIES_CURSOR_MODE |\
-        TEGRA_DC_EXT_CAPABILITIES_BLOCKLINEAR)
-
 struct tegra_dc_ext_control_user {
        struct tegra_dc_ext_control     *control;
 
index d2a79a1..8287913 100644 (file)
@@ -155,18 +155,46 @@ struct tegra_dc_ext_flip_2 {
 
 /*
  * Cursor image format:
- * - Tegra hardware supports two colors: foreground and background, specified
- *   by the client in RGB8.
- * - The image should be specified as two 1bpp bitmaps immediately following
- *   each other in memory.  Each pixel in the final cursor will be constructed
- *   from the bitmaps with the following logic:
+ *
+ * Tegra hardware supports two different cursor formats:
+ *
+ * (1) Two color cursor: foreground and background colors are
+ *     specified by the client in RGB8.
+ *
+ *     The two-color image should be specified as two 1bpp bitmaps
+ *     immediately following each other in memory.  Each pixel in the
+ *     final cursor will be constructed from the bitmaps with the
+ *     following logic:
+ *
  *             bitmap1 bitmap0
  *             (mask)  (color)
  *               1        0    transparent
  *               1        1    inverted
  *               0        0    background color
  *               0        1    foreground color
- * - Exactly one of the SIZE flags must be specified.
+ *
+ *     This format is supported when TEGRA_DC_EXT_CONTROL_GET_CAPABILITIES
+ *     reports the TEGRA_DC_EXT_CAPABILITIES_CURSOR_TWO_COLOR bit.
+ *
+ * (2) RGBA cursor: in this case the image is four bytes per pixel,
+ *     with alpha in the low eight bits.
+ *
+ *     The RGB components of the cursor image can be either
+ *     premultipled by alpha:
+ *
+ *         cursor[r,g,b] + desktop[r,g,b] * (1 - cursor[a])
+ *
+ *     or not:
+ *
+ *         cursor[r,g,b] * cursor[a] + desktop[r,g,b] * (1 - cursor[a])
+ *
+ *     TEGRA_DC_EXT_CONTROL_GET_CAPABILITIES will report one or more of
+ *     TEGRA_DC_EXT_CURSOR_FLAGS_RGBA{,_NON}_PREMULT_ALPHA to indicate
+ *     which are supported on the current hardware.
+ *
+ * Specify one of TEGRA_DC_EXT_CURSOR_FLAGS to indicate the format.
+ *
+ * Exactly one of the SIZE flags must be specified.
  */
 
 
@@ -175,8 +203,25 @@ struct tegra_dc_ext_flip_2 {
 #define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128   ((3 & 0x7) << 0)
 #define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256   ((4 & 0x7) << 0)
 #define TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(x)                (((x) & 0x7) >> 0)
-#define TEGRA_DC_EXT_CURSOR_FLAGS_2BIT_LEGACY          (0 << 16)
-#define TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL          (1 << 16)
+
+#define TEGRA_DC_EXT_CURSOR_FORMAT_2BIT_LEGACY                 (0)
+#define TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_NON_PREMULT_ALPHA      (1)
+#define TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_PREMULT_ALPHA          (3)
+
+#define TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_2BIT_LEGACY \
+       (TEGRA_DC_EXT_CURSOR_FORMAT_2BIT_LEGACY << 16)
+#define TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_RGBA_NON_PREMULT_ALPHA        \
+       (TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_NON_PREMULT_ALPHA << 16)
+#define TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_RGBA_PREMULT_ALPHA \
+       (TEGRA_DC_EXT_CURSOR_FORMAT_RGBA_PREMULT_ALPHA << 16)
+
+#define TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS(x)    (((x) >> 16) & 0x7)
+
+/* aliases for source-level backwards compatibility */
+#define TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL \
+       TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_RGBA_NON_PREMULT_ALPHA
+#define TEGRA_DC_EXT_CURSOR_FLAGS_2BIT_LEGACY \
+       TEGRA_DC_EXT_CURSOR_FORMAT_FLAGS_2BIT_LEGACY
 
 enum CR_MODE {
        legacy,
@@ -407,8 +452,13 @@ struct tegra_dc_ext_control_event_bandwidth {
        __u32 handle;
 };
 
-#define TEGRA_DC_EXT_CAPABILITIES_CURSOR_MODE  (1 << 0)
-#define TEGRA_DC_EXT_CAPABILITIES_BLOCKLINEAR   (1 << 1)
+#define TEGRA_DC_EXT_CAPABILITIES_CURSOR_MODE                  (1 << 0)
+#define TEGRA_DC_EXT_CAPABILITIES_BLOCKLINEAR                  (1 << 1)
+
+#define TEGRA_DC_EXT_CAPABILITIES_CURSOR_TWO_COLOR             (1 << 2)
+#define TEGRA_DC_EXT_CAPABILITIES_CURSOR_RGBA_NON_PREMULT_ALPHA        (1 << 3)
+#define TEGRA_DC_EXT_CAPABILITIES_CURSOR_RGBA_PREMULT_ALPHA    (1 << 4)
+
 struct tegra_dc_ext_control_capabilities {
        __u32 caps;
        /* Leave some wiggle room for future expansion */