{
memcpy(page_address(task->cmd_page),
&g2d_setup_commands, sizeof(g2d_setup_commands));
- task->cmd_count = ARRAY_SIZE(g2d_setup_commands);
+ task->sec.cmd_count = ARRAY_SIZE(g2d_setup_commands);
}
static void g2d_set_taskctl_commands(struct g2d_task *task)
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;
+ regs[task->sec.cmd_count].offset = G2D_TILE_DIRECTION_ORDER_REG;
+ regs[task->sec.cmd_count].value = G2D_TILE_DIRECTION_VERTICAL;
if (!IS_HWFC(task->flags) &&
(IS_YUV420(mode) || IS_YUV422_2P(mode)))
- regs[task->cmd_count].value |=
+ regs[task->sec.cmd_count].value |=
G2D_TILE_DIRECTION_ZORDER;
- task->cmd_count++;
+ task->sec.cmd_count++;
}
/*
* 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++;
+ regs[task->sec.cmd_count].offset = G2D_DST_SPLIT_TILE_IDX_REG;
+ regs[task->sec.cmd_count].value = (layer_width(&task->target) / 2) >> 4;
+ regs[task->sec.cmd_count].value |= G2D_DST_SPLIT_TILE_IDX_VFLAG;
+ task->sec.cmd_count++;
}
static void g2d_set_hwfc_commands(struct g2d_task *task)
{
struct g2d_reg *regs = (struct g2d_reg *)page_address(task->cmd_page);
- regs[task->cmd_count].offset = G2D_HWFC_CAPTURE_IDX_REG;
- regs[task->cmd_count].value = IS_HWFC(task->flags) ?
+ regs[task->sec.cmd_count].offset = G2D_HWFC_CAPTURE_IDX_REG;
+ regs[task->sec.cmd_count].value = IS_HWFC(task->flags) ?
G2D_HWFC_CAPTURE_HWFC_JOB : 0;
- regs[task->cmd_count].value |= task->job_id;
+ regs[task->sec.cmd_count].value |= task->sec.job_id;
- task->cmd_count++;
+ task->sec.cmd_count++;
}
static void g2d_set_start_commands(struct g2d_task *task)
* Number of commands should be multiple of 8.
* If it is not, then pad dummy commands with no side effect.
*/
- while ((task->cmd_count & 7) != 0) {
- regs[task->cmd_count].offset = G2D_LAYER_UPDATE_REG;
- regs[task->cmd_count].value = regs[TASK_REG_LAYER_UPDATE].value;
- task->cmd_count++;
+ while ((task->sec.cmd_count & 7) != 0) {
+ regs[task->sec.cmd_count].offset = G2D_LAYER_UPDATE_REG;
+ regs[task->sec.cmd_count].value =
+ regs[TASK_REG_LAYER_UPDATE].value;
+ task->sec.cmd_count++;
}
}
{
/* 832 is the total number of the G2D registers */
/* Tuned tone mapping LUT (66 entries) might be specified */
- BUG_ON(task->cmd_count > 896);
+ BUG_ON(task->sec.cmd_count > 896);
g2d_set_taskctl_commands(task);
return -EINVAL;
}
- cmdaddr += task->cmd_count;
+ cmdaddr += task->sec.cmd_count;
copied = g2d_copy_commands(g2d_dev, -1, cmdaddr, cmds->target,
target_command_checker, G2DSFR_DST_FIELD_COUNT);
task->target.commands = cmdaddr;
cmdaddr += copied;
- task->cmd_count += copied;
+ task->sec.cmd_count += copied;
for (i = 0; i < num_sources; i++) {
u32 srccmds[G2DSFR_SRC_FIELD_COUNT];
task->source[i].commands = cmdaddr;
cmdaddr += copied;
- task->cmd_count += copied;
+ task->sec.cmd_count += copied;
}
if (copy_from_user(cmdaddr, cmds->extra,
if (!g2d_validate_extra_command(g2d_dev, cmdaddr, cmds->num_extra_regs))
return -EINVAL;
- task->cmd_count += cmds->num_extra_regs;
+ task->sec.cmd_count += cmds->num_extra_regs;
/* overwrite if TM LUT values are specified: consumes 66 entries */
if (exynos_hdr_get_tm_lut(tm_tuned_lut)) {
(unsigned long)(base + i * sizeof(u32));
cmdaddr->value = tm_tuned_lut[i];
cmdaddr++;
- task->cmd_count++;
+ task->sec.cmd_count++;
}
}
}
const struct g2d_fmt *fmt = g2d_find_format(colormode,
task->g2d_dev->caps);
struct g2d_reg *reg = (struct g2d_reg *)page_address(task->cmd_page);
- unsigned int cmd_count = task->cmd_count;
+ unsigned int cmd_count = task->sec.cmd_count;
u32 width = layer_width(layer);
u32 height = layer_height(layer);
unsigned int i;
return 0;
}
- reg[task->cmd_count].offset = base_offset + reg_offset[2];
- reg[task->cmd_count].value = layer->buffer[0].dma_addr;
- reg[task->cmd_count + 1].offset = base_offset + reg_offset[3];
+ reg[task->sec.cmd_count].offset = base_offset + reg_offset[2];
+ reg[task->sec.cmd_count].value = layer->buffer[0].dma_addr;
+ reg[task->sec.cmd_count + 1].offset = base_offset + reg_offset[3];
if (base_offset == TARGET_OFFSET)
- reg[task->cmd_count + 1].value =
+ reg[task->sec.cmd_count + 1].value =
ALIGN(AFBC_HEADER_SIZE(layer->commands)
+ layer->buffer[0].dma_addr, align);
else
- reg[task->cmd_count + 1].value = layer->buffer[0].dma_addr;
+ reg[task->sec.cmd_count + 1].value = layer->buffer[0].dma_addr;
- return task->cmd_count + 2;
+ return task->sec.cmd_count + 2;
}
bool g2d_prepare_source(struct g2d_task *task,
if ((layer->flags & G2D_LAYERFLAG_COLORFILL) != 0)
return true;
- task->cmd_count = ((colormode & G2D_DATAFORMAT_AFBC) != 0)
+ task->sec.cmd_count = ((colormode & G2D_DATAFORMAT_AFBC) != 0)
? g2d_set_afbc_buffer(task, layer, LAYER_OFFSET(index))
: g2d_set_image_buffer(task, layer, colormode,
offsets, LAYER_OFFSET(index));
* It is alright to set task->cmd_count to 0
* because this task is to be discarded.
*/
- return task->cmd_count != 0;
+ return task->sec.cmd_count != 0;
}
bool g2d_prepare_target(struct g2d_task *task)
{
u32 colormode = task->target.commands[G2DSFR_IMG_COLORMODE].value;
- task->cmd_count = ((colormode & G2D_DATAFORMAT_AFBC) != 0)
+ task->sec.cmd_count = ((colormode & G2D_DATAFORMAT_AFBC) != 0)
? g2d_set_afbc_buffer(task, &task->target,
TARGET_OFFSET)
: g2d_set_image_buffer(task, &task->target, colormode,
dst_base_reg_offset, TARGET_OFFSET);
- return task->cmd_count != 0;
+ return task->sec.cmd_count != 0;
}
for (task = g2d_dev->tasks; task; task = task->next) {
seq_printf(s, "TASK[%d]: state %#lx flags %#x ",
- task->job_id, task->state, task->flags);
+ task->sec.job_id, task->state, task->flags);
seq_printf(s, "prio %d begin@%llu end@%llu nr_src %d\n",
- task->priority, ktime_to_us(task->ktime_begin),
+ task->sec.priority, ktime_to_us(task->ktime_begin),
ktime_to_us(task->ktime_end), task->num_source);
}
regs = page_address(task->cmd_page);
- for (i = 0; i < task->cmd_count; i++)
+ for (i = 0; i < task->sec.cmd_count; i++)
pr_info("G2D: CMD[%03d] %#06x, %#010x\n",
i, regs[i].offset, regs[i].value);
}
if (task) {
stamp->state = task->state;
- stamp->job_id = task->job_id;
+ stamp->job_id = task->sec.job_id;
} else {
stamp->job_id = 0;
stamp->state = 0;
if (g2d_debug == 1) {
dev_info(task->g2d_dev->dev,
"Job %u consumed %06u usec. by H/W\n",
- task->job_id, val);
+ task->sec.job_id, val);
} else if (g2d_debug == 2) {
g2d_dump_info(task->g2d_dev, task);
}
/* media/exynos_tsmux.h includes below functions */
if (task != NULL && IS_HWFC(task->flags)) {
if (stampid == G2D_STAMP_STATE_PUSH)
- g2d_blending_start(task->job_id);
+ g2d_blending_start(task->sec.job_id);
if (stampid == G2D_STAMP_STATE_DONE)
- g2d_blending_end(task->job_id);
+ g2d_blending_end(task->sec.job_id);
}
}
spin_lock_irqsave(&g2d_dev->lock_task, flags);
for (task = g2d_dev->tasks; task != NULL; task = task->next) {
- if (!is_task_state_idle(task) && (task->priority < priority)) {
+ if (!is_task_state_idle(task) &&
+ (task->sec.priority < priority)) {
spin_unlock_irqrestore(&g2d_dev->lock_task, flags);
return -EBUSY;
}
spin_lock_irqsave(&g2d_dev->lock_task, flags);
- job_state = g2d_hw_get_job_state(g2d_dev, task->job_id);
+ job_state = g2d_hw_get_job_state(g2d_dev, task->sec.job_id);
g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_HW, job_state);
dev_err(g2d_dev->dev, "%s: Time is up: %d msec for job %u %lu %u\n",
__func__, G2D_HW_TIMEOUT_MSEC,
- task->job_id, task->state, job_state);
+ task->sec.job_id, task->state, job_state);
if (!is_task_state_active(task))
/*
mark_task_state_killed(task);
- g2d_hw_kill_task(g2d_dev, task->job_id);
+ g2d_hw_kill_task(g2d_dev, task->sec.job_id);
out:
spin_unlock_irqrestore(&g2d_dev->lock_task, flags);
task->ktime_begin = ktime_get();
if (IS_HWFC(task->flags))
- hwfc_set_valid_buffer(task->job_id, task->job_id);
+ hwfc_set_valid_buffer(task->sec.job_id, task->sec.job_id);
return 0;
}
break;
}
- g2d_stamp_task(task, G2D_STAMP_STATE_BEGIN, task->priority);
+ g2d_stamp_task(task, G2D_STAMP_STATE_BEGIN, task->sec.priority);
g2d_start_task(task);
#include "g2d_debug.h"
#include "g2d_secure.h"
-struct g2d_task_secbuf {
- unsigned long cmd_paddr;
- int cmd_count;
- int priority;
- int job_id;
- int secure_layer;
-};
-
static void g2d_hw_push_task_by_smc(struct g2d_device *g2d_dev,
struct g2d_task *task)
{
- struct g2d_task_secbuf sec_task;
int i;
- sec_task.cmd_paddr = (unsigned long)page_to_phys(task->cmd_page);
- sec_task.cmd_count = task->cmd_count;
- sec_task.priority = task->priority;
- sec_task.job_id = task->job_id;
- sec_task.secure_layer = 0;
+ task->sec.secure_layer_mask = 0;
- for (i = 0; i < task->num_source; i++) {
+ for (i = 0; i < task->num_source; i++)
if (!!(task->source[i].flags & G2D_LAYERFLAG_SECURE))
- sec_task.secure_layer |= 1 << i;
- }
+ task->sec.secure_layer_mask |= 1 << i;
+
if (!!(task->target.flags & G2D_LAYERFLAG_SECURE) ||
- !!(sec_task.secure_layer))
- sec_task.secure_layer |= 1 << 24;
+ !!(task->sec.secure_layer_mask))
+ task->sec.secure_layer_mask |= 1 << 24;
- __flush_dcache_area(&sec_task, sizeof(sec_task));
+ __flush_dcache_area(&task->sec, sizeof(task->sec));
__flush_dcache_area(page_address(task->cmd_page), G2D_CMD_LIST_SIZE);
- if (exynos_smc(SMC_DRM_G2D_CMD_DATA, virt_to_phys(&sec_task), 0, 0)) {
+ if (exynos_smc(SMC_DRM_G2D_CMD_DATA, virt_to_phys(&task->sec), 0, 0)) {
dev_err(g2d_dev->dev, "%s : Failed to push %d %d %d %d\n",
- __func__, sec_task.cmd_count, sec_task.priority,
- sec_task.job_id, sec_task.secure_layer);
+ __func__, task->sec.cmd_count, task->sec.priority,
+ task->sec.job_id, task->sec.secure_layer_mask);
g2d_dump_info(g2d_dev, task);
BUG();
void g2d_hw_push_task(struct g2d_device *g2d_dev, struct g2d_task *task)
{
bool self_prot = g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
- u32 state = g2d_hw_get_job_state(g2d_dev, task->job_id);
+ u32 state = g2d_hw_get_job_state(g2d_dev, task->sec.job_id);
if (state != G2D_JOB_STATE_DONE)
dev_err(g2d_dev->dev, "%s: Unexpected state %#x of JOB %d\n",
- __func__, state, task->job_id);
+ __func__, state, task->sec.job_id);
if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)) {
unsigned int i;
writel_relaxed(state,
g2d_dev->reg +
- G2D_JOBn_LAYER_SECURE_REG(task->job_id));
+ G2D_JOBn_LAYER_SECURE_REG(task->sec.job_id));
}
- writel_relaxed(G2D_JOB_HEADER_DATA(task->priority, task->job_id),
+ writel_relaxed(G2D_JOB_HEADER_DATA(task->sec.priority,
+ task->sec.job_id),
g2d_dev->reg + G2D_JOB_HEADER_REG);
writel_relaxed(G2D_ERR_INT_ENABLE, g2d_dev->reg + G2D_INTEN_REG);
writel_relaxed(task->cmd_addr, g2d_dev->reg + G2D_JOB_BASEADDR_REG);
- writel_relaxed(task->cmd_count, g2d_dev->reg + G2D_JOB_SFRNUM_REG);
- writel_relaxed(1 << task->job_id, g2d_dev->reg + G2D_JOB_INT_ID_REG);
+ writel_relaxed(task->sec.cmd_count, g2d_dev->reg + G2D_JOB_SFRNUM_REG);
+ writel_relaxed(1 << task->sec.job_id,
+ g2d_dev->reg + G2D_JOB_INT_ID_REG);
writel(G2D_JOBPUSH_INT_ENABLE, g2d_dev->reg + G2D_JOB_PUSH_REG);
}
struct g2d_task *task;
list_for_each_entry(task, &g2d_dev->tasks_active, node) {
- if (task->job_id == id)
+ if (task->sec.job_id == id)
return task;
}
struct g2d_task, node);
dev_err(g2d_dev->dev, "%s: Flushed task of ID %d\n",
- __func__, task->job_id);
+ __func__, task->sec.job_id);
mark_task_state_killed(task);
INIT_WORK(&task->work, g2d_task_schedule_work);
init_task_state(task);
- task->priority = g2d_ctx->priority;
+ task->sec.priority = g2d_ctx->priority;
g2d_init_commands(task);
if (IS_HWFC(task->flags)) {
/* hwfc job id will be set from repeater driver info */
- task->job_id = G2D_MAX_JOBS;
+ task->sec.job_id = G2D_MAX_JOBS;
list_add(&task->node, &g2d_dev->tasks_free_hwfc);
} else {
list_add(&task->node, &g2d_dev->tasks_free);
goto err_page;
}
- task->job_id = id;
+ task->sec.job_id = id;
task->bufidx = -1;
task->g2d_dev = g2d_dev;
if (ret)
goto err_map;
+ task->sec.cmd_paddr = (unsigned long)page_to_phys(task->cmd_page);
+
for (i = 0; i < g2d_dev->max_layers; i++)
task->source[i].task = task;
task->target.task = task;
struct g2d_device *g2d_dev;
unsigned int flags;
- unsigned int job_id;
unsigned int bufidx;
unsigned long state;
struct sync_file *release_fence;
/* Command list */
struct page *cmd_page;
dma_addr_t cmd_addr;
- unsigned int cmd_count;
- unsigned int priority;
+ struct {
+ unsigned long cmd_paddr;
+ unsigned int cmd_count;
+ unsigned int priority;
+ unsigned int job_id;
+ /* temporarily used by g2d_hw_push_task_by_smc */
+ int secure_layer_mask;
+ } sec;
+
ktime_t ktime_begin;
ktime_t ktime_end;
return PTR_ERR(dmabuf);
}
} else {
- dmabuf = ctx->hwfc_info->bufs[task->job_id];
+ dmabuf = ctx->hwfc_info->bufs[task->sec.job_id];
get_dma_buf(dmabuf);
}
ptask = ptask->next;
continue;
}
- if ((ptask->job_id == task->bufidx) &&
+ if ((ptask->sec.job_id == task->bufidx) &&
!is_task_state_idle(ptask)) {
dev_err(dev, "%s: The %d task is not idle\n",
__func__, task->bufidx);
g2d_stamp_task(task, G2D_STAMP_STATE_HWFCBUF, task->bufidx);
- task->job_id = task->bufidx;
+ task->sec.job_id = task->bufidx;
spin_unlock_irqrestore(&task->g2d_dev->lock_task, flags);