Release 4.15 drivers/gpu/drm/sti/sti_awg_utils.c
  
  
  
/*
 * 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_DELAY (-5)
#define AWG_OPCODE_OFFSET 10
#define AWG_MAX_ARG       0x3ff
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.
         *
         * mux_sel is used in case of SAV/EAV synchronization.
         */
	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 &= AWG_MAX_ARG;
			break;
		case REPEAT:
		case REPLAY:
			if (arg == 0) {
				/* REPEAT or REPLAY instruction not needed */
				return 0;
			}
			mux = 0;
			data_enable = 0;
			arg &= AWG_MAX_ARG;
			break;
		case JUMP:
			mux = 0;
			data_enable = 0;
			arg |= 0x40; /* for jump instruction 7th bit is 1 */
			arg &= AWG_MAX_ARG;
			break;
		case STOP:
			arg = 0;
			break;
		case SET:
		case RPTSET:
		case RPLSET:
		case HOLD:
			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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Benjamin Gaignard | 288 | 98.63% | 1 | 33.33% | 
| Bich Hemon | 4 | 1.37% | 2 | 66.67% | 
| Total | 292 | 100.00% | 3 | 100.00% | 
static int awg_generate_line_signal(
		struct awg_code_generation_params *fwparams,
		struct awg_timing *timing)
{
	long int val;
	int ret = 0;
	if (timing->trailing_pixels > 0) {
		/* skip trailing pixel */
		val = timing->blanking_level;
		ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);
		val = timing->trailing_pixels - 1 + AWG_DELAY;
		ret |= awg_generate_instr(SKIP, val, 0, 0, fwparams);
	}
	/* set DE signal high */
	val = timing->blanking_level;
	ret |= awg_generate_instr((timing->trailing_pixels > 0) ? SET : RPLSET,
			val, 0, 1, fwparams);
	if (timing->blanking_pixels > 0) {
		/* skip the number of active pixel */
		val = timing->active_pixels - 1;
		ret |= awg_generate_instr(SKIP, val, 0, 1, fwparams);
		/* set DE signal low */
		val = timing->blanking_level;
		ret |= awg_generate_instr(SET, val, 0, 0, fwparams);
	}
	return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Benjamin Gaignard | 132 | 76.30% | 1 | 25.00% | 
| Bich Hemon | 41 | 23.70% | 3 | 75.00% | 
| Total | 173 | 100.00% | 4 | 100.00% | 
int sti_awg_generate_code_data_enable_mode(
		struct awg_code_generation_params *fwparams,
		struct awg_timing *timing)
{
	long int val, tmp_val;
	int ret = 0;
	if (timing->trailing_lines > 0) {
		/* skip trailing lines */
		val = timing->blanking_level;
		ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);
		val = timing->trailing_lines - 1;
		ret |= awg_generate_instr(REPLAY, val, 0, 0, fwparams);
	}
	tmp_val = timing->active_lines - 1;
	while (tmp_val > 0) {
		/* generate DE signal for each line */
		ret |= awg_generate_line_signal(fwparams, timing);
		/* replay the sequence as many active lines defined */
		ret |= awg_generate_instr(REPLAY,
					  min_t(int, AWG_MAX_ARG, tmp_val),
					  0, 0, fwparams);
		tmp_val -= AWG_MAX_ARG;
	}
	if (timing->blanking_lines > 0) {
		/* skip blanking lines */
		val = timing->blanking_level;
		ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);
		val = timing->blanking_lines - 1;
		ret |= awg_generate_instr(REPLAY, val, 0, 0, fwparams);
	}
	return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Benjamin Gaignard | 122 | 63.54% | 1 | 33.33% | 
| Bich Hemon | 70 | 36.46% | 2 | 66.67% | 
| Total | 192 | 100.00% | 3 | 100.00% | 
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp | 
| Benjamin Gaignard | 572 | 82.30% | 1 | 25.00% | 
| Bich Hemon | 123 | 17.70% | 3 | 75.00% | 
| Total | 695 | 100.00% | 4 | 100.00% | 
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.