Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dm_services.h"
0027 
0028 /* include DCE11 register header files */
0029 #include "dce/dce_11_0_d.h"
0030 #include "dce/dce_11_0_sh_mask.h"
0031 
0032 #include "dc_types.h"
0033 #include "dc_bios_types.h"
0034 #include "dc.h"
0035 
0036 #include "include/grph_object_id.h"
0037 #include "include/logger_interface.h"
0038 #include "dce110_timing_generator.h"
0039 
0040 #include "timing_generator.h"
0041 
0042 
0043 #define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10
0044 
0045 #define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1)
0046 #define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1)
0047 
0048 #define CRTC_REG(reg) (reg + tg110->offsets.crtc)
0049 #define DCP_REG(reg) (reg + tg110->offsets.dcp)
0050 
0051 /* Flowing register offsets are same in files of
0052  * dce/dce_11_0_d.h
0053  * dce/vi_polaris10_p/vi_polaris10_d.h
0054  *
0055  * So we can create dce110 timing generator to use it.
0056  */
0057 
0058 
0059 /*
0060 * apply_front_porch_workaround
0061 *
0062 * This is a workaround for a bug that has existed since R5xx and has not been
0063 * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
0064 */
0065 static void dce110_timing_generator_apply_front_porch_workaround(
0066     struct timing_generator *tg,
0067     struct dc_crtc_timing *timing)
0068 {
0069     if (timing->flags.INTERLACE == 1) {
0070         if (timing->v_front_porch < 2)
0071             timing->v_front_porch = 2;
0072     } else {
0073         if (timing->v_front_porch < 1)
0074             timing->v_front_porch = 1;
0075     }
0076 }
0077 
0078 /*
0079  *****************************************************************************
0080  *  Function: is_in_vertical_blank
0081  *
0082  *  @brief
0083  *     check the current status of CRTC to check if we are in Vertical Blank
0084  *     regioneased" state
0085  *
0086  *  @return
0087  *     true if currently in blank region, false otherwise
0088  *
0089  *****************************************************************************
0090  */
0091 static bool dce110_timing_generator_is_in_vertical_blank(
0092         struct timing_generator *tg)
0093 {
0094     uint32_t addr = 0;
0095     uint32_t value = 0;
0096     uint32_t field = 0;
0097     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0098 
0099     addr = CRTC_REG(mmCRTC_STATUS);
0100     value = dm_read_reg(tg->ctx, addr);
0101     field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK);
0102     return field == 1;
0103 }
0104 
0105 void dce110_timing_generator_set_early_control(
0106         struct timing_generator *tg,
0107         uint32_t early_cntl)
0108 {
0109     uint32_t regval;
0110     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0111     uint32_t address = CRTC_REG(mmCRTC_CONTROL);
0112 
0113     regval = dm_read_reg(tg->ctx, address);
0114     set_reg_field_value(regval, early_cntl,
0115             CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
0116     dm_write_reg(tg->ctx, address, regval);
0117 }
0118 
0119 /*
0120  * Enable CRTC
0121  * Enable CRTC - call ASIC Control Object to enable Timing generator.
0122  */
0123 bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
0124 {
0125     enum bp_result result;
0126 
0127     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0128     uint32_t value = 0;
0129 
0130     /*
0131      * 3 is used to make sure V_UPDATE occurs at the beginning of the first
0132      * line of vertical front porch
0133      */
0134     set_reg_field_value(
0135         value,
0136         0,
0137         CRTC_MASTER_UPDATE_MODE,
0138         MASTER_UPDATE_MODE);
0139 
0140     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
0141 
0142     /* TODO: may want this on to catch underflow */
0143     value = 0;
0144     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value);
0145 
0146     result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
0147 
0148     return result == BP_RESULT_OK;
0149 }
0150 
0151 void dce110_timing_generator_program_blank_color(
0152         struct timing_generator *tg,
0153         const struct tg_color *black_color)
0154 {
0155     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0156     uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
0157     uint32_t value = dm_read_reg(tg->ctx, addr);
0158 
0159     set_reg_field_value(
0160         value,
0161         black_color->color_b_cb,
0162         CRTC_BLACK_COLOR,
0163         CRTC_BLACK_COLOR_B_CB);
0164     set_reg_field_value(
0165         value,
0166         black_color->color_g_y,
0167         CRTC_BLACK_COLOR,
0168         CRTC_BLACK_COLOR_G_Y);
0169     set_reg_field_value(
0170         value,
0171         black_color->color_r_cr,
0172         CRTC_BLACK_COLOR,
0173         CRTC_BLACK_COLOR_R_CR);
0174 
0175     dm_write_reg(tg->ctx, addr, value);
0176 }
0177 
0178 /*
0179  *****************************************************************************
0180  *  Function: disable_stereo
0181  *
0182  *  @brief
0183  *     Disables active stereo on controller
0184  *     Frame Packing need to be disabled in vBlank or when CRTC not running
0185  *****************************************************************************
0186  */
0187 #if 0
0188 @TODOSTEREO
0189 static void disable_stereo(struct timing_generator *tg)
0190 {
0191     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0192     uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
0193     uint32_t value = 0;
0194     uint32_t test = 0;
0195     uint32_t field = 0;
0196     uint32_t struc_en = 0;
0197     uint32_t struc_stereo_sel_ovr = 0;
0198 
0199     value = dm_read_reg(tg->ctx, addr);
0200     struc_en = get_reg_field_value(
0201             value,
0202             CRTC_3D_STRUCTURE_CONTROL,
0203             CRTC_3D_STRUCTURE_EN);
0204 
0205     struc_stereo_sel_ovr = get_reg_field_value(
0206             value,
0207             CRTC_3D_STRUCTURE_CONTROL,
0208             CRTC_3D_STRUCTURE_STEREO_SEL_OVR);
0209 
0210     /*
0211      * When disabling Frame Packing in 2 step mode, we need to program both
0212      * registers at the same frame
0213      * Programming it in the beginning of VActive makes sure we are ok
0214      */
0215 
0216     if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
0217         tg->funcs->wait_for_vblank(tg);
0218         tg->funcs->wait_for_vactive(tg);
0219     }
0220 
0221     value = 0;
0222     dm_write_reg(tg->ctx, addr, value);
0223 
0224     addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
0225     dm_write_reg(tg->ctx, addr, value);
0226 }
0227 #endif
0228 
0229 /*
0230  * disable_crtc - call ASIC Control Object to disable Timing generator.
0231  */
0232 bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
0233 {
0234     enum bp_result result;
0235 
0236     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0237 
0238     result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false);
0239 
0240     /* Need to make sure stereo is disabled according to the DCE5.0 spec */
0241 
0242     /*
0243      * @TODOSTEREO call this when adding stereo support
0244      * tg->funcs->disable_stereo(tg);
0245      */
0246 
0247     return result == BP_RESULT_OK;
0248 }
0249 
0250 /*
0251  * program_horz_count_by_2
0252  * Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise
0253  */
0254 static void program_horz_count_by_2(
0255     struct timing_generator *tg,
0256     const struct dc_crtc_timing *timing)
0257 {
0258     uint32_t regval;
0259     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0260 
0261     regval = dm_read_reg(tg->ctx,
0262             CRTC_REG(mmCRTC_COUNT_CONTROL));
0263 
0264     set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL,
0265             CRTC_HORZ_COUNT_BY2_EN);
0266 
0267     if (timing->flags.HORZ_COUNT_BY_TWO)
0268         set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL,
0269                     CRTC_HORZ_COUNT_BY2_EN);
0270 
0271     dm_write_reg(tg->ctx,
0272             CRTC_REG(mmCRTC_COUNT_CONTROL), regval);
0273 }
0274 
0275 /*
0276  * program_timing_generator
0277  * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition.
0278  * Call ASIC Control Object to program Timings.
0279  */
0280 bool dce110_timing_generator_program_timing_generator(
0281     struct timing_generator *tg,
0282     const struct dc_crtc_timing *dc_crtc_timing)
0283 {
0284     enum bp_result result;
0285     struct bp_hw_crtc_timing_parameters bp_params;
0286     struct dc_crtc_timing patched_crtc_timing;
0287     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0288 
0289     uint32_t vsync_offset = dc_crtc_timing->v_border_bottom +
0290             dc_crtc_timing->v_front_porch;
0291     uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset;
0292 
0293     uint32_t hsync_offset = dc_crtc_timing->h_border_right +
0294             dc_crtc_timing->h_front_porch;
0295     uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset;
0296 
0297     memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters));
0298 
0299     /* Due to an asic bug we need to apply the Front Porch workaround prior
0300      * to programming the timing.
0301      */
0302 
0303     patched_crtc_timing = *dc_crtc_timing;
0304 
0305     dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing);
0306 
0307     bp_params.controller_id = tg110->controller_id;
0308 
0309     bp_params.h_total = patched_crtc_timing.h_total;
0310     bp_params.h_addressable =
0311         patched_crtc_timing.h_addressable;
0312     bp_params.v_total = patched_crtc_timing.v_total;
0313     bp_params.v_addressable = patched_crtc_timing.v_addressable;
0314 
0315     bp_params.h_sync_start = h_sync_start;
0316     bp_params.h_sync_width = patched_crtc_timing.h_sync_width;
0317     bp_params.v_sync_start = v_sync_start;
0318     bp_params.v_sync_width = patched_crtc_timing.v_sync_width;
0319 
0320     /* Set overscan */
0321     bp_params.h_overscan_left =
0322         patched_crtc_timing.h_border_left;
0323     bp_params.h_overscan_right =
0324         patched_crtc_timing.h_border_right;
0325     bp_params.v_overscan_top = patched_crtc_timing.v_border_top;
0326     bp_params.v_overscan_bottom =
0327         patched_crtc_timing.v_border_bottom;
0328 
0329     /* Set flags */
0330     if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1)
0331         bp_params.flags.HSYNC_POSITIVE_POLARITY = 1;
0332 
0333     if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1)
0334         bp_params.flags.VSYNC_POSITIVE_POLARITY = 1;
0335 
0336     if (patched_crtc_timing.flags.INTERLACE == 1)
0337         bp_params.flags.INTERLACE = 1;
0338 
0339     if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1)
0340         bp_params.flags.HORZ_COUNT_BY_TWO = 1;
0341 
0342     result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params);
0343 
0344     program_horz_count_by_2(tg, &patched_crtc_timing);
0345 
0346     tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing);
0347 
0348     /* Enable stereo - only when we need to pack 3D frame. Other types
0349      * of stereo handled in explicit call */
0350 
0351     return result == BP_RESULT_OK;
0352 }
0353 
0354 /*
0355  *****************************************************************************
0356  *  Function: set_drr
0357  *
0358  *  @brief
0359  *     Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
0360  *
0361  *  @param [in] pHwCrtcTiming: point to H
0362  *  wCrtcTiming struct
0363  *****************************************************************************
0364  */
0365 void dce110_timing_generator_set_drr(
0366     struct timing_generator *tg,
0367     const struct drr_params *params)
0368 {
0369     /* register values */
0370     uint32_t v_total_min = 0;
0371     uint32_t v_total_max = 0;
0372     uint32_t v_total_cntl = 0;
0373     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0374 
0375     uint32_t addr = 0;
0376 
0377     addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
0378     v_total_min = dm_read_reg(tg->ctx, addr);
0379 
0380     addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
0381     v_total_max = dm_read_reg(tg->ctx, addr);
0382 
0383     addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
0384     v_total_cntl = dm_read_reg(tg->ctx, addr);
0385 
0386     if (params != NULL &&
0387         params->vertical_total_max > 0 &&
0388         params->vertical_total_min > 0) {
0389 
0390         set_reg_field_value(v_total_max,
0391                 params->vertical_total_max - 1,
0392                 CRTC_V_TOTAL_MAX,
0393                 CRTC_V_TOTAL_MAX);
0394 
0395         set_reg_field_value(v_total_min,
0396                 params->vertical_total_min - 1,
0397                 CRTC_V_TOTAL_MIN,
0398                 CRTC_V_TOTAL_MIN);
0399 
0400         set_reg_field_value(v_total_cntl,
0401                 1,
0402                 CRTC_V_TOTAL_CONTROL,
0403                 CRTC_V_TOTAL_MIN_SEL);
0404 
0405         set_reg_field_value(v_total_cntl,
0406                 1,
0407                 CRTC_V_TOTAL_CONTROL,
0408                 CRTC_V_TOTAL_MAX_SEL);
0409 
0410         set_reg_field_value(v_total_cntl,
0411                 0,
0412                 CRTC_V_TOTAL_CONTROL,
0413                 CRTC_FORCE_LOCK_ON_EVENT);
0414         set_reg_field_value(v_total_cntl,
0415                 0,
0416                 CRTC_V_TOTAL_CONTROL,
0417                 CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
0418 
0419         set_reg_field_value(v_total_cntl,
0420                 0,
0421                 CRTC_V_TOTAL_CONTROL,
0422                 CRTC_SET_V_TOTAL_MIN_MASK_EN);
0423 
0424         set_reg_field_value(v_total_cntl,
0425                 0,
0426                 CRTC_V_TOTAL_CONTROL,
0427                 CRTC_SET_V_TOTAL_MIN_MASK);
0428     } else {
0429         set_reg_field_value(v_total_cntl,
0430             0,
0431             CRTC_V_TOTAL_CONTROL,
0432             CRTC_SET_V_TOTAL_MIN_MASK);
0433         set_reg_field_value(v_total_cntl,
0434                 0,
0435                 CRTC_V_TOTAL_CONTROL,
0436                 CRTC_V_TOTAL_MIN_SEL);
0437         set_reg_field_value(v_total_cntl,
0438                 0,
0439                 CRTC_V_TOTAL_CONTROL,
0440                 CRTC_V_TOTAL_MAX_SEL);
0441         set_reg_field_value(v_total_min,
0442                 0,
0443                 CRTC_V_TOTAL_MIN,
0444                 CRTC_V_TOTAL_MIN);
0445         set_reg_field_value(v_total_max,
0446                 0,
0447                 CRTC_V_TOTAL_MAX,
0448                 CRTC_V_TOTAL_MAX);
0449         set_reg_field_value(v_total_cntl,
0450                 0,
0451                 CRTC_V_TOTAL_CONTROL,
0452                 CRTC_FORCE_LOCK_ON_EVENT);
0453         set_reg_field_value(v_total_cntl,
0454                 0,
0455                 CRTC_V_TOTAL_CONTROL,
0456                 CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
0457     }
0458 
0459     addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
0460     dm_write_reg(tg->ctx, addr, v_total_min);
0461 
0462     addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
0463     dm_write_reg(tg->ctx, addr, v_total_max);
0464 
0465     addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
0466     dm_write_reg(tg->ctx, addr, v_total_cntl);
0467 }
0468 
0469 void dce110_timing_generator_set_static_screen_control(
0470     struct timing_generator *tg,
0471     uint32_t event_triggers,
0472     uint32_t num_frames)
0473 {
0474     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0475     uint32_t static_screen_cntl = 0;
0476     uint32_t addr = 0;
0477 
0478     // By register spec, it only takes 8 bit value
0479     if (num_frames > 0xFF)
0480         num_frames = 0xFF;
0481 
0482     addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
0483     static_screen_cntl = dm_read_reg(tg->ctx, addr);
0484 
0485     set_reg_field_value(static_screen_cntl,
0486                 event_triggers,
0487                 CRTC_STATIC_SCREEN_CONTROL,
0488                 CRTC_STATIC_SCREEN_EVENT_MASK);
0489 
0490     set_reg_field_value(static_screen_cntl,
0491                 num_frames,
0492                 CRTC_STATIC_SCREEN_CONTROL,
0493                 CRTC_STATIC_SCREEN_FRAME_COUNT);
0494 
0495     dm_write_reg(tg->ctx, addr, static_screen_cntl);
0496 }
0497 
0498 /*
0499  * get_vblank_counter
0500  *
0501  * @brief
0502  * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
0503  * holds the counter of frames.
0504  *
0505  * @param
0506  * struct timing_generator *tg - [in] timing generator which controls the
0507  * desired CRTC
0508  *
0509  * @return
0510  * Counter of frames, which should equal to number of vblanks.
0511  */
0512 uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
0513 {
0514     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0515     uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT);
0516     uint32_t value = dm_read_reg(tg->ctx, addr);
0517     uint32_t field = get_reg_field_value(
0518             value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
0519 
0520     return field;
0521 }
0522 
0523 /*
0524  *****************************************************************************
0525  *  Function: dce110_timing_generator_get_position
0526  *
0527  *  @brief
0528  *     Returns CRTC vertical/horizontal counters
0529  *
0530  *  @param [out] position
0531  *****************************************************************************
0532  */
0533 void dce110_timing_generator_get_position(struct timing_generator *tg,
0534     struct crtc_position *position)
0535 {
0536     uint32_t value;
0537     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0538 
0539     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
0540 
0541     position->horizontal_count = get_reg_field_value(
0542             value,
0543             CRTC_STATUS_POSITION,
0544             CRTC_HORZ_COUNT);
0545 
0546     position->vertical_count = get_reg_field_value(
0547             value,
0548             CRTC_STATUS_POSITION,
0549             CRTC_VERT_COUNT);
0550 
0551     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION));
0552 
0553     position->nominal_vcount = get_reg_field_value(
0554             value,
0555             CRTC_NOM_VERT_POSITION,
0556             CRTC_VERT_COUNT_NOM);
0557 }
0558 
0559 /*
0560  *****************************************************************************
0561  *  Function: get_crtc_scanoutpos
0562  *
0563  *  @brief
0564  *     Returns CRTC vertical/horizontal counters
0565  *
0566  *  @param [out] vpos, hpos
0567  *****************************************************************************
0568  */
0569 void dce110_timing_generator_get_crtc_scanoutpos(
0570     struct timing_generator *tg,
0571     uint32_t *v_blank_start,
0572     uint32_t *v_blank_end,
0573     uint32_t *h_position,
0574     uint32_t *v_position)
0575 {
0576     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0577     struct crtc_position position;
0578 
0579     uint32_t value  = dm_read_reg(tg->ctx,
0580             CRTC_REG(mmCRTC_V_BLANK_START_END));
0581 
0582     *v_blank_start = get_reg_field_value(value,
0583                          CRTC_V_BLANK_START_END,
0584                          CRTC_V_BLANK_START);
0585     *v_blank_end = get_reg_field_value(value,
0586                        CRTC_V_BLANK_START_END,
0587                        CRTC_V_BLANK_END);
0588 
0589     dce110_timing_generator_get_position(
0590             tg, &position);
0591 
0592     *h_position = position.horizontal_count;
0593     *v_position = position.vertical_count;
0594 }
0595 
0596 /* TODO: is it safe to assume that mask/shift of Primary and Underlay
0597  * are the same?
0598  * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always
0599  * guaranteed? */
0600 void dce110_timing_generator_program_blanking(
0601     struct timing_generator *tg,
0602     const struct dc_crtc_timing *timing)
0603 {
0604     uint32_t vsync_offset = timing->v_border_bottom +
0605             timing->v_front_porch;
0606     uint32_t v_sync_start =timing->v_addressable + vsync_offset;
0607 
0608     uint32_t hsync_offset = timing->h_border_right +
0609             timing->h_front_porch;
0610     uint32_t h_sync_start = timing->h_addressable + hsync_offset;
0611     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0612 
0613     struct dc_context *ctx = tg->ctx;
0614     uint32_t value = 0;
0615     uint32_t addr = 0;
0616     uint32_t tmp = 0;
0617 
0618     addr = CRTC_REG(mmCRTC_H_TOTAL);
0619     value = dm_read_reg(ctx, addr);
0620     set_reg_field_value(
0621         value,
0622         timing->h_total - 1,
0623         CRTC_H_TOTAL,
0624         CRTC_H_TOTAL);
0625     dm_write_reg(ctx, addr, value);
0626 
0627     addr = CRTC_REG(mmCRTC_V_TOTAL);
0628     value = dm_read_reg(ctx, addr);
0629     set_reg_field_value(
0630         value,
0631         timing->v_total - 1,
0632         CRTC_V_TOTAL,
0633         CRTC_V_TOTAL);
0634     dm_write_reg(ctx, addr, value);
0635 
0636     /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
0637      * V_TOTAL_MIN are equal to V_TOTAL.
0638      */
0639     addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
0640     value = dm_read_reg(ctx, addr);
0641     set_reg_field_value(
0642         value,
0643         timing->v_total - 1,
0644         CRTC_V_TOTAL_MAX,
0645         CRTC_V_TOTAL_MAX);
0646     dm_write_reg(ctx, addr, value);
0647 
0648     addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
0649     value = dm_read_reg(ctx, addr);
0650     set_reg_field_value(
0651         value,
0652         timing->v_total - 1,
0653         CRTC_V_TOTAL_MIN,
0654         CRTC_V_TOTAL_MIN);
0655     dm_write_reg(ctx, addr, value);
0656 
0657     addr = CRTC_REG(mmCRTC_H_BLANK_START_END);
0658     value = dm_read_reg(ctx, addr);
0659 
0660     tmp = timing->h_total -
0661         (h_sync_start + timing->h_border_left);
0662 
0663     set_reg_field_value(
0664         value,
0665         tmp,
0666         CRTC_H_BLANK_START_END,
0667         CRTC_H_BLANK_END);
0668 
0669     tmp = tmp + timing->h_addressable +
0670         timing->h_border_left + timing->h_border_right;
0671 
0672     set_reg_field_value(
0673         value,
0674         tmp,
0675         CRTC_H_BLANK_START_END,
0676         CRTC_H_BLANK_START);
0677 
0678     dm_write_reg(ctx, addr, value);
0679 
0680     addr = CRTC_REG(mmCRTC_V_BLANK_START_END);
0681     value = dm_read_reg(ctx, addr);
0682 
0683     tmp = timing->v_total - (v_sync_start + timing->v_border_top);
0684 
0685     set_reg_field_value(
0686         value,
0687         tmp,
0688         CRTC_V_BLANK_START_END,
0689         CRTC_V_BLANK_END);
0690 
0691     tmp = tmp + timing->v_addressable + timing->v_border_top +
0692         timing->v_border_bottom;
0693 
0694     set_reg_field_value(
0695         value,
0696         tmp,
0697         CRTC_V_BLANK_START_END,
0698         CRTC_V_BLANK_START);
0699 
0700     dm_write_reg(ctx, addr, value);
0701 }
0702 
0703 void dce110_timing_generator_set_test_pattern(
0704     struct timing_generator *tg,
0705     /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
0706      * because this is not DP-specific (which is probably somewhere in DP
0707      * encoder) */
0708     enum controller_dp_test_pattern test_pattern,
0709     enum dc_color_depth color_depth)
0710 {
0711     struct dc_context *ctx = tg->ctx;
0712     uint32_t value;
0713     uint32_t addr;
0714     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0715     enum test_pattern_color_format bit_depth;
0716     enum test_pattern_dyn_range dyn_range;
0717     enum test_pattern_mode mode;
0718     /* color ramp generator mixes 16-bits color */
0719     uint32_t src_bpc = 16;
0720     /* requested bpc */
0721     uint32_t dst_bpc;
0722     uint32_t index;
0723     /* RGB values of the color bars.
0724      * Produce two RGB colors: RGB0 - white (all Fs)
0725      * and RGB1 - black (all 0s)
0726      * (three RGB components for two colors)
0727      */
0728     uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
0729                         0x0000, 0x0000};
0730     /* dest color (converted to the specified color format) */
0731     uint16_t dst_color[6];
0732     uint32_t inc_base;
0733 
0734     /* translate to bit depth */
0735     switch (color_depth) {
0736     case COLOR_DEPTH_666:
0737         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
0738     break;
0739     case COLOR_DEPTH_888:
0740         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0741     break;
0742     case COLOR_DEPTH_101010:
0743         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
0744     break;
0745     case COLOR_DEPTH_121212:
0746         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
0747     break;
0748     default:
0749         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0750     break;
0751     }
0752 
0753     switch (test_pattern) {
0754     case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
0755     case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
0756     {
0757         dyn_range = (test_pattern ==
0758                 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
0759                 TEST_PATTERN_DYN_RANGE_CEA :
0760                 TEST_PATTERN_DYN_RANGE_VESA);
0761         mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
0762         value = 0;
0763         addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
0764 
0765         set_reg_field_value(
0766             value,
0767             6,
0768             CRTC_TEST_PATTERN_PARAMETERS,
0769             CRTC_TEST_PATTERN_VRES);
0770         set_reg_field_value(
0771             value,
0772             6,
0773             CRTC_TEST_PATTERN_PARAMETERS,
0774             CRTC_TEST_PATTERN_HRES);
0775 
0776         dm_write_reg(ctx, addr, value);
0777 
0778         addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
0779         value = 0;
0780 
0781         set_reg_field_value(
0782             value,
0783             1,
0784             CRTC_TEST_PATTERN_CONTROL,
0785             CRTC_TEST_PATTERN_EN);
0786 
0787         set_reg_field_value(
0788             value,
0789             mode,
0790             CRTC_TEST_PATTERN_CONTROL,
0791             CRTC_TEST_PATTERN_MODE);
0792 
0793         set_reg_field_value(
0794             value,
0795             dyn_range,
0796             CRTC_TEST_PATTERN_CONTROL,
0797             CRTC_TEST_PATTERN_DYNAMIC_RANGE);
0798         set_reg_field_value(
0799             value,
0800             bit_depth,
0801             CRTC_TEST_PATTERN_CONTROL,
0802             CRTC_TEST_PATTERN_COLOR_FORMAT);
0803         dm_write_reg(ctx, addr, value);
0804     }
0805     break;
0806 
0807     case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
0808     case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
0809     {
0810         mode = (test_pattern ==
0811             CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
0812             TEST_PATTERN_MODE_VERTICALBARS :
0813             TEST_PATTERN_MODE_HORIZONTALBARS);
0814 
0815         switch (bit_depth) {
0816         case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0817             dst_bpc = 6;
0818         break;
0819         case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0820             dst_bpc = 8;
0821         break;
0822         case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0823             dst_bpc = 10;
0824         break;
0825         default:
0826             dst_bpc = 8;
0827         break;
0828         }
0829 
0830         /* adjust color to the required colorFormat */
0831         for (index = 0; index < 6; index++) {
0832             /* dst = 2^dstBpc * src / 2^srcBpc = src >>
0833              * (srcBpc - dstBpc);
0834              */
0835             dst_color[index] =
0836                 src_color[index] >> (src_bpc - dst_bpc);
0837         /* CRTC_TEST_PATTERN_DATA has 16 bits,
0838          * lowest 6 are hardwired to ZERO
0839          * color bits should be left aligned aligned to MSB
0840          * XXXXXXXXXX000000 for 10 bit,
0841          * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
0842          */
0843             dst_color[index] <<= (16 - dst_bpc);
0844         }
0845 
0846         value = 0;
0847         addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
0848         dm_write_reg(ctx, addr, value);
0849 
0850         /* We have to write the mask before data, similar to pipeline.
0851          * For example, for 8 bpc, if we want RGB0 to be magenta,
0852          * and RGB1 to be cyan,
0853          * we need to make 7 writes:
0854          * MASK   DATA
0855          * 000001 00000000 00000000                     set mask to R0
0856          * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
0857          * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
0858          * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
0859          * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
0860          * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
0861          * 100000 11111111 00000000     B1 255, 0xFF00
0862          *
0863          * we will make a loop of 6 in which we prepare the mask,
0864          * then write, then prepare the color for next write.
0865          * first iteration will write mask only,
0866          * but each next iteration color prepared in
0867          * previous iteration will be written within new mask,
0868          * the last component will written separately,
0869          * mask is not changing between 6th and 7th write
0870          * and color will be prepared by last iteration
0871          */
0872 
0873         /* write color, color values mask in CRTC_TEST_PATTERN_MASK
0874          * is B1, G1, R1, B0, G0, R0
0875          */
0876         value = 0;
0877         addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
0878         for (index = 0; index < 6; index++) {
0879             /* prepare color mask, first write PATTERN_DATA
0880              * will have all zeros
0881              */
0882             set_reg_field_value(
0883                 value,
0884                 (1 << index),
0885                 CRTC_TEST_PATTERN_COLOR,
0886                 CRTC_TEST_PATTERN_MASK);
0887             /* write color component */
0888             dm_write_reg(ctx, addr, value);
0889             /* prepare next color component,
0890              * will be written in the next iteration
0891              */
0892             set_reg_field_value(
0893                 value,
0894                 dst_color[index],
0895                 CRTC_TEST_PATTERN_COLOR,
0896                 CRTC_TEST_PATTERN_DATA);
0897         }
0898         /* write last color component,
0899          * it's been already prepared in the loop
0900          */
0901         dm_write_reg(ctx, addr, value);
0902 
0903         /* enable test pattern */
0904         addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
0905         value = 0;
0906 
0907         set_reg_field_value(
0908             value,
0909             1,
0910             CRTC_TEST_PATTERN_CONTROL,
0911             CRTC_TEST_PATTERN_EN);
0912 
0913         set_reg_field_value(
0914             value,
0915             mode,
0916             CRTC_TEST_PATTERN_CONTROL,
0917             CRTC_TEST_PATTERN_MODE);
0918 
0919         set_reg_field_value(
0920             value,
0921             0,
0922             CRTC_TEST_PATTERN_CONTROL,
0923             CRTC_TEST_PATTERN_DYNAMIC_RANGE);
0924 
0925         set_reg_field_value(
0926             value,
0927             bit_depth,
0928             CRTC_TEST_PATTERN_CONTROL,
0929             CRTC_TEST_PATTERN_COLOR_FORMAT);
0930 
0931         dm_write_reg(ctx, addr, value);
0932     }
0933     break;
0934 
0935     case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
0936     {
0937         mode = (bit_depth ==
0938             TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
0939             TEST_PATTERN_MODE_DUALRAMP_RGB :
0940             TEST_PATTERN_MODE_SINGLERAMP_RGB);
0941 
0942         switch (bit_depth) {
0943         case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0944             dst_bpc = 6;
0945         break;
0946         case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0947             dst_bpc = 8;
0948         break;
0949         case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0950             dst_bpc = 10;
0951         break;
0952         default:
0953             dst_bpc = 8;
0954         break;
0955         }
0956 
0957         /* increment for the first ramp for one color gradation
0958          * 1 gradation for 6-bit color is 2^10
0959          * gradations in 16-bit color
0960          */
0961         inc_base = (src_bpc - dst_bpc);
0962 
0963         value = 0;
0964         addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
0965 
0966         switch (bit_depth) {
0967         case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0968         {
0969             set_reg_field_value(
0970                 value,
0971                 inc_base,
0972                 CRTC_TEST_PATTERN_PARAMETERS,
0973                 CRTC_TEST_PATTERN_INC0);
0974             set_reg_field_value(
0975                 value,
0976                 0,
0977                 CRTC_TEST_PATTERN_PARAMETERS,
0978                 CRTC_TEST_PATTERN_INC1);
0979             set_reg_field_value(
0980                 value,
0981                 6,
0982                 CRTC_TEST_PATTERN_PARAMETERS,
0983                 CRTC_TEST_PATTERN_HRES);
0984             set_reg_field_value(
0985                 value,
0986                 6,
0987                 CRTC_TEST_PATTERN_PARAMETERS,
0988                 CRTC_TEST_PATTERN_VRES);
0989             set_reg_field_value(
0990                 value,
0991                 0,
0992                 CRTC_TEST_PATTERN_PARAMETERS,
0993                 CRTC_TEST_PATTERN_RAMP0_OFFSET);
0994         }
0995         break;
0996         case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0997         {
0998             set_reg_field_value(
0999                 value,
1000                 inc_base,
1001                 CRTC_TEST_PATTERN_PARAMETERS,
1002                 CRTC_TEST_PATTERN_INC0);
1003             set_reg_field_value(
1004                 value,
1005                 0,
1006                 CRTC_TEST_PATTERN_PARAMETERS,
1007                 CRTC_TEST_PATTERN_INC1);
1008             set_reg_field_value(
1009                 value,
1010                 8,
1011                 CRTC_TEST_PATTERN_PARAMETERS,
1012                 CRTC_TEST_PATTERN_HRES);
1013             set_reg_field_value(
1014                 value,
1015                 6,
1016                 CRTC_TEST_PATTERN_PARAMETERS,
1017                 CRTC_TEST_PATTERN_VRES);
1018             set_reg_field_value(
1019                 value,
1020                 0,
1021                 CRTC_TEST_PATTERN_PARAMETERS,
1022                 CRTC_TEST_PATTERN_RAMP0_OFFSET);
1023         }
1024         break;
1025         case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1026         {
1027             set_reg_field_value(
1028                 value,
1029                 inc_base,
1030                 CRTC_TEST_PATTERN_PARAMETERS,
1031                 CRTC_TEST_PATTERN_INC0);
1032             set_reg_field_value(
1033                 value,
1034                 inc_base + 2,
1035                 CRTC_TEST_PATTERN_PARAMETERS,
1036                 CRTC_TEST_PATTERN_INC1);
1037             set_reg_field_value(
1038                 value,
1039                 8,
1040                 CRTC_TEST_PATTERN_PARAMETERS,
1041                 CRTC_TEST_PATTERN_HRES);
1042             set_reg_field_value(
1043                 value,
1044                 5,
1045                 CRTC_TEST_PATTERN_PARAMETERS,
1046                 CRTC_TEST_PATTERN_VRES);
1047             set_reg_field_value(
1048                 value,
1049                 384 << 6,
1050                 CRTC_TEST_PATTERN_PARAMETERS,
1051                 CRTC_TEST_PATTERN_RAMP0_OFFSET);
1052         }
1053         break;
1054         default:
1055         break;
1056         }
1057         dm_write_reg(ctx, addr, value);
1058 
1059         value = 0;
1060         addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
1061         dm_write_reg(ctx, addr, value);
1062 
1063         /* enable test pattern */
1064         addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
1065         value = 0;
1066 
1067         set_reg_field_value(
1068             value,
1069             1,
1070             CRTC_TEST_PATTERN_CONTROL,
1071             CRTC_TEST_PATTERN_EN);
1072 
1073         set_reg_field_value(
1074             value,
1075             mode,
1076             CRTC_TEST_PATTERN_CONTROL,
1077             CRTC_TEST_PATTERN_MODE);
1078 
1079         set_reg_field_value(
1080             value,
1081             0,
1082             CRTC_TEST_PATTERN_CONTROL,
1083             CRTC_TEST_PATTERN_DYNAMIC_RANGE);
1084         /* add color depth translation here */
1085         set_reg_field_value(
1086             value,
1087             bit_depth,
1088             CRTC_TEST_PATTERN_CONTROL,
1089             CRTC_TEST_PATTERN_COLOR_FORMAT);
1090 
1091         dm_write_reg(ctx, addr, value);
1092     }
1093     break;
1094     case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1095     {
1096         value = 0;
1097         dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value);
1098         dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value);
1099         dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS),
1100                 value);
1101     }
1102     break;
1103     default:
1104     break;
1105     }
1106 }
1107 
1108 /*
1109  * dce110_timing_generator_validate_timing
1110  * The timing generators support a maximum display size of is 8192 x 8192 pixels,
1111  * including both active display and blanking periods. Check H Total and V Total.
1112  */
1113 bool dce110_timing_generator_validate_timing(
1114     struct timing_generator *tg,
1115     const struct dc_crtc_timing *timing,
1116     enum signal_type signal)
1117 {
1118     uint32_t h_blank;
1119     uint32_t h_back_porch, hsync_offset, h_sync_start;
1120 
1121     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1122 
1123     ASSERT(timing != NULL);
1124 
1125     if (!timing)
1126         return false;
1127 
1128     hsync_offset = timing->h_border_right + timing->h_front_porch;
1129     h_sync_start = timing->h_addressable + hsync_offset;
1130 
1131     /* Currently we don't support 3D, so block all 3D timings */
1132     if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE)
1133         return false;
1134 
1135     /* Temporarily blocking interlacing mode until it's supported */
1136     if (timing->flags.INTERLACE == 1)
1137         return false;
1138 
1139     /* Check maximum number of pixels supported by Timing Generator
1140      * (Currently will never fail, in order to fail needs display which
1141      * needs more than 8192 horizontal and
1142      * more than 8192 vertical total pixels)
1143      */
1144     if (timing->h_total > tg110->max_h_total ||
1145         timing->v_total > tg110->max_v_total)
1146         return false;
1147 
1148     h_blank = (timing->h_total - timing->h_addressable -
1149         timing->h_border_right -
1150         timing->h_border_left);
1151 
1152     if (h_blank < tg110->min_h_blank)
1153         return false;
1154 
1155     if (timing->h_front_porch < tg110->min_h_front_porch)
1156         return false;
1157 
1158     h_back_porch = h_blank - (h_sync_start -
1159         timing->h_addressable -
1160         timing->h_border_right -
1161         timing->h_sync_width);
1162 
1163     if (h_back_porch < tg110->min_h_back_porch)
1164         return false;
1165 
1166     return true;
1167 }
1168 
1169 /*
1170  * Wait till we are at the beginning of VBlank.
1171  */
1172 void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
1173 {
1174     /* We want to catch beginning of VBlank here, so if the first try are
1175      * in VBlank, we might be very close to Active, in this case wait for
1176      * another frame
1177      */
1178     while (dce110_timing_generator_is_in_vertical_blank(tg)) {
1179         if (!dce110_timing_generator_is_counter_moving(tg)) {
1180             /* error - no point to wait if counter is not moving */
1181             break;
1182         }
1183     }
1184 
1185     while (!dce110_timing_generator_is_in_vertical_blank(tg)) {
1186         if (!dce110_timing_generator_is_counter_moving(tg)) {
1187             /* error - no point to wait if counter is not moving */
1188             break;
1189         }
1190     }
1191 }
1192 
1193 /*
1194  * Wait till we are in VActive (anywhere in VActive)
1195  */
1196 void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
1197 {
1198     while (dce110_timing_generator_is_in_vertical_blank(tg)) {
1199         if (!dce110_timing_generator_is_counter_moving(tg)) {
1200             /* error - no point to wait if counter is not moving */
1201             break;
1202         }
1203     }
1204 }
1205 
1206 /*
1207  *****************************************************************************
1208  *  Function: dce110_timing_generator_setup_global_swap_lock
1209  *
1210  *  @brief
1211  *     Setups Global Swap Lock group for current pipe
1212  *     Pipe can join or leave GSL group, become a TimingServer or TimingClient
1213  *
1214  *  @param [in] gsl_params: setup data
1215  *****************************************************************************
1216  */
1217 void dce110_timing_generator_setup_global_swap_lock(
1218     struct timing_generator *tg,
1219     const struct dcp_gsl_params *gsl_params)
1220 {
1221     uint32_t value;
1222     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1223     uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
1224     uint32_t check_point = FLIP_READY_BACK_LOOKUP;
1225 
1226     value = dm_read_reg(tg->ctx, address);
1227 
1228     /* This pipe will belong to GSL Group zero. */
1229     set_reg_field_value(value,
1230                 1,
1231                 DCP_GSL_CONTROL,
1232                 DCP_GSL0_EN);
1233 
1234     set_reg_field_value(value,
1235                 gsl_params->gsl_master == tg->inst,
1236                 DCP_GSL_CONTROL,
1237                 DCP_GSL_MASTER_EN);
1238 
1239     set_reg_field_value(value,
1240                 HFLIP_READY_DELAY,
1241                 DCP_GSL_CONTROL,
1242                 DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
1243 
1244     /* Keep signal low (pending high) during 6 lines.
1245      * Also defines minimum interval before re-checking signal. */
1246     set_reg_field_value(value,
1247                 HFLIP_CHECK_DELAY,
1248                 DCP_GSL_CONTROL,
1249                 DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
1250 
1251     dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value);
1252     value = 0;
1253 
1254     set_reg_field_value(value,
1255                 gsl_params->gsl_master,
1256                 DCIO_GSL0_CNTL,
1257                 DCIO_GSL0_VSYNC_SEL);
1258 
1259     set_reg_field_value(value,
1260                 0,
1261                 DCIO_GSL0_CNTL,
1262                 DCIO_GSL0_TIMING_SYNC_SEL);
1263 
1264     set_reg_field_value(value,
1265                 0,
1266                 DCIO_GSL0_CNTL,
1267                 DCIO_GSL0_GLOBAL_UNLOCK_SEL);
1268 
1269     dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value);
1270 
1271 
1272     {
1273         uint32_t value_crtc_vtotal;
1274 
1275         value_crtc_vtotal = dm_read_reg(tg->ctx,
1276                 CRTC_REG(mmCRTC_V_TOTAL));
1277 
1278         set_reg_field_value(value,
1279                     0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */
1280                     DCP_GSL_CONTROL,
1281                     DCP_GSL_SYNC_SOURCE);
1282 
1283         /* Checkpoint relative to end of frame */
1284         check_point = get_reg_field_value(value_crtc_vtotal,
1285                           CRTC_V_TOTAL,
1286                           CRTC_V_TOTAL);
1287 
1288         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0);
1289     }
1290 
1291     set_reg_field_value(value,
1292                 1,
1293                 DCP_GSL_CONTROL,
1294                 DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
1295 
1296     dm_write_reg(tg->ctx, address, value);
1297 
1298     /********************************************************************/
1299     address = CRTC_REG(mmCRTC_GSL_CONTROL);
1300 
1301     value = dm_read_reg(tg->ctx, address);
1302     set_reg_field_value(value,
1303                 check_point - FLIP_READY_BACK_LOOKUP,
1304                 CRTC_GSL_CONTROL,
1305                 CRTC_GSL_CHECK_LINE_NUM);
1306 
1307     set_reg_field_value(value,
1308                 VFLIP_READY_DELAY,
1309                 CRTC_GSL_CONTROL,
1310                 CRTC_GSL_FORCE_DELAY);
1311 
1312     dm_write_reg(tg->ctx, address, value);
1313 }
1314 
1315 void dce110_timing_generator_tear_down_global_swap_lock(
1316     struct timing_generator *tg)
1317 {
1318     /* Clear all the register writes done by
1319      * dce110_timing_generator_setup_global_swap_lock
1320      */
1321 
1322     uint32_t value;
1323     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1324     uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
1325 
1326     value = 0;
1327 
1328     /* This pipe will belong to GSL Group zero. */
1329     /* Settig HW default values from reg specs */
1330     set_reg_field_value(value,
1331             0,
1332             DCP_GSL_CONTROL,
1333             DCP_GSL0_EN);
1334 
1335     set_reg_field_value(value,
1336             0,
1337             DCP_GSL_CONTROL,
1338             DCP_GSL_MASTER_EN);
1339 
1340     set_reg_field_value(value,
1341             0x2,
1342             DCP_GSL_CONTROL,
1343             DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
1344 
1345     set_reg_field_value(value,
1346             0x6,
1347             DCP_GSL_CONTROL,
1348             DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
1349 
1350     /* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */
1351     {
1352         dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_TOTAL));
1353 
1354         set_reg_field_value(value,
1355                 0,
1356                 DCP_GSL_CONTROL,
1357                 DCP_GSL_SYNC_SOURCE);
1358     }
1359 
1360     set_reg_field_value(value,
1361             0,
1362             DCP_GSL_CONTROL,
1363             DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
1364 
1365     dm_write_reg(tg->ctx, address, value);
1366 
1367     /********************************************************************/
1368     address = CRTC_REG(mmCRTC_GSL_CONTROL);
1369 
1370     value = 0;
1371     set_reg_field_value(value,
1372             0,
1373             CRTC_GSL_CONTROL,
1374             CRTC_GSL_CHECK_LINE_NUM);
1375 
1376     set_reg_field_value(value,
1377             0x2,
1378             CRTC_GSL_CONTROL,
1379             CRTC_GSL_FORCE_DELAY);
1380 
1381     dm_write_reg(tg->ctx, address, value);
1382 }
1383 /*
1384  *****************************************************************************
1385  *  Function: is_counter_moving
1386  *
1387  *  @brief
1388  *     check if the timing generator is currently going
1389  *
1390  *  @return
1391  *     true if currently going, false if currently paused or stopped.
1392  *
1393  *****************************************************************************
1394  */
1395 bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
1396 {
1397     struct crtc_position position1, position2;
1398 
1399     tg->funcs->get_position(tg, &position1);
1400     tg->funcs->get_position(tg, &position2);
1401 
1402     if (position1.horizontal_count == position2.horizontal_count &&
1403         position1.vertical_count == position2.vertical_count)
1404         return false;
1405     else
1406         return true;
1407 }
1408 
1409 void dce110_timing_generator_enable_advanced_request(
1410     struct timing_generator *tg,
1411     bool enable,
1412     const struct dc_crtc_timing *timing)
1413 {
1414     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1415     uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL);
1416     uint32_t value = dm_read_reg(tg->ctx, addr);
1417 
1418     if (enable) {
1419         set_reg_field_value(
1420             value,
1421             0,
1422             CRTC_START_LINE_CONTROL,
1423             CRTC_LEGACY_REQUESTOR_EN);
1424     } else {
1425         set_reg_field_value(
1426             value,
1427             1,
1428             CRTC_START_LINE_CONTROL,
1429             CRTC_LEGACY_REQUESTOR_EN);
1430     }
1431 
1432     if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
1433         set_reg_field_value(
1434             value,
1435             3,
1436             CRTC_START_LINE_CONTROL,
1437             CRTC_ADVANCED_START_LINE_POSITION);
1438         set_reg_field_value(
1439             value,
1440             0,
1441             CRTC_START_LINE_CONTROL,
1442             CRTC_PREFETCH_EN);
1443     } else {
1444         set_reg_field_value(
1445             value,
1446             4,
1447             CRTC_START_LINE_CONTROL,
1448             CRTC_ADVANCED_START_LINE_POSITION);
1449         set_reg_field_value(
1450             value,
1451             1,
1452             CRTC_START_LINE_CONTROL,
1453             CRTC_PREFETCH_EN);
1454     }
1455 
1456     set_reg_field_value(
1457         value,
1458         1,
1459         CRTC_START_LINE_CONTROL,
1460         CRTC_PROGRESSIVE_START_LINE_EARLY);
1461 
1462     set_reg_field_value(
1463         value,
1464         1,
1465         CRTC_START_LINE_CONTROL,
1466         CRTC_INTERLACE_START_LINE_EARLY);
1467 
1468     dm_write_reg(tg->ctx, addr, value);
1469 }
1470 
1471 /*TODO: Figure out if we need this function. */
1472 void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
1473         bool lock)
1474 {
1475     struct dc_context *ctx = tg->ctx;
1476     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1477     uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK);
1478     uint32_t value = dm_read_reg(ctx, addr);
1479 
1480     set_reg_field_value(
1481         value,
1482         lock ? 1 : 0,
1483         CRTC_MASTER_UPDATE_LOCK,
1484         MASTER_UPDATE_LOCK);
1485 
1486     dm_write_reg(ctx, addr, value);
1487 }
1488 
1489 void dce110_timing_generator_enable_reset_trigger(
1490     struct timing_generator *tg,
1491     int source_tg_inst)
1492 {
1493     uint32_t value;
1494     uint32_t rising_edge = 0;
1495     uint32_t falling_edge = 0;
1496     enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
1497     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1498 
1499     /* Setup trigger edge */
1500     {
1501         uint32_t pol_value = dm_read_reg(tg->ctx,
1502                 CRTC_REG(mmCRTC_V_SYNC_A_CNTL));
1503 
1504         /* Register spec has reversed definition:
1505          *  0 for positive, 1 for negative */
1506         if (get_reg_field_value(pol_value,
1507                 CRTC_V_SYNC_A_CNTL,
1508                 CRTC_V_SYNC_A_POL) == 0) {
1509             rising_edge = 1;
1510         } else {
1511             falling_edge = 1;
1512         }
1513     }
1514 
1515     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
1516 
1517     trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
1518 
1519     set_reg_field_value(value,
1520             trig_src_select,
1521             CRTC_TRIGB_CNTL,
1522             CRTC_TRIGB_SOURCE_SELECT);
1523 
1524     set_reg_field_value(value,
1525             TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
1526             CRTC_TRIGB_CNTL,
1527             CRTC_TRIGB_POLARITY_SELECT);
1528 
1529     set_reg_field_value(value,
1530             rising_edge,
1531             CRTC_TRIGB_CNTL,
1532             CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
1533 
1534     set_reg_field_value(value,
1535             falling_edge,
1536             CRTC_TRIGB_CNTL,
1537             CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
1538 
1539     set_reg_field_value(value,
1540             0, /* send every signal */
1541             CRTC_TRIGB_CNTL,
1542             CRTC_TRIGB_FREQUENCY_SELECT);
1543 
1544     set_reg_field_value(value,
1545             0, /* no delay */
1546             CRTC_TRIGB_CNTL,
1547             CRTC_TRIGB_DELAY);
1548 
1549     set_reg_field_value(value,
1550             1, /* clear trigger status */
1551             CRTC_TRIGB_CNTL,
1552             CRTC_TRIGB_CLEAR);
1553 
1554     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
1555 
1556     /**************************************************************/
1557 
1558     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1559 
1560     set_reg_field_value(value,
1561             2, /* force H count to H_TOTAL and V count to V_TOTAL */
1562             CRTC_FORCE_COUNT_NOW_CNTL,
1563             CRTC_FORCE_COUNT_NOW_MODE);
1564 
1565     set_reg_field_value(value,
1566             1, /* TriggerB - we never use TriggerA */
1567             CRTC_FORCE_COUNT_NOW_CNTL,
1568             CRTC_FORCE_COUNT_NOW_TRIG_SEL);
1569 
1570     set_reg_field_value(value,
1571             1, /* clear trigger status */
1572             CRTC_FORCE_COUNT_NOW_CNTL,
1573             CRTC_FORCE_COUNT_NOW_CLEAR);
1574 
1575     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1576 }
1577 
1578 void dce110_timing_generator_enable_crtc_reset(
1579         struct timing_generator *tg,
1580         int source_tg_inst,
1581         struct crtc_trigger_info *crtc_tp)
1582 {
1583     uint32_t value = 0;
1584     uint32_t rising_edge = 0;
1585     uint32_t falling_edge = 0;
1586     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1587 
1588     /* Setup trigger edge */
1589     switch (crtc_tp->event) {
1590     case CRTC_EVENT_VSYNC_RISING:
1591             rising_edge = 1;
1592             break;
1593 
1594     case CRTC_EVENT_VSYNC_FALLING:
1595         falling_edge = 1;
1596         break;
1597     }
1598 
1599     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
1600 
1601     set_reg_field_value(value,
1602                 source_tg_inst,
1603                 CRTC_TRIGB_CNTL,
1604                 CRTC_TRIGB_SOURCE_SELECT);
1605 
1606     set_reg_field_value(value,
1607                 TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
1608                 CRTC_TRIGB_CNTL,
1609                 CRTC_TRIGB_POLARITY_SELECT);
1610 
1611     set_reg_field_value(value,
1612                 rising_edge,
1613                 CRTC_TRIGB_CNTL,
1614                 CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
1615 
1616     set_reg_field_value(value,
1617                 falling_edge,
1618                 CRTC_TRIGB_CNTL,
1619                 CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
1620 
1621     set_reg_field_value(value,
1622                 1, /* clear trigger status */
1623                 CRTC_TRIGB_CNTL,
1624                 CRTC_TRIGB_CLEAR);
1625 
1626     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
1627 
1628     /**************************************************************/
1629 
1630     switch (crtc_tp->delay) {
1631     case TRIGGER_DELAY_NEXT_LINE:
1632         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1633 
1634         set_reg_field_value(value,
1635                     0, /* force H count to H_TOTAL and V count to V_TOTAL */
1636                     CRTC_FORCE_COUNT_NOW_CNTL,
1637                     CRTC_FORCE_COUNT_NOW_MODE);
1638 
1639         set_reg_field_value(value,
1640                     0, /* TriggerB - we never use TriggerA */
1641                     CRTC_FORCE_COUNT_NOW_CNTL,
1642                     CRTC_FORCE_COUNT_NOW_TRIG_SEL);
1643 
1644         set_reg_field_value(value,
1645                     1, /* clear trigger status */
1646                     CRTC_FORCE_COUNT_NOW_CNTL,
1647                     CRTC_FORCE_COUNT_NOW_CLEAR);
1648 
1649         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1650 
1651         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1652 
1653         set_reg_field_value(value,
1654                     1,
1655                     CRTC_VERT_SYNC_CONTROL,
1656                     CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
1657 
1658         set_reg_field_value(value,
1659                     2,
1660                     CRTC_VERT_SYNC_CONTROL,
1661                     CRTC_AUTO_FORCE_VSYNC_MODE);
1662 
1663         break;
1664 
1665     case TRIGGER_DELAY_NEXT_PIXEL:
1666         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1667 
1668         set_reg_field_value(value,
1669                     1,
1670                     CRTC_VERT_SYNC_CONTROL,
1671                     CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
1672 
1673         set_reg_field_value(value,
1674                     0,
1675                     CRTC_VERT_SYNC_CONTROL,
1676                     CRTC_AUTO_FORCE_VSYNC_MODE);
1677 
1678         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
1679 
1680         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1681 
1682         set_reg_field_value(value,
1683                     2, /* force H count to H_TOTAL and V count to V_TOTAL */
1684                     CRTC_FORCE_COUNT_NOW_CNTL,
1685                     CRTC_FORCE_COUNT_NOW_MODE);
1686 
1687         set_reg_field_value(value,
1688                     1, /* TriggerB - we never use TriggerA */
1689                     CRTC_FORCE_COUNT_NOW_CNTL,
1690                     CRTC_FORCE_COUNT_NOW_TRIG_SEL);
1691 
1692         set_reg_field_value(value,
1693                     1, /* clear trigger status */
1694                     CRTC_FORCE_COUNT_NOW_CNTL,
1695                     CRTC_FORCE_COUNT_NOW_CLEAR);
1696 
1697         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1698         break;
1699     }
1700 
1701     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE));
1702 
1703     set_reg_field_value(value,
1704                 2,
1705                 CRTC_MASTER_UPDATE_MODE,
1706                 MASTER_UPDATE_MODE);
1707 
1708     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
1709 }
1710 void dce110_timing_generator_disable_reset_trigger(
1711     struct timing_generator *tg)
1712 {
1713     uint32_t value;
1714     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1715 
1716     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1717 
1718     set_reg_field_value(value,
1719                 0, /* force counter now mode is disabled */
1720                 CRTC_FORCE_COUNT_NOW_CNTL,
1721                 CRTC_FORCE_COUNT_NOW_MODE);
1722 
1723     set_reg_field_value(value,
1724                 1, /* clear trigger status */
1725                 CRTC_FORCE_COUNT_NOW_CNTL,
1726                 CRTC_FORCE_COUNT_NOW_CLEAR);
1727 
1728     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
1729 
1730     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1731 
1732     set_reg_field_value(value,
1733                 1,
1734                 CRTC_VERT_SYNC_CONTROL,
1735                 CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
1736 
1737     set_reg_field_value(value,
1738                 0,
1739                 CRTC_VERT_SYNC_CONTROL,
1740                 CRTC_AUTO_FORCE_VSYNC_MODE);
1741 
1742     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
1743 
1744     /********************************************************************/
1745     value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
1746 
1747     set_reg_field_value(value,
1748                 TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
1749                 CRTC_TRIGB_CNTL,
1750                 CRTC_TRIGB_SOURCE_SELECT);
1751 
1752     set_reg_field_value(value,
1753                 TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
1754                 CRTC_TRIGB_CNTL,
1755                 CRTC_TRIGB_POLARITY_SELECT);
1756 
1757     set_reg_field_value(value,
1758                 1, /* clear trigger status */
1759                 CRTC_TRIGB_CNTL,
1760                 CRTC_TRIGB_CLEAR);
1761 
1762     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
1763 }
1764 
1765 /*
1766  *****************************************************************************
1767  *  @brief
1768  *     Checks whether CRTC triggered reset occurred
1769  *
1770  *  @return
1771  *     true if triggered reset occurred, false otherwise
1772  *****************************************************************************
1773  */
1774 bool dce110_timing_generator_did_triggered_reset_occur(
1775     struct timing_generator *tg)
1776 {
1777     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1778     uint32_t value = dm_read_reg(tg->ctx,
1779             CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
1780     uint32_t value1 = dm_read_reg(tg->ctx,
1781             CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
1782     bool force = get_reg_field_value(value,
1783                      CRTC_FORCE_COUNT_NOW_CNTL,
1784                      CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
1785     bool vert_sync = get_reg_field_value(value1,
1786                          CRTC_VERT_SYNC_CONTROL,
1787                          CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0;
1788 
1789     return (force || vert_sync);
1790 }
1791 
1792 /*
1793  * dce110_timing_generator_disable_vga
1794  * Turn OFF VGA Mode and Timing  - DxVGA_CONTROL
1795  * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors;
1796  */
1797 void dce110_timing_generator_disable_vga(
1798     struct timing_generator *tg)
1799 {
1800     uint32_t addr = 0;
1801     uint32_t value = 0;
1802 
1803     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1804 
1805     switch (tg110->controller_id) {
1806     case CONTROLLER_ID_D0:
1807         addr = mmD1VGA_CONTROL;
1808         break;
1809     case CONTROLLER_ID_D1:
1810         addr = mmD2VGA_CONTROL;
1811         break;
1812     case CONTROLLER_ID_D2:
1813         addr = mmD3VGA_CONTROL;
1814         break;
1815     case CONTROLLER_ID_D3:
1816         addr = mmD4VGA_CONTROL;
1817         break;
1818     case CONTROLLER_ID_D4:
1819         addr = mmD5VGA_CONTROL;
1820         break;
1821     case CONTROLLER_ID_D5:
1822         addr = mmD6VGA_CONTROL;
1823         break;
1824     default:
1825         break;
1826     }
1827     value = dm_read_reg(tg->ctx, addr);
1828 
1829     set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
1830     set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
1831     set_reg_field_value(
1832             value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
1833     set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
1834 
1835     dm_write_reg(tg->ctx, addr, value);
1836 }
1837 
1838 /*
1839  * set_overscan_color_black
1840  *
1841  * @param :black_color is one of the color space
1842  *    :this routine will set overscan black color according to the color space.
1843  * @return none
1844  */
1845 void dce110_timing_generator_set_overscan_color_black(
1846     struct timing_generator *tg,
1847     const struct tg_color *color)
1848 {
1849     struct dc_context *ctx = tg->ctx;
1850     uint32_t addr;
1851     uint32_t value = 0;
1852     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1853 
1854     set_reg_field_value(
1855             value,
1856             color->color_b_cb,
1857             CRTC_OVERSCAN_COLOR,
1858             CRTC_OVERSCAN_COLOR_BLUE);
1859 
1860     set_reg_field_value(
1861             value,
1862             color->color_r_cr,
1863             CRTC_OVERSCAN_COLOR,
1864             CRTC_OVERSCAN_COLOR_RED);
1865 
1866     set_reg_field_value(
1867             value,
1868             color->color_g_y,
1869             CRTC_OVERSCAN_COLOR,
1870             CRTC_OVERSCAN_COLOR_GREEN);
1871 
1872     addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
1873     dm_write_reg(ctx, addr, value);
1874     addr = CRTC_REG(mmCRTC_BLACK_COLOR);
1875     dm_write_reg(ctx, addr, value);
1876     /* This is desirable to have a constant DAC output voltage during the
1877      * blank time that is higher than the 0 volt reference level that the
1878      * DAC outputs when the NBLANK signal
1879      * is asserted low, such as for output to an analog TV. */
1880     addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
1881     dm_write_reg(ctx, addr, value);
1882 
1883     /* TO DO we have to program EXT registers and we need to know LB DATA
1884      * format because it is used when more 10 , i.e. 12 bits per color
1885      *
1886      * m_mmDxCRTC_OVERSCAN_COLOR_EXT
1887      * m_mmDxCRTC_BLACK_COLOR_EXT
1888      * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
1889      */
1890 
1891 }
1892 
1893 void dce110_tg_program_blank_color(struct timing_generator *tg,
1894         const struct tg_color *black_color)
1895 {
1896     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1897     uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
1898     uint32_t value = dm_read_reg(tg->ctx, addr);
1899 
1900     set_reg_field_value(
1901         value,
1902         black_color->color_b_cb,
1903         CRTC_BLACK_COLOR,
1904         CRTC_BLACK_COLOR_B_CB);
1905     set_reg_field_value(
1906         value,
1907         black_color->color_g_y,
1908         CRTC_BLACK_COLOR,
1909         CRTC_BLACK_COLOR_G_Y);
1910     set_reg_field_value(
1911         value,
1912         black_color->color_r_cr,
1913         CRTC_BLACK_COLOR,
1914         CRTC_BLACK_COLOR_R_CR);
1915 
1916     dm_write_reg(tg->ctx, addr, value);
1917 
1918     addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
1919     dm_write_reg(tg->ctx, addr, value);
1920 }
1921 
1922 void dce110_tg_set_overscan_color(struct timing_generator *tg,
1923     const struct tg_color *overscan_color)
1924 {
1925     struct dc_context *ctx = tg->ctx;
1926     uint32_t value = 0;
1927     uint32_t addr;
1928     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1929 
1930     set_reg_field_value(
1931         value,
1932         overscan_color->color_b_cb,
1933         CRTC_OVERSCAN_COLOR,
1934         CRTC_OVERSCAN_COLOR_BLUE);
1935 
1936     set_reg_field_value(
1937         value,
1938         overscan_color->color_g_y,
1939         CRTC_OVERSCAN_COLOR,
1940         CRTC_OVERSCAN_COLOR_GREEN);
1941 
1942     set_reg_field_value(
1943         value,
1944         overscan_color->color_r_cr,
1945         CRTC_OVERSCAN_COLOR,
1946         CRTC_OVERSCAN_COLOR_RED);
1947 
1948     addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
1949     dm_write_reg(ctx, addr, value);
1950 }
1951 
1952 void dce110_tg_program_timing(struct timing_generator *tg,
1953     const struct dc_crtc_timing *timing,
1954     int vready_offset,
1955     int vstartup_start,
1956     int vupdate_offset,
1957     int vupdate_width,
1958     const enum signal_type signal,
1959     bool use_vbios)
1960 {
1961     if (use_vbios)
1962         dce110_timing_generator_program_timing_generator(tg, timing);
1963     else
1964         dce110_timing_generator_program_blanking(tg, timing);
1965 }
1966 
1967 bool dce110_tg_is_blanked(struct timing_generator *tg)
1968 {
1969     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1970     uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
1971 
1972     if (get_reg_field_value(
1973             value,
1974             CRTC_BLANK_CONTROL,
1975             CRTC_BLANK_DATA_EN) == 1 &&
1976         get_reg_field_value(
1977             value,
1978             CRTC_BLANK_CONTROL,
1979             CRTC_CURRENT_BLANK_STATE) == 1)
1980         return true;
1981     return false;
1982 }
1983 
1984 void dce110_tg_set_blank(struct timing_generator *tg,
1985         bool enable_blanking)
1986 {
1987     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1988     uint32_t value = 0;
1989 
1990     set_reg_field_value(
1991         value,
1992         1,
1993         CRTC_DOUBLE_BUFFER_CONTROL,
1994         CRTC_BLANK_DATA_DOUBLE_BUFFER_EN);
1995 
1996     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value);
1997     value = 0;
1998 
1999     if (enable_blanking) {
2000         set_reg_field_value(
2001             value,
2002             1,
2003             CRTC_BLANK_CONTROL,
2004             CRTC_BLANK_DATA_EN);
2005 
2006         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);
2007 
2008     } else
2009         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
2010 }
2011 
2012 bool dce110_tg_validate_timing(struct timing_generator *tg,
2013     const struct dc_crtc_timing *timing)
2014 {
2015     return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
2016 }
2017 
2018 void dce110_tg_wait_for_state(struct timing_generator *tg,
2019     enum crtc_state state)
2020 {
2021     switch (state) {
2022     case CRTC_STATE_VBLANK:
2023         dce110_timing_generator_wait_for_vblank(tg);
2024         break;
2025 
2026     case CRTC_STATE_VACTIVE:
2027         dce110_timing_generator_wait_for_vactive(tg);
2028         break;
2029 
2030     default:
2031         break;
2032     }
2033 }
2034 
2035 void dce110_tg_set_colors(struct timing_generator *tg,
2036     const struct tg_color *blank_color,
2037     const struct tg_color *overscan_color)
2038 {
2039     if (blank_color != NULL)
2040         dce110_tg_program_blank_color(tg, blank_color);
2041     if (overscan_color != NULL)
2042         dce110_tg_set_overscan_color(tg, overscan_color);
2043 }
2044 
2045 /* Gets first line of blank region of the display timing for CRTC
2046  * and programms is as a trigger to fire vertical interrupt
2047  */
2048 bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
2049 {
2050     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2051     uint32_t v_blank_start = 0;
2052     uint32_t v_blank_end = 0;
2053     uint32_t val = 0;
2054     uint32_t h_position, v_position;
2055 
2056     tg->funcs->get_scanoutpos(
2057             tg,
2058             &v_blank_start,
2059             &v_blank_end,
2060             &h_position,
2061             &v_position);
2062 
2063     if (v_blank_start == 0 || v_blank_end == 0)
2064         return false;
2065 
2066     set_reg_field_value(
2067         val,
2068         v_blank_start,
2069         CRTC_VERTICAL_INTERRUPT0_POSITION,
2070         CRTC_VERTICAL_INTERRUPT0_LINE_START);
2071 
2072     /* Set interval width for interrupt to fire to 1 scanline */
2073     set_reg_field_value(
2074         val,
2075         v_blank_start + width,
2076         CRTC_VERTICAL_INTERRUPT0_POSITION,
2077         CRTC_VERTICAL_INTERRUPT0_LINE_END);
2078 
2079     dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val);
2080 
2081     return true;
2082 }
2083 
2084 static bool dce110_is_tg_enabled(struct timing_generator *tg)
2085 {
2086     uint32_t addr = 0;
2087     uint32_t value = 0;
2088     uint32_t field = 0;
2089     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2090 
2091     addr = CRTC_REG(mmCRTC_CONTROL);
2092     value = dm_read_reg(tg->ctx, addr);
2093     field = get_reg_field_value(value, CRTC_CONTROL,
2094                     CRTC_CURRENT_MASTER_EN_STATE);
2095     return field == 1;
2096 }
2097 
2098 bool dce110_configure_crc(struct timing_generator *tg,
2099               const struct crc_params *params)
2100 {
2101     uint32_t cntl_addr = 0;
2102     uint32_t addr = 0;
2103     uint32_t value;
2104     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2105 
2106     /* Cannot configure crc on a CRTC that is disabled */
2107     if (!dce110_is_tg_enabled(tg))
2108         return false;
2109 
2110     cntl_addr = CRTC_REG(mmCRTC_CRC_CNTL);
2111 
2112     /* First, disable CRC before we configure it. */
2113     dm_write_reg(tg->ctx, cntl_addr, 0);
2114 
2115     if (!params->enable)
2116         return true;
2117 
2118     /* Program frame boundaries */
2119     /* Window A x axis start and end. */
2120     value = 0;
2121     addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL);
2122     set_reg_field_value(value, params->windowa_x_start,
2123                 CRTC_CRC0_WINDOWA_X_CONTROL,
2124                 CRTC_CRC0_WINDOWA_X_START);
2125     set_reg_field_value(value, params->windowa_x_end,
2126                 CRTC_CRC0_WINDOWA_X_CONTROL,
2127                 CRTC_CRC0_WINDOWA_X_END);
2128     dm_write_reg(tg->ctx, addr, value);
2129 
2130     /* Window A y axis start and end. */
2131     value = 0;
2132     addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL);
2133     set_reg_field_value(value, params->windowa_y_start,
2134                 CRTC_CRC0_WINDOWA_Y_CONTROL,
2135                 CRTC_CRC0_WINDOWA_Y_START);
2136     set_reg_field_value(value, params->windowa_y_end,
2137                 CRTC_CRC0_WINDOWA_Y_CONTROL,
2138                 CRTC_CRC0_WINDOWA_Y_END);
2139     dm_write_reg(tg->ctx, addr, value);
2140 
2141     /* Window B x axis start and end. */
2142     value = 0;
2143     addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL);
2144     set_reg_field_value(value, params->windowb_x_start,
2145                 CRTC_CRC0_WINDOWB_X_CONTROL,
2146                 CRTC_CRC0_WINDOWB_X_START);
2147     set_reg_field_value(value, params->windowb_x_end,
2148                 CRTC_CRC0_WINDOWB_X_CONTROL,
2149                 CRTC_CRC0_WINDOWB_X_END);
2150     dm_write_reg(tg->ctx, addr, value);
2151 
2152     /* Window B y axis start and end. */
2153     value = 0;
2154     addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL);
2155     set_reg_field_value(value, params->windowb_y_start,
2156                 CRTC_CRC0_WINDOWB_Y_CONTROL,
2157                 CRTC_CRC0_WINDOWB_Y_START);
2158     set_reg_field_value(value, params->windowb_y_end,
2159                 CRTC_CRC0_WINDOWB_Y_CONTROL,
2160                 CRTC_CRC0_WINDOWB_Y_END);
2161     dm_write_reg(tg->ctx, addr, value);
2162 
2163     /* Set crc mode and selection, and enable. Only using CRC0*/
2164     value = 0;
2165     set_reg_field_value(value, params->continuous_mode ? 1 : 0,
2166                 CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
2167     set_reg_field_value(value, params->selection,
2168                 CRTC_CRC_CNTL, CRTC_CRC0_SELECT);
2169     set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
2170     dm_write_reg(tg->ctx, cntl_addr, value);
2171 
2172     return true;
2173 }
2174 
2175 bool dce110_get_crc(struct timing_generator *tg,
2176             uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
2177 {
2178     uint32_t addr = 0;
2179     uint32_t value = 0;
2180     uint32_t field = 0;
2181     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
2182 
2183     addr = CRTC_REG(mmCRTC_CRC_CNTL);
2184     value = dm_read_reg(tg->ctx, addr);
2185     field = get_reg_field_value(value, CRTC_CRC_CNTL, CRTC_CRC_EN);
2186 
2187     /* Early return if CRC is not enabled for this CRTC */
2188     if (!field)
2189         return false;
2190 
2191     addr = CRTC_REG(mmCRTC_CRC0_DATA_RG);
2192     value = dm_read_reg(tg->ctx, addr);
2193     *r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR);
2194     *g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y);
2195 
2196     addr = CRTC_REG(mmCRTC_CRC0_DATA_B);
2197     value = dm_read_reg(tg->ctx, addr);
2198     *b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB);
2199 
2200     return true;
2201 }
2202 
2203 static const struct timing_generator_funcs dce110_tg_funcs = {
2204         .validate_timing = dce110_tg_validate_timing,
2205         .program_timing = dce110_tg_program_timing,
2206         .enable_crtc = dce110_timing_generator_enable_crtc,
2207         .disable_crtc = dce110_timing_generator_disable_crtc,
2208         .is_counter_moving = dce110_timing_generator_is_counter_moving,
2209         .get_position = dce110_timing_generator_get_position,
2210         .get_frame_count = dce110_timing_generator_get_vblank_counter,
2211         .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
2212         .set_early_control = dce110_timing_generator_set_early_control,
2213         .wait_for_state = dce110_tg_wait_for_state,
2214         .set_blank = dce110_tg_set_blank,
2215         .is_blanked = dce110_tg_is_blanked,
2216         .set_colors = dce110_tg_set_colors,
2217         .set_overscan_blank_color =
2218                 dce110_timing_generator_set_overscan_color_black,
2219         .set_blank_color = dce110_timing_generator_program_blank_color,
2220         .disable_vga = dce110_timing_generator_disable_vga,
2221         .did_triggered_reset_occur =
2222                 dce110_timing_generator_did_triggered_reset_occur,
2223         .setup_global_swap_lock =
2224                 dce110_timing_generator_setup_global_swap_lock,
2225         .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger,
2226         .enable_crtc_reset = dce110_timing_generator_enable_crtc_reset,
2227         .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger,
2228         .tear_down_global_swap_lock =
2229                 dce110_timing_generator_tear_down_global_swap_lock,
2230         .enable_advanced_request =
2231                 dce110_timing_generator_enable_advanced_request,
2232         .set_drr =
2233                 dce110_timing_generator_set_drr,
2234         .get_last_used_drr_vtotal = NULL,
2235         .set_static_screen_control =
2236             dce110_timing_generator_set_static_screen_control,
2237         .set_test_pattern = dce110_timing_generator_set_test_pattern,
2238         .arm_vert_intr = dce110_arm_vert_intr,
2239         .is_tg_enabled = dce110_is_tg_enabled,
2240         .configure_crc = dce110_configure_crc,
2241         .get_crc = dce110_get_crc,
2242 };
2243 
2244 void dce110_timing_generator_construct(
2245     struct dce110_timing_generator *tg110,
2246     struct dc_context *ctx,
2247     uint32_t instance,
2248     const struct dce110_timing_generator_offsets *offsets)
2249 {
2250     tg110->controller_id = CONTROLLER_ID_D0 + instance;
2251     tg110->base.inst = instance;
2252 
2253     tg110->offsets = *offsets;
2254 
2255     tg110->base.funcs = &dce110_tg_funcs;
2256 
2257     tg110->base.ctx = ctx;
2258     tg110->base.bp = ctx->dc_bios;
2259 
2260     tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
2261     tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
2262 
2263     tg110->min_h_blank = 56;
2264     tg110->min_h_front_porch = 4;
2265     tg110->min_h_back_porch = 4;
2266 }