2 * Copyright (C) STMicroelectronics SA 2014
3 * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
4 * License terms: GNU General Public License (GPL), version 2
7 #include "sti_awg_utils.h"
11 #define AWG_OPCODE_OFFSET 10
12 #define AWG_MAX_ARG 0x3ff
26 static int awg_generate_instr(enum opcode opcode
,
30 struct awg_code_generation_params
*fwparams
)
33 u32 mux
= (mux_sel
<< 8) & 0x1ff;
34 u32 data_enable
= (data_en
<< 9) & 0x2ff;
35 long int arg_tmp
= arg
;
37 /* skip, repeat and replay arg should not exceed 1023.
38 * If user wants to exceed this value, the instruction should be
39 * duplicate and arg should be adjust for each duplicated instruction.
41 * mux_sel is used in case of SAV/EAV synchronization.
46 if (fwparams
->instruction_offset
>= AWG_MAX_INST
) {
47 DRM_ERROR("too many number of instructions\n");
53 /* leave 'arg' + 1 pixel elapsing without changing
55 arg
--; /* pixel adjustment */
59 /* SKIP instruction not needed */
64 /* SKIP 0 not permitted but we want to skip 1
65 * pixel. So we transform SKIP into SET
78 /* REPEAT or REPLAY instruction not needed */
89 arg
|= 0x40; /* for jump instruction 7th bit is 1 */
102 DRM_ERROR("instruction %d does not exist\n", opcode
);
106 arg_tmp
= arg_tmp
- arg
;
108 arg
= ((arg
+ mux
) + data_enable
);
110 instruction
= ((opcode
) << AWG_OPCODE_OFFSET
) | arg
;
111 fwparams
->ram_code
[fwparams
->instruction_offset
] =
112 instruction
& (0x3fff);
113 fwparams
->instruction_offset
++;
118 static int awg_generate_line_signal(
119 struct awg_code_generation_params
*fwparams
,
120 struct awg_timing
*timing
)
125 if (timing
->trailing_pixels
> 0) {
126 /* skip trailing pixel */
127 val
= timing
->blanking_level
;
128 ret
|= awg_generate_instr(RPLSET
, val
, 0, 0, fwparams
);
130 val
= timing
->trailing_pixels
- 1 + AWG_DELAY
;
131 ret
|= awg_generate_instr(SKIP
, val
, 0, 0, fwparams
);
134 /* set DE signal high */
135 val
= timing
->blanking_level
;
136 ret
|= awg_generate_instr((timing
->trailing_pixels
> 0) ? SET
: RPLSET
,
137 val
, 0, 1, fwparams
);
139 if (timing
->blanking_pixels
> 0) {
140 /* skip the number of active pixel */
141 val
= timing
->active_pixels
- 1;
142 ret
|= awg_generate_instr(SKIP
, val
, 0, 1, fwparams
);
144 /* set DE signal low */
145 val
= timing
->blanking_level
;
146 ret
|= awg_generate_instr(SET
, val
, 0, 0, fwparams
);
152 int sti_awg_generate_code_data_enable_mode(
153 struct awg_code_generation_params
*fwparams
,
154 struct awg_timing
*timing
)
156 long int val
, tmp_val
;
159 if (timing
->trailing_lines
> 0) {
160 /* skip trailing lines */
161 val
= timing
->blanking_level
;
162 ret
|= awg_generate_instr(RPLSET
, val
, 0, 0, fwparams
);
164 val
= timing
->trailing_lines
- 1;
165 ret
|= awg_generate_instr(REPLAY
, val
, 0, 0, fwparams
);
168 tmp_val
= timing
->active_lines
- 1;
170 while (tmp_val
> 0) {
171 /* generate DE signal for each line */
172 ret
|= awg_generate_line_signal(fwparams
, timing
);
173 /* replay the sequence as many active lines defined */
174 ret
|= awg_generate_instr(REPLAY
,
175 min_t(int, AWG_MAX_ARG
, tmp_val
),
177 tmp_val
-= AWG_MAX_ARG
;
180 if (timing
->blanking_lines
> 0) {
181 /* skip blanking lines */
182 val
= timing
->blanking_level
;
183 ret
|= awg_generate_instr(RPLSET
, val
, 0, 0, fwparams
);
185 val
= timing
->blanking_lines
- 1;
186 ret
|= awg_generate_instr(REPLAY
, val
, 0, 0, fwparams
);