diff options
author | 2015-08-04 12:17:53 -0700 | |
---|---|---|
committer | 2015-08-04 15:44:42 -0700 | |
commit | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch) | |
tree | 1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/drivers/gpu/drm/sti/sti_awg_utils.c | |
parent | 98260f3884f4a202f9ca5eabed40b1354c489b29 (diff) |
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base.
It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and
the base is:
commit 0917f823c59692d751951bf5ea699a2d1e2f26a2
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat Jul 25 12:13:34 2015 +0200
Prepare v4.1.3-rt3
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
We lose all the git history this way and it's not good. We
should apply another opnfv project repo in future.
Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/drivers/gpu/drm/sti/sti_awg_utils.c')
-rw-r--r-- | kernel/drivers/gpu/drm/sti/sti_awg_utils.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/kernel/drivers/gpu/drm/sti/sti_awg_utils.c b/kernel/drivers/gpu/drm/sti/sti_awg_utils.c new file mode 100644 index 000000000..6029a2e3d --- /dev/null +++ b/kernel/drivers/gpu/drm/sti/sti_awg_utils.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) STMicroelectronics SA 2014 + * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics. + * License terms: GNU General Public License (GPL), version 2 + */ + +#include "sti_awg_utils.h" + +#define AWG_OPCODE_OFFSET 10 + +enum opcode { + SET, + RPTSET, + RPLSET, + SKIP, + STOP, + REPEAT, + REPLAY, + JUMP, + HOLD, +}; + +static int awg_generate_instr(enum opcode opcode, + long int arg, + long int mux_sel, + long int data_en, + struct awg_code_generation_params *fwparams) +{ + u32 instruction = 0; + u32 mux = (mux_sel << 8) & 0x1ff; + u32 data_enable = (data_en << 9) & 0x2ff; + long int arg_tmp = arg; + + /* skip, repeat and replay arg should not exceed 1023. + * If user wants to exceed this value, the instruction should be + * duplicate and arg should be adjust for each duplicated instruction. + */ + + while (arg_tmp > 0) { + arg = arg_tmp; + if (fwparams->instruction_offset >= AWG_MAX_INST) { + DRM_ERROR("too many number of instructions\n"); + return -EINVAL; + } + + switch (opcode) { + case SKIP: + /* leave 'arg' + 1 pixel elapsing without changing + * output bus */ + arg--; /* pixel adjustment */ + arg_tmp--; + + if (arg < 0) { + /* SKIP instruction not needed */ + return 0; + } + + if (arg == 0) { + /* SKIP 0 not permitted but we want to skip 1 + * pixel. So we transform SKIP into SET + * instruction */ + opcode = SET; + break; + } + + mux = 0; + data_enable = 0; + arg = (arg << 22) >> 22; + arg &= (0x3ff); + break; + case REPEAT: + case REPLAY: + if (arg == 0) { + /* REPEAT or REPLAY instruction not needed */ + return 0; + } + + mux = 0; + data_enable = 0; + arg = (arg << 22) >> 22; + arg &= (0x3ff); + break; + case JUMP: + mux = 0; + data_enable = 0; + arg |= 0x40; /* for jump instruction 7th bit is 1 */ + arg = (arg << 22) >> 22; + arg &= 0x3ff; + break; + case STOP: + arg = 0; + break; + case SET: + case RPTSET: + case RPLSET: + case HOLD: + arg = (arg << 24) >> 24; + arg &= (0x0ff); + break; + default: + DRM_ERROR("instruction %d does not exist\n", opcode); + return -EINVAL; + } + + arg_tmp = arg_tmp - arg; + + arg = ((arg + mux) + data_enable); + + instruction = ((opcode) << AWG_OPCODE_OFFSET) | arg; + fwparams->ram_code[fwparams->instruction_offset] = + instruction & (0x3fff); + fwparams->instruction_offset++; + } + return 0; +} + +int sti_awg_generate_code_data_enable_mode( + struct awg_code_generation_params *fwparams, + struct awg_timing *timing) +{ + long int val; + long int data_en; + int ret = 0; + + if (timing->trailing_lines > 0) { + /* skip trailing lines */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams); + + val = timing->trailing_lines - 1; + data_en = 0; + ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams); + } + + if (timing->trailing_pixels > 0) { + /* skip trailing pixel */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams); + + val = timing->trailing_pixels - 1; + data_en = 0; + ret |= awg_generate_instr(SKIP, val, 0, data_en, fwparams); + } + + /* set DE signal high */ + val = timing->blanking_level; + data_en = 1; + ret |= awg_generate_instr((timing->trailing_pixels > 0) ? SET : RPLSET, + val, 0, data_en, fwparams); + + if (timing->blanking_pixels > 0) { + /* skip the number of active pixel */ + val = timing->active_pixels - 1; + data_en = 1; + ret |= awg_generate_instr(SKIP, val, 0, data_en, fwparams); + + /* set DE signal low */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(SET, val, 0, data_en, fwparams); + } + + /* replay the sequence as many active lines defined */ + val = timing->active_lines - 1; + data_en = 0; + ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams); + + if (timing->blanking_lines > 0) { + /* skip blanking lines */ + val = timing->blanking_level; + data_en = 0; + ret |= awg_generate_instr(RPLSET, val, 0, data_en, fwparams); + + val = timing->blanking_lines - 1; + data_en = 0; + ret |= awg_generate_instr(REPLAY, val, 0, data_en, fwparams); + } + + return ret; +} |