0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "reg_helper.h"
0027 #include "dcn201_optc.h"
0028 #include "dcn10/dcn10_optc.h"
0029 #include "dc.h"
0030
0031 #define REG(reg)\
0032 optc1->tg_regs->reg
0033
0034 #define CTX \
0035 optc1->base.ctx
0036
0037 #undef FN
0038 #define FN(reg_name, field_name) \
0039 optc1->tg_shift->field_name, optc1->tg_mask->field_name
0040
0041
0042 bool optc201_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
0043 {
0044 return optc1_is_two_pixels_per_containter(timing);
0045 }
0046
0047 static void optc201_triplebuffer_lock(struct timing_generator *optc)
0048 {
0049 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0050
0051 REG_SET(OTG_GLOBAL_CONTROL0, 0,
0052 OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
0053 REG_SET(OTG_VUPDATE_KEEPOUT, 0,
0054 OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1);
0055 REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
0056 OTG_MASTER_UPDATE_LOCK, 1);
0057
0058 if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS)
0059 REG_WAIT(OTG_MASTER_UPDATE_LOCK,
0060 UPDATE_LOCK_STATUS, 1,
0061 1, 10);
0062 }
0063
0064 static void optc201_triplebuffer_unlock(struct timing_generator *optc)
0065 {
0066 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0067
0068 REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
0069 OTG_MASTER_UPDATE_LOCK, 0);
0070 REG_SET(OTG_VUPDATE_KEEPOUT, 0,
0071 OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 0);
0072
0073 }
0074
0075 static bool optc201_validate_timing(
0076 struct timing_generator *optc,
0077 const struct dc_crtc_timing *timing)
0078 {
0079 uint32_t v_blank;
0080 uint32_t h_blank;
0081 uint32_t min_v_blank;
0082 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0083
0084 ASSERT(timing != NULL);
0085
0086 v_blank = (timing->v_total - timing->v_addressable -
0087 timing->v_border_top - timing->v_border_bottom);
0088
0089 h_blank = (timing->h_total - timing->h_addressable -
0090 timing->h_border_right -
0091 timing->h_border_left);
0092
0093 if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE &&
0094 timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
0095 timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
0096 timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
0097 timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
0098 timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
0099 return false;
0100
0101
0102
0103
0104
0105
0106 if (timing->h_total > optc1->max_h_total ||
0107 timing->v_total > optc1->max_v_total)
0108 return false;
0109
0110 if (h_blank < optc1->min_h_blank)
0111 return false;
0112
0113 if (timing->h_sync_width < optc1->min_h_sync_width ||
0114 timing->v_sync_width < optc1->min_v_sync_width)
0115 return false;
0116
0117 min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank;
0118
0119 if (v_blank < min_v_blank)
0120 return false;
0121
0122 return true;
0123
0124 }
0125
0126 static void optc201_get_optc_source(struct timing_generator *optc,
0127 uint32_t *num_of_src_opp,
0128 uint32_t *src_opp_id_0,
0129 uint32_t *src_opp_id_1)
0130 {
0131 struct optc *optc1 = DCN10TG_FROM_TG(optc);
0132
0133 REG_GET(OPTC_DATA_SOURCE_SELECT,
0134 OPTC_SEG0_SRC_SEL, src_opp_id_0);
0135
0136 *num_of_src_opp = 1;
0137 }
0138
0139 static struct timing_generator_funcs dcn201_tg_funcs = {
0140 .validate_timing = optc201_validate_timing,
0141 .program_timing = optc1_program_timing,
0142 .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
0143 .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
0144 .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
0145 .program_global_sync = optc1_program_global_sync,
0146 .enable_crtc = optc2_enable_crtc,
0147 .disable_crtc = optc1_disable_crtc,
0148
0149 .is_counter_moving = optc1_is_counter_moving,
0150 .get_position = optc1_get_position,
0151 .get_frame_count = optc1_get_vblank_counter,
0152 .get_scanoutpos = optc1_get_crtc_scanoutpos,
0153 .get_otg_active_size = optc1_get_otg_active_size,
0154 .set_early_control = optc1_set_early_control,
0155
0156 .wait_for_state = optc1_wait_for_state,
0157 .set_blank = optc1_set_blank,
0158 .is_blanked = optc1_is_blanked,
0159 .set_blank_color = optc1_program_blank_color,
0160 .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
0161 .enable_reset_trigger = optc1_enable_reset_trigger,
0162 .enable_crtc_reset = optc1_enable_crtc_reset,
0163 .disable_reset_trigger = optc1_disable_reset_trigger,
0164 .triplebuffer_lock = optc201_triplebuffer_lock,
0165 .triplebuffer_unlock = optc201_triplebuffer_unlock,
0166 .lock = optc1_lock,
0167 .unlock = optc1_unlock,
0168 .enable_optc_clock = optc1_enable_optc_clock,
0169 .set_drr = optc1_set_drr,
0170 .get_last_used_drr_vtotal = NULL,
0171 .set_vtotal_min_max = optc1_set_vtotal_min_max,
0172 .set_static_screen_control = optc1_set_static_screen_control,
0173 .program_stereo = optc1_program_stereo,
0174 .is_stereo_left_eye = optc1_is_stereo_left_eye,
0175 .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer,
0176 .tg_init = optc1_tg_init,
0177 .is_tg_enabled = optc1_is_tg_enabled,
0178 .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
0179 .clear_optc_underflow = optc1_clear_optc_underflow,
0180 .get_crc = optc1_get_crc,
0181 .configure_crc = optc2_configure_crc,
0182 .set_dsc_config = optc2_set_dsc_config,
0183 .set_dwb_source = NULL,
0184 .get_optc_source = optc201_get_optc_source,
0185 .set_vtg_params = optc1_set_vtg_params,
0186 .program_manual_trigger = optc2_program_manual_trigger,
0187 .setup_manual_trigger = optc2_setup_manual_trigger,
0188 .get_hw_timing = optc1_get_hw_timing,
0189 };
0190
0191 void dcn201_timing_generator_init(struct optc *optc1)
0192 {
0193 optc1->base.funcs = &dcn201_tg_funcs;
0194
0195 optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
0196 optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
0197
0198 optc1->min_h_blank = 32;
0199 optc1->min_v_blank = 3;
0200 optc1->min_v_blank_interlace = 5;
0201 optc1->min_h_sync_width = 8;
0202 optc1->min_v_sync_width = 1;
0203 }