[COMMON] g2d: Add command list completion
authorCho KyongHo <pullip.cho@samsung.com>
Thu, 4 May 2017 09:37:49 +0000 (18:37 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:13 +0000 (20:22 +0300)
To push a command list to H/W, G2D driver should add some required
information to the command list including:
- initialization of H/W for the new job
- information about the layers involved with the job.
- information about secure layers.
The driver should also satisfies the requirment of H/W. It includes
alignment restriction of the number of commands in the command list.
If the number of commands are not multiple of 8, the driver appends
some redundant commands to satisfy the restriction.

Change-Id: Ia986f95de7df8e96907cac0cf7197f1fc3560db8
Signed-off-by: Cho KyongHo <pullip.cho@samsung.com>
drivers/gpu/exynos/g2d/g2d_command.c
drivers/gpu/exynos/g2d/g2d_command.h
drivers/gpu/exynos/g2d/g2d_regs.h
drivers/gpu/exynos/g2d/g2d_task.c
drivers/gpu/exynos/g2d/g2d_uapi_process.c

index 651790dd1c710ce2424552415d60aea940391d4a..1155ea2b59a63a219aab284c1165dd1b54fdfc23 100644 (file)
 #include "g2d_task.h"
 #include "g2d_uapi.h"
 #include "g2d_command.h"
+#include "g2d_regs.h"
+
+/*
+ * Number of registers of coefficients of conversion functions
+ * - 4 sets of color space conversion for sources
+ * - 1 set of color space conversion for destination
+ * - 2 sets of HDR coefficients
+ *   - 2 matrices of EOTF
+ *   - 2 matrices of Gamut mapping
+ *   - 2 matrices Tone mappings
+ */
+#define MAX_EXTRA_REGS (9 * 5 + (65 + 9 + 33) * 2)
+
+enum {
+       TASK_REG_SOFT_RESET,
+       TASK_REG_LAYER_SECURE,
+       TASK_REG_LAYER_UPDATE,
+
+       TASK_REG_COUNT
+};
+
+/*
+ * G2D_SECURE_LAYER_REG and G2D_LAYER_UPDATE_REG are updated in
+ * g2d_prepare_source() and g2d_prepare_target().
+ */
+static struct g2d_reg g2d_setup_commands[TASK_REG_COUNT] = {
+       {G2D_SOFT_RESET_REG,   0x00000004}, /* CoreSFRClear */
+       {G2D_SECURE_LAYER_REG, 0x00000000},
+       {G2D_LAYER_UPDATE_REG, 0x00000000},
+};
+
+void g2d_init_commands(struct g2d_task *task)
+{
+       memcpy(page_address(task->cmd_page),
+               &g2d_setup_commands, sizeof(g2d_setup_commands));
+       task->cmd_count = ARRAY_SIZE(g2d_setup_commands);
+}
+
+void g2d_complete_commands(struct g2d_task *task)
+{
+       struct g2d_reg *regs = page_address(task->cmd_page);
+       unsigned int n = 8 - ((task->cmd_count + 1) % 8);
+
+
+       /* 832 is the total number of the G2D registers */
+       BUG_ON(task->cmd_count > 830);
+
+       /*
+        * Number of commands should be multiple of 8.
+        * If it is not, then pad dummy commands with no side effect.
+        */
+       while (n-- > 0) {
+               regs[task->cmd_count].offset = G2D_LAYER_UPDATE_REG;
+               regs[task->cmd_count].value = regs[TASK_REG_LAYER_UPDATE].value;
+               task->cmd_count++;
+       }
+
+       regs[task->cmd_count].offset = G2D_BITBLT_START_REG;
+       regs[task->cmd_count].value = 1;
+       task->cmd_count++;
+}
 
 #define NV12N_Y_SIZE(w, h)     (ALIGN((w), 16) * ALIGN((h), 16) + 256)
 #define NV12N_CBCR_SIZE(w, h)          \
@@ -587,7 +648,13 @@ int g2d_import_commands(struct g2d_device *g2d_dev, struct g2d_task *task,
        unsigned int i;
        int copied;
 
-       task->cmd_count = 0;
+       if (cmds->num_extra_regs > MAX_EXTRA_REGS) {
+               dev_err(dev, "%s: Too many coefficient reigsters %d\n",
+                       __func__, cmds->num_extra_regs);
+               return -EINVAL;
+       }
+
+       cmdaddr += task->cmd_count;
 
        copied = g2d_copy_commands(g2d_dev, -1, cmdaddr, cmds->target,
                                target_command_checker, G2DSFR_DST_FIELD_COUNT);
@@ -734,10 +801,19 @@ static unsigned int g2d_set_afbc_buffer(struct g2d_task *task,
 bool g2d_prepare_source(struct g2d_task *task,
                        struct g2d_layer *layer, int index)
 {
+       struct g2d_reg *reg = (struct g2d_reg *)page_address(task->cmd_page);
        u32 colormode = layer->commands[G2DSFR_IMG_COLORMODE].value;
        unsigned char *offsets = IS_YUV420_82(colormode) ?
                                src_base_reg_offset_yuv82 : src_base_reg_offset;
 
+       reg[TASK_REG_LAYER_UPDATE].value |= 1 << index;
+
+       if ((layer->flags & G2D_LAYERFLAG_COLORFILL) != 0)
+               return true;
+
+       if ((layer->flags & G2D_LAYERFLAG_SECURE) != 0)
+               reg[TASK_REG_LAYER_SECURE].value |= 1 << index;
+
        task->cmd_count = ((colormode & G2D_DATAFORMAT_AFBC) != 0)
                        ? g2d_set_afbc_buffer(task, layer, LAYER_OFFSET(index))
                        : g2d_set_image_buffer(task, layer, colormode,
@@ -751,8 +827,12 @@ bool g2d_prepare_source(struct g2d_task *task,
 
 bool g2d_prepare_target(struct g2d_task *task)
 {
+       struct g2d_reg *reg = (struct g2d_reg *)page_address(task->cmd_page);
        u32 colormode = task->target.commands[G2DSFR_IMG_COLORMODE].value;
 
+       if ((task->target.flags & G2D_LAYERFLAG_SECURE) != 0)
+               reg[TASK_REG_LAYER_SECURE].value |= 1 << 24;
+
        task->cmd_count = ((colormode & G2D_DATAFORMAT_AFBC) != 0)
                        ? g2d_set_afbc_buffer(task, &task->target,
                                              TARGET_OFFSET)
index 3f2f9b86cfaef9cee85efbafc2c8c8a951fc0188..5de201de83ba32bf7da1094e284a0d8c36b6298f 100644 (file)
@@ -30,6 +30,8 @@ struct g2d_fmt {
        u8              num_planes;
 };
 
+void g2d_init_commands(struct g2d_task *task);
+void g2d_complete_commands(struct g2d_task *task);
 const struct g2d_fmt *g2d_find_format(u32 fmtval);
 int g2d_import_commands(struct g2d_device *g2d_dev, struct g2d_task *task,
                        struct g2d_task_data *data, unsigned int num_sources);
index 9f9ff6a484079863a5b56859d8338a0b90ea2446..7355806e009e6a938cbb432edaf631c847b24647 100644 (file)
@@ -20,6 +20,8 @@
 #define G2D_FIFO_STAT_REG                      0x010
 #define G2D_VERSION_INFO_REG                   0x014
 #define G2D_AXI_MODE_REG                       0x01c
+#define G2D_SECURE_MODE_REG                    0x030
+#define G2D_SECURE_LAYER_REG                   0x034
 #define G2D_COMP_DEBUG_ADDR_REG                        0x0f0
 #define G2D_COMP_DEBUG_DATA_REG                        0x0f4
 
index cd1fd7a2cc95e33350a3d723a62967e4ec73b200..fffb7cf13cf1db4815ce4554b22b4c3dbebd0c76 100644 (file)
@@ -21,6 +21,7 @@
 #include "g2d.h"
 #include "g2d_task.h"
 #include "g2d_uapi_process.h"
+#include "g2d_command.h"
 
 struct g2d_task *g2d_get_active_task_from_id(struct g2d_device *g2d_dev,
                                             unsigned int id)
@@ -170,6 +171,8 @@ static void g2d_schedule_task(struct g2d_task *task)
        unsigned long flags;
        int ret;
 
+       g2d_complete_commands(task);
+
        /*
         * Unconditional invocation of pm_runtime_get_sync() has no side effect
         * in g2d_schedule(). It just increases the usage count of RPM if this
@@ -259,6 +262,8 @@ struct g2d_task *g2d_get_free_task(struct g2d_device *g2d_dev)
 
        init_task_state(task);
 
+       g2d_init_commands(task);
+
        spin_unlock_irqrestore(&g2d_dev->lock_task, flags);
 
        return task;
index 029f32235c98ce90881058aff8d0517190b17d49..03c10f0ccb2fdbbef3c332a4a00f2dcb06e93e11 100644 (file)
@@ -534,6 +534,8 @@ static int g2d_get_source(struct g2d_device *g2d_dev, struct g2d_task *task,
                if (layer->flags & G2D_LAYERFLAG_COLORFILL) {
                        layer->num_buffers = 0;
                        layer->flags &= ~G2D_LAYERFLAG_ACQUIRE_FENCE;
+                       /* g2d_prepare_source() always successes for colofill */
+                       g2d_prepare_source(task, layer, index);
                        return 0;
                }