[COMMON] g2d: add the task control register
authorhyesoo.yu <hyesoo.yu@samsung.com>
Fri, 12 May 2017 12:39:46 +0000 (21:39 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:27:19 +0000 (14:27 +0900)
If rotated area is larger than the non-rotated area,
H/W changes the writing direction. At this time,
if the destination is YUV 2plane, uses the Z-order
to reduce write bandwidth.

Secondly, H/W can process two jobs in parallel, so it
can be processed by dividing the target area into two.

Change-Id: I67e2dd4189d0f5f7dd92305a3ddf1771b507d086
Signed-off-by: hyesoo.yu <hyesoo.yu@samsung.com>
drivers/gpu/exynos/g2d/g2d_command.c
drivers/gpu/exynos/g2d/g2d_format.h
drivers/gpu/exynos/g2d/g2d_regs.h

index 1155ea2b59a63a219aab284c1165dd1b54fdfc23..da8a2e3ad6dc1c6dc7c7a6c570c7b59ffbb22e96 100644 (file)
 #include "g2d_uapi.h"
 #include "g2d_command.h"
 #include "g2d_regs.h"
+#include "g2d_format.h"
+
+#define layer_crop_width(layer)                                        \
+               (((layer)->commands[G2DSFR_IMG_RIGHT].value) -  \
+                ((layer)->commands[G2DSFR_IMG_LEFT].value))
+#define layer_crop_height(layer)                               \
+               (((layer)->commands[G2DSFR_IMG_BOTTOM].value) - \
+                ((layer)->commands[G2DSFR_IMG_TOP].value))
+#define layer_width(layer)     ((layer)->commands[G2DSFR_IMG_WIDTH].value)
+#define layer_height(layer)    ((layer)->commands[G2DSFR_IMG_HEIGHT].value)
+#define layer_pixelcount(layer)        (layer_width(layer) * layer_height(layer))
 
 /*
  * Number of registers of coefficients of conversion functions
@@ -59,6 +70,49 @@ void g2d_init_commands(struct g2d_task *task)
        task->cmd_count = ARRAY_SIZE(g2d_setup_commands);
 }
 
+static void g2d_set_taskctl_commands(struct g2d_task *task)
+{
+       struct g2d_reg *regs = (struct g2d_reg *)page_address(task->cmd_page);
+       struct g2d_layer *layer;
+       u32 rot = 0;
+       u32 n_rot = 0;
+       u32 size = 0; /* Size doesn't cause overflow */
+       int i;
+
+       for (i = 0; i < task->num_source; i++) {
+               layer = &task->source[i];
+               size = layer_crop_width(layer) * layer_crop_height(layer);
+
+               if (layer->commands[G2DSFR_SRC_ROTATE].value & 1)
+                       rot += size;
+               else
+                       n_rot += size;
+       }
+
+       if (rot > n_rot) {
+               u32 mode = task->target.commands[G2DSFR_IMG_COLORMODE].value;
+
+               regs[task->cmd_count].offset = G2D_TILE_DIRECTION_ORDER_REG;
+               regs[task->cmd_count].value = G2D_TILE_DIRECTION_VERTICAL;
+
+               if (IS_YUV420(mode) || IS_YUV422_2P(mode))
+                       regs[task->cmd_count].value |=
+                                       G2D_TILE_DIRECTION_ZORDER;
+
+               task->cmd_count++;
+       }
+
+       /*
+        * Divide the entire destination in half by verital,
+        * and let the H/W work in parallel.
+        * split index is half the width divided by 16
+        */
+       regs[task->cmd_count].offset = G2D_DST_SPLIT_TILE_IDX_REG;
+       regs[task->cmd_count].value = (layer_width(&task->target) / 2) >> 4;
+       regs[task->cmd_count].value |= G2D_DST_SPLIT_TILE_IDX_VFLAG;
+       task->cmd_count++;
+}
+
 void g2d_complete_commands(struct g2d_task *task)
 {
        struct g2d_reg *regs = page_address(task->cmd_page);
@@ -68,6 +122,8 @@ void g2d_complete_commands(struct g2d_task *task)
        /* 832 is the total number of the G2D registers */
        BUG_ON(task->cmd_count > 830);
 
+       g2d_set_taskctl_commands(task);
+
        /*
         * Number of commands should be multiple of 8.
         * If it is not, then pad dummy commands with no side effect.
@@ -209,9 +265,6 @@ const struct g2d_fmt *g2d_find_format(u32 fmtval)
        return NULL;
 }
 
-#define layer_width(layer)     ((layer)->commands[G2DSFR_IMG_WIDTH].value)
-#define layer_height(layer)    ((layer)->commands[G2DSFR_IMG_HEIGHT].value)
-#define layer_pixelcount(layer)        (layer_width(layer) * layer_height(layer))
 #define YUV82_BASE_ALIGNED(addr, idx) IS_ALIGNED((addr), 32 >> (idx / 2))
 #define YUV82_BASE_ALIGN(addr, idx)   ALIGN((addr), 32 >> (idx / 2))
 
index 5a00b2ea2102a44ed0b62feb5482c764866a8988..81f4ee7cd8f337c5d741507c057a794a5b8d5818 100644 (file)
@@ -75,7 +75,9 @@
 #define IS_AFBC(fmt)   ((fmt & G2D_DATAFORMAT_AFBC) != 0)
 #define IS_UORDER(fmt) ((fmt & G2D_DATAFORMAT_UORDER) != 0)
 #define IS_YUV(fmt)    (((fmt) & G2D_DATAFMT_MASK) > G2D_DATAFMT_RESERVED)
+#define IS_YUV420(fmt) ((((fmt) >> G2D_DATAFMT_SHIFT) & 0xF) == 0x8)
 #define IS_YUV422(fmt) ((((fmt) >> G2D_DATAFMT_SHIFT) & 0xE) == 0xA)
+#define IS_YUV422_2P(fmt)      ((((fmt) >> G2D_DATAFMT_SHIFT) & 0xF) == 0xB)
 #define IS_RGB(fmt)    (((fmt) & G2D_DATAFMT_MASK) < G2D_DATAFMT_8)
 #define IS_YUV420_82(fmt) (((fmt) & G2D_DATAFMT_MASK) == G2D_DATAFMT_YUV420SP82)
 
index 7355806e009e6a938cbb432edaf631c847b24647..bbb4852965b3fa75eefbfc75eb0a12b741da6d63 100644 (file)
 #define G2D_COMP_DEBUG_ADDR_REG                        0x0f0
 #define G2D_COMP_DEBUG_DATA_REG                        0x0f4
 
+/* Task Control Registers */
+#define G2D_TILE_DIRECTION_ORDER_REG           (0x1a0)
+#define G2D_DST_SPLIT_TILE_IDX_REG             (0x1a4)
+
 /* Job Manager Registers */
 #define G2D_JOB_INT_ID_REG                     0x09C
 #define G2D_JOB_HEADER_REG                     0x080
 #define G2D_GLOBAL_RESET                       (3 << 0)
 #define G2D_SOFT_RESET                         (1 << 0)
 
+/* Fields of G2D_TILE_DIRECTION_ORDER_REG */
+#define G2D_TILE_DIRECTION_ZORDER      (1 << 4)
+#define G2D_TILE_DIRECTION_VERTICAL    (1 << 0)
+
+/* Fields of G2D_DST_SPLIT_TILE_IDX_REG */
+#define G2D_DST_SPLIT_TILE_IDX_VFLAG   (1 << 16)
+#define G2D_DST_SPLIT_TILE_IDX_HFLAG   (0 << 16)
+
 void g2d_hw_push_task(struct g2d_device *g2d_dev, struct g2d_task *task);
 int g2d_hw_get_current_task(struct g2d_device *g2d_dev);
 void g2d_hw_kill_task(struct g2d_device *g2d_dev, unsigned int job_id);