0001
0002
0003
0004
0005
0006
0007 #include <drm/drm_print.h>
0008
0009 #include "sti_awg_utils.h"
0010
0011 #define AWG_DELAY (-5)
0012
0013 #define AWG_OPCODE_OFFSET 10
0014 #define AWG_MAX_ARG 0x3ff
0015
0016 enum opcode {
0017 SET,
0018 RPTSET,
0019 RPLSET,
0020 SKIP,
0021 STOP,
0022 REPEAT,
0023 REPLAY,
0024 JUMP,
0025 HOLD,
0026 };
0027
0028 static int awg_generate_instr(enum opcode opcode,
0029 long int arg,
0030 long int mux_sel,
0031 long int data_en,
0032 struct awg_code_generation_params *fwparams)
0033 {
0034 u32 instruction = 0;
0035 u32 mux = (mux_sel << 8) & 0x1ff;
0036 u32 data_enable = (data_en << 9) & 0x2ff;
0037 long int arg_tmp = arg;
0038
0039
0040
0041
0042
0043
0044
0045
0046 while (arg_tmp > 0) {
0047 arg = arg_tmp;
0048 if (fwparams->instruction_offset >= AWG_MAX_INST) {
0049 DRM_ERROR("too many number of instructions\n");
0050 return -EINVAL;
0051 }
0052
0053 switch (opcode) {
0054 case SKIP:
0055
0056
0057 arg--;
0058 arg_tmp--;
0059
0060 if (arg < 0) {
0061
0062 return 0;
0063 }
0064
0065 if (arg == 0) {
0066
0067
0068
0069 opcode = SET;
0070 break;
0071 }
0072
0073 mux = 0;
0074 data_enable = 0;
0075 arg &= AWG_MAX_ARG;
0076 break;
0077 case REPEAT:
0078 case REPLAY:
0079 if (arg == 0) {
0080
0081 return 0;
0082 }
0083
0084 mux = 0;
0085 data_enable = 0;
0086 arg &= AWG_MAX_ARG;
0087 break;
0088 case JUMP:
0089 mux = 0;
0090 data_enable = 0;
0091 arg |= 0x40;
0092 arg &= AWG_MAX_ARG;
0093 break;
0094 case STOP:
0095 arg = 0;
0096 break;
0097 case SET:
0098 case RPTSET:
0099 case RPLSET:
0100 case HOLD:
0101 arg &= (0x0ff);
0102 break;
0103 default:
0104 DRM_ERROR("instruction %d does not exist\n", opcode);
0105 return -EINVAL;
0106 }
0107
0108 arg_tmp = arg_tmp - arg;
0109
0110 arg = ((arg + mux) + data_enable);
0111
0112 instruction = ((opcode) << AWG_OPCODE_OFFSET) | arg;
0113 fwparams->ram_code[fwparams->instruction_offset] =
0114 instruction & (0x3fff);
0115 fwparams->instruction_offset++;
0116 }
0117 return 0;
0118 }
0119
0120 static int awg_generate_line_signal(
0121 struct awg_code_generation_params *fwparams,
0122 struct awg_timing *timing)
0123 {
0124 long int val;
0125 int ret = 0;
0126
0127 if (timing->trailing_pixels > 0) {
0128
0129 val = timing->blanking_level;
0130 ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);
0131
0132 val = timing->trailing_pixels - 1 + AWG_DELAY;
0133 ret |= awg_generate_instr(SKIP, val, 0, 0, fwparams);
0134 }
0135
0136
0137 val = timing->blanking_level;
0138 ret |= awg_generate_instr((timing->trailing_pixels > 0) ? SET : RPLSET,
0139 val, 0, 1, fwparams);
0140
0141 if (timing->blanking_pixels > 0) {
0142
0143 val = timing->active_pixels - 1;
0144 ret |= awg_generate_instr(SKIP, val, 0, 1, fwparams);
0145
0146
0147 val = timing->blanking_level;
0148 ret |= awg_generate_instr(SET, val, 0, 0, fwparams);
0149 }
0150
0151 return ret;
0152 }
0153
0154 int sti_awg_generate_code_data_enable_mode(
0155 struct awg_code_generation_params *fwparams,
0156 struct awg_timing *timing)
0157 {
0158 long int val, tmp_val;
0159 int ret = 0;
0160
0161 if (timing->trailing_lines > 0) {
0162
0163 val = timing->blanking_level;
0164 ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);
0165
0166 val = timing->trailing_lines - 1;
0167 ret |= awg_generate_instr(REPLAY, val, 0, 0, fwparams);
0168 }
0169
0170 tmp_val = timing->active_lines - 1;
0171
0172 while (tmp_val > 0) {
0173
0174 ret |= awg_generate_line_signal(fwparams, timing);
0175
0176 ret |= awg_generate_instr(REPLAY,
0177 min_t(int, AWG_MAX_ARG, tmp_val),
0178 0, 0, fwparams);
0179 tmp_val -= AWG_MAX_ARG;
0180 }
0181
0182 if (timing->blanking_lines > 0) {
0183
0184 val = timing->blanking_level;
0185 ret |= awg_generate_instr(RPLSET, val, 0, 0, fwparams);
0186
0187 val = timing->blanking_lines - 1;
0188 ret |= awg_generate_instr(REPLAY, val, 0, 0, fwparams);
0189 }
0190
0191 return ret;
0192 }