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 "dce/dce_12_0_offset.h"
0029 #include "dce/dce_12_0_sh_mask.h"
0030 #include "soc15_hw_ip.h"
0031 #include "vega10_ip_offset.h"
0032 
0033 #include "dc_types.h"
0034 #include "dc_bios_types.h"
0035 
0036 #include "include/grph_object_id.h"
0037 #include "include/logger_interface.h"
0038 #include "dce120_timing_generator.h"
0039 
0040 #include "timing_generator.h"
0041 
0042 #define CRTC_REG_UPDATE_N(reg_name, n, ...) \
0043         generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
0044 
0045 #define CRTC_REG_SET_N(reg_name, n, ...)    \
0046         generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
0047 
0048 #define CRTC_REG_UPDATE(reg, field, val)    \
0049         CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
0050 
0051 #define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2)  \
0052         CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
0053 
0054 #define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3)    \
0055         CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
0056 
0057 #define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4)  \
0058         CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4)
0059 
0060 #define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5)    \
0061         CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4, FD(reg##__##field5), val5)
0062 
0063 #define CRTC_REG_SET(reg, field, val)   \
0064         CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val)
0065 
0066 #define CRTC_REG_SET_2(reg, field1, val1, field2, val2) \
0067         CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
0068 
0069 #define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3)   \
0070         CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
0071 
0072 /*
0073  *****************************************************************************
0074  *  Function: is_in_vertical_blank
0075  *
0076  *  @brief
0077  *     check the current status of CRTC to check if we are in Vertical Blank
0078  *     regioneased" state
0079  *
0080  *  @return
0081  *     true if currently in blank region, false otherwise
0082  *
0083  *****************************************************************************
0084  */
0085 static bool dce120_timing_generator_is_in_vertical_blank(
0086         struct timing_generator *tg)
0087 {
0088     uint32_t field = 0;
0089     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0090     uint32_t value = dm_read_reg_soc15(
0091                     tg->ctx,
0092                     mmCRTC0_CRTC_STATUS,
0093                     tg110->offsets.crtc);
0094 
0095     field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK);
0096     return field == 1;
0097 }
0098 
0099 
0100 /* determine if given timing can be supported by TG */
0101 static bool dce120_timing_generator_validate_timing(
0102     struct timing_generator *tg,
0103     const struct dc_crtc_timing *timing,
0104     enum signal_type signal)
0105 {
0106     uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1;
0107     uint32_t v_blank =
0108                     (timing->v_total - timing->v_addressable -
0109                     timing->v_border_top - timing->v_border_bottom) *
0110                     interlace_factor;
0111     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0112 
0113     if (!dce110_timing_generator_validate_timing(
0114                     tg,
0115                     timing,
0116                     signal))
0117         return false;
0118 
0119 
0120     if (v_blank < tg110->min_v_blank    ||
0121          timing->h_sync_width  < tg110->min_h_sync_width ||
0122          timing->v_sync_width  < tg110->min_v_sync_width)
0123         return false;
0124 
0125     return true;
0126 }
0127 
0128 static bool dce120_tg_validate_timing(struct timing_generator *tg,
0129     const struct dc_crtc_timing *timing)
0130 {
0131     return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
0132 }
0133 
0134 /******** HW programming ************/
0135 /* Disable/Enable Timing Generator */
0136 static bool dce120_timing_generator_enable_crtc(struct timing_generator *tg)
0137 {
0138     enum bp_result result;
0139     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0140 
0141     /* Set MASTER_UPDATE_MODE to 0
0142      * This is needed for DRR, and also suggested to be default value by Syed.*/
0143 
0144     CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE,
0145             MASTER_UPDATE_MODE, 0);
0146 
0147     CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK,
0148             UNDERFLOW_UPDATE_LOCK, 0);
0149 
0150     /* TODO API for AtomFirmware didn't change*/
0151     result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
0152 
0153     return result == BP_RESULT_OK;
0154 }
0155 
0156 static void dce120_timing_generator_set_early_control(
0157         struct timing_generator *tg,
0158         uint32_t early_cntl)
0159 {
0160     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0161 
0162     CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL,
0163             CRTC_HBLANK_EARLY_CONTROL, early_cntl);
0164 }
0165 
0166 /**************** TG current status ******************/
0167 
0168 /* return the current frame counter. Used by Linux kernel DRM */
0169 static uint32_t dce120_timing_generator_get_vblank_counter(
0170         struct timing_generator *tg)
0171 {
0172     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0173     uint32_t value = dm_read_reg_soc15(
0174                 tg->ctx,
0175                 mmCRTC0_CRTC_STATUS_FRAME_COUNT,
0176                 tg110->offsets.crtc);
0177     uint32_t field = get_reg_field_value(
0178                 value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
0179 
0180     return field;
0181 }
0182 
0183 /* Get current H and V position */
0184 static void dce120_timing_generator_get_crtc_position(
0185     struct timing_generator *tg,
0186     struct crtc_position *position)
0187 {
0188     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0189     uint32_t value = dm_read_reg_soc15(
0190                 tg->ctx,
0191                 mmCRTC0_CRTC_STATUS_POSITION,
0192                 tg110->offsets.crtc);
0193 
0194     position->horizontal_count = get_reg_field_value(value,
0195             CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
0196 
0197     position->vertical_count = get_reg_field_value(value,
0198             CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
0199 
0200     value = dm_read_reg_soc15(
0201                 tg->ctx,
0202                 mmCRTC0_CRTC_NOM_VERT_POSITION,
0203                 tg110->offsets.crtc);
0204 
0205     position->nominal_vcount = get_reg_field_value(value,
0206             CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
0207 }
0208 
0209 /* wait until TG is in beginning of vertical blank region */
0210 static void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg)
0211 {
0212     /* We want to catch beginning of VBlank here, so if the first try are
0213      * in VBlank, we might be very close to Active, in this case wait for
0214      * another frame
0215      */
0216     while (dce120_timing_generator_is_in_vertical_blank(tg)) {
0217         if (!tg->funcs->is_counter_moving(tg)) {
0218             /* error - no point to wait if counter is not moving */
0219             break;
0220         }
0221     }
0222 
0223     while (!dce120_timing_generator_is_in_vertical_blank(tg)) {
0224         if (!tg->funcs->is_counter_moving(tg)) {
0225             /* error - no point to wait if counter is not moving */
0226             break;
0227         }
0228     }
0229 }
0230 
0231 /* wait until TG is in beginning of active region */
0232 static void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg)
0233 {
0234     while (dce120_timing_generator_is_in_vertical_blank(tg)) {
0235         if (!tg->funcs->is_counter_moving(tg)) {
0236             /* error - no point to wait if counter is not moving */
0237             break;
0238         }
0239     }
0240 }
0241 
0242 /*********** Timing Generator Synchronization routines ****/
0243 
0244 /* Setups Global Swap Lock group, TimingServer or TimingClient*/
0245 static void dce120_timing_generator_setup_global_swap_lock(
0246     struct timing_generator *tg,
0247     const struct dcp_gsl_params *gsl_params)
0248 {
0249     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0250     uint32_t value_crtc_vtotal =
0251                             dm_read_reg_soc15(tg->ctx,
0252                             mmCRTC0_CRTC_V_TOTAL,
0253                             tg110->offsets.crtc);
0254     /* Checkpoint relative to end of frame */
0255     uint32_t check_point =
0256                             get_reg_field_value(value_crtc_vtotal,
0257                             CRTC0_CRTC_V_TOTAL,
0258                             CRTC_V_TOTAL);
0259 
0260 
0261     dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0);
0262 
0263     CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6,
0264         /* This pipe will belong to GSL Group zero. */
0265         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1,
0266         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst,
0267         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
0268         /* Keep signal low (pending high) during 6 lines.
0269          * Also defines minimum interval before re-checking signal. */
0270         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
0271         /* DCP_GSL_PURPOSE_SURFACE_FLIP */
0272         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
0273         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1);
0274 
0275     CRTC_REG_SET_2(
0276             CRTC0_CRTC_GSL_CONTROL,
0277             CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP,
0278             CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY);
0279 }
0280 
0281 /* Clear all the register writes done by setup_global_swap_lock */
0282 static void dce120_timing_generator_tear_down_global_swap_lock(
0283     struct timing_generator *tg)
0284 {
0285     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0286 
0287     /* Settig HW default values from reg specs */
0288     CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6,
0289             FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0,
0290             FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0,
0291             FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
0292             FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
0293             /* DCP_GSL_PURPOSE_SURFACE_FLIP */
0294             FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
0295             FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0);
0296 
0297     CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL,
0298                CRTC_GSL_CHECK_LINE_NUM, 0,
0299                CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/
0300 }
0301 
0302 /* Reset slave controllers on master VSync */
0303 static void dce120_timing_generator_enable_reset_trigger(
0304     struct timing_generator *tg,
0305     int source)
0306 {
0307     enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
0308     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0309     uint32_t rising_edge = 0;
0310     uint32_t falling_edge = 0;
0311     /* Setup trigger edge */
0312     uint32_t pol_value = dm_read_reg_soc15(
0313                                     tg->ctx,
0314                                     mmCRTC0_CRTC_V_SYNC_A_CNTL,
0315                                     tg110->offsets.crtc);
0316 
0317     /* Register spec has reversed definition:
0318      *  0 for positive, 1 for negative */
0319     if (get_reg_field_value(pol_value,
0320             CRTC0_CRTC_V_SYNC_A_CNTL,
0321             CRTC_V_SYNC_A_POL) == 0) {
0322         rising_edge = 1;
0323     } else {
0324         falling_edge = 1;
0325     }
0326 
0327     /* TODO What about other sources ?*/
0328     trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
0329 
0330     CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7,
0331         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select,
0332         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
0333         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge,
0334         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge,
0335         /* send every signal */
0336         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0,
0337         /* no delay */
0338         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0,
0339         /* clear trigger status */
0340         FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1);
0341 
0342     CRTC_REG_UPDATE_3(
0343             CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0344             CRTC_FORCE_COUNT_NOW_MODE, 2,
0345             CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1,
0346             CRTC_FORCE_COUNT_NOW_CLEAR, 1);
0347 }
0348 
0349 /* disabling trigger-reset */
0350 static void dce120_timing_generator_disable_reset_trigger(
0351     struct timing_generator *tg)
0352 {
0353     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0354 
0355     CRTC_REG_UPDATE_2(
0356         CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0357         CRTC_FORCE_COUNT_NOW_MODE, 0,
0358         CRTC_FORCE_COUNT_NOW_CLEAR, 1);
0359 
0360     CRTC_REG_UPDATE_3(
0361         CRTC0_CRTC_TRIGB_CNTL,
0362         CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
0363         CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
0364         /* clear trigger status */
0365         CRTC_TRIGB_CLEAR, 1);
0366 
0367 }
0368 
0369 /* Checks whether CRTC triggered reset occurred */
0370 static bool dce120_timing_generator_did_triggered_reset_occur(
0371     struct timing_generator *tg)
0372 {
0373     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0374     uint32_t value = dm_read_reg_soc15(
0375             tg->ctx,
0376             mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0377             tg110->offsets.crtc);
0378 
0379     return get_reg_field_value(value,
0380             CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
0381             CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
0382 }
0383 
0384 
0385 /******** Stuff to move to other virtual HW objects *****************/
0386 /* Move to enable accelerated mode */
0387 static void dce120_timing_generator_disable_vga(struct timing_generator *tg)
0388 {
0389     uint32_t offset = 0;
0390     uint32_t value = 0;
0391     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0392 
0393     switch (tg110->controller_id) {
0394     case CONTROLLER_ID_D0:
0395         offset = 0;
0396         break;
0397     case CONTROLLER_ID_D1:
0398         offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL;
0399         break;
0400     case CONTROLLER_ID_D2:
0401         offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL;
0402         break;
0403     case CONTROLLER_ID_D3:
0404         offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL;
0405         break;
0406     case CONTROLLER_ID_D4:
0407         offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL;
0408         break;
0409     case CONTROLLER_ID_D5:
0410         offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL;
0411         break;
0412     default:
0413         break;
0414     }
0415 
0416     value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset);
0417 
0418     set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
0419     set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
0420     set_reg_field_value(
0421             value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
0422     set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
0423 
0424     dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value);
0425 }
0426 /* TODO: Should we move it to transform */
0427 /* Fully program CRTC timing in timing generator */
0428 static void dce120_timing_generator_program_blanking(
0429     struct timing_generator *tg,
0430     const struct dc_crtc_timing *timing)
0431 {
0432     uint32_t tmp1 = 0;
0433     uint32_t tmp2 = 0;
0434     uint32_t vsync_offset = timing->v_border_bottom +
0435             timing->v_front_porch;
0436     uint32_t v_sync_start = timing->v_addressable + vsync_offset;
0437 
0438     uint32_t hsync_offset = timing->h_border_right +
0439             timing->h_front_porch;
0440     uint32_t h_sync_start = timing->h_addressable + hsync_offset;
0441     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0442 
0443     CRTC_REG_UPDATE(
0444         CRTC0_CRTC_H_TOTAL,
0445         CRTC_H_TOTAL,
0446         timing->h_total - 1);
0447 
0448     CRTC_REG_UPDATE(
0449         CRTC0_CRTC_V_TOTAL,
0450         CRTC_V_TOTAL,
0451         timing->v_total - 1);
0452 
0453     /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
0454      * V_TOTAL_MIN are equal to V_TOTAL.
0455      */
0456     CRTC_REG_UPDATE(
0457         CRTC0_CRTC_V_TOTAL_MAX,
0458         CRTC_V_TOTAL_MAX,
0459         timing->v_total - 1);
0460 
0461     CRTC_REG_UPDATE(
0462         CRTC0_CRTC_V_TOTAL_MIN,
0463         CRTC_V_TOTAL_MIN,
0464         timing->v_total - 1);
0465 
0466     tmp1 = timing->h_total -
0467             (h_sync_start + timing->h_border_left);
0468     tmp2 = tmp1 + timing->h_addressable +
0469             timing->h_border_left + timing->h_border_right;
0470 
0471     CRTC_REG_UPDATE_2(
0472             CRTC0_CRTC_H_BLANK_START_END,
0473             CRTC_H_BLANK_END, tmp1,
0474             CRTC_H_BLANK_START, tmp2);
0475 
0476     tmp1 = timing->v_total - (v_sync_start + timing->v_border_top);
0477     tmp2 = tmp1 + timing->v_addressable + timing->v_border_top +
0478             timing->v_border_bottom;
0479 
0480     CRTC_REG_UPDATE_2(
0481         CRTC0_CRTC_V_BLANK_START_END,
0482         CRTC_V_BLANK_END, tmp1,
0483         CRTC_V_BLANK_START, tmp2);
0484 }
0485 
0486 /* TODO: Should we move it to opp? */
0487 /* Combine with below and move YUV/RGB color conversion to SW layer */
0488 static void dce120_timing_generator_program_blank_color(
0489     struct timing_generator *tg,
0490     const struct tg_color *black_color)
0491 {
0492     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0493 
0494     CRTC_REG_UPDATE_3(
0495         CRTC0_CRTC_BLACK_COLOR,
0496         CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
0497         CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
0498         CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
0499 }
0500 /* Combine with above and move YUV/RGB color conversion to SW layer */
0501 static void dce120_timing_generator_set_overscan_color_black(
0502     struct timing_generator *tg,
0503     const struct tg_color *color)
0504 {
0505     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0506     uint32_t value = 0;
0507     CRTC_REG_SET_3(
0508         CRTC0_CRTC_OVERSCAN_COLOR,
0509         CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb,
0510         CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y,
0511         CRTC_OVERSCAN_COLOR_RED, color->color_r_cr);
0512 
0513     value = dm_read_reg_soc15(
0514             tg->ctx,
0515             mmCRTC0_CRTC_OVERSCAN_COLOR,
0516             tg110->offsets.crtc);
0517 
0518     dm_write_reg_soc15(
0519             tg->ctx,
0520             mmCRTC0_CRTC_BLACK_COLOR,
0521             tg110->offsets.crtc,
0522             value);
0523 
0524     /* This is desirable to have a constant DAC output voltage during the
0525      * blank time that is higher than the 0 volt reference level that the
0526      * DAC outputs when the NBLANK signal
0527      * is asserted low, such as for output to an analog TV. */
0528     dm_write_reg_soc15(
0529         tg->ctx,
0530         mmCRTC0_CRTC_BLANK_DATA_COLOR,
0531         tg110->offsets.crtc,
0532         value);
0533 
0534     /* TO DO we have to program EXT registers and we need to know LB DATA
0535      * format because it is used when more 10 , i.e. 12 bits per color
0536      *
0537      * m_mmDxCRTC_OVERSCAN_COLOR_EXT
0538      * m_mmDxCRTC_BLACK_COLOR_EXT
0539      * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
0540      */
0541 }
0542 
0543 static void dce120_timing_generator_set_drr(
0544     struct timing_generator *tg,
0545     const struct drr_params *params)
0546 {
0547 
0548     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0549 
0550     if (params != NULL &&
0551         params->vertical_total_max > 0 &&
0552         params->vertical_total_min > 0) {
0553 
0554         CRTC_REG_UPDATE(
0555                 CRTC0_CRTC_V_TOTAL_MIN,
0556                 CRTC_V_TOTAL_MIN, params->vertical_total_min - 1);
0557         CRTC_REG_UPDATE(
0558                 CRTC0_CRTC_V_TOTAL_MAX,
0559                 CRTC_V_TOTAL_MAX, params->vertical_total_max - 1);
0560         CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6,
0561                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1,
0562                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1,
0563                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
0564                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
0565                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0,
0566                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
0567         CRTC_REG_UPDATE(
0568                 CRTC0_CRTC_STATIC_SCREEN_CONTROL,
0569                 CRTC_STATIC_SCREEN_EVENT_MASK,
0570                 0x180);
0571 
0572     } else {
0573         CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
0574                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
0575                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
0576                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
0577                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
0578                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
0579         CRTC_REG_UPDATE(
0580                 CRTC0_CRTC_V_TOTAL_MIN,
0581                 CRTC_V_TOTAL_MIN, 0);
0582         CRTC_REG_UPDATE(
0583                 CRTC0_CRTC_V_TOTAL_MAX,
0584                 CRTC_V_TOTAL_MAX, 0);
0585         CRTC_REG_UPDATE(
0586                 CRTC0_CRTC_STATIC_SCREEN_CONTROL,
0587                 CRTC_STATIC_SCREEN_EVENT_MASK,
0588                 0);
0589     }
0590 }
0591 
0592 static void dce120_timing_generator_get_crtc_scanoutpos(
0593     struct timing_generator *tg,
0594     uint32_t *v_blank_start,
0595     uint32_t *v_blank_end,
0596     uint32_t *h_position,
0597     uint32_t *v_position)
0598 {
0599     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0600     struct crtc_position position;
0601 
0602     uint32_t v_blank_start_end = dm_read_reg_soc15(
0603             tg->ctx,
0604             mmCRTC0_CRTC_V_BLANK_START_END,
0605             tg110->offsets.crtc);
0606 
0607     *v_blank_start = get_reg_field_value(v_blank_start_end,
0608                          CRTC0_CRTC_V_BLANK_START_END,
0609                          CRTC_V_BLANK_START);
0610     *v_blank_end = get_reg_field_value(v_blank_start_end,
0611                        CRTC0_CRTC_V_BLANK_START_END,
0612                        CRTC_V_BLANK_END);
0613 
0614     dce120_timing_generator_get_crtc_position(
0615             tg, &position);
0616 
0617     *h_position = position.horizontal_count;
0618     *v_position = position.vertical_count;
0619 }
0620 
0621 static void dce120_timing_generator_enable_advanced_request(
0622     struct timing_generator *tg,
0623     bool enable,
0624     const struct dc_crtc_timing *timing)
0625 {
0626     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0627     uint32_t v_sync_width_and_b_porch =
0628                 timing->v_total - timing->v_addressable -
0629                 timing->v_border_bottom - timing->v_front_porch;
0630     uint32_t value = dm_read_reg_soc15(
0631                 tg->ctx,
0632                 mmCRTC0_CRTC_START_LINE_CONTROL,
0633                 tg110->offsets.crtc);
0634 
0635     set_reg_field_value(
0636         value,
0637         enable ? 0 : 1,
0638         CRTC0_CRTC_START_LINE_CONTROL,
0639         CRTC_LEGACY_REQUESTOR_EN);
0640 
0641     /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency
0642      * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines)
0643      */
0644     if (v_sync_width_and_b_porch > 10)
0645         v_sync_width_and_b_porch = 10;
0646 
0647     set_reg_field_value(
0648         value,
0649         v_sync_width_and_b_porch,
0650         CRTC0_CRTC_START_LINE_CONTROL,
0651         CRTC_ADVANCED_START_LINE_POSITION);
0652 
0653     dm_write_reg_soc15(tg->ctx,
0654             mmCRTC0_CRTC_START_LINE_CONTROL,
0655             tg110->offsets.crtc,
0656             value);
0657 }
0658 
0659 static void dce120_tg_program_blank_color(struct timing_generator *tg,
0660     const struct tg_color *black_color)
0661 {
0662     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0663     uint32_t value = 0;
0664 
0665     CRTC_REG_UPDATE_3(
0666         CRTC0_CRTC_BLACK_COLOR,
0667         CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
0668         CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
0669         CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
0670 
0671     value = dm_read_reg_soc15(
0672                 tg->ctx,
0673                 mmCRTC0_CRTC_BLACK_COLOR,
0674                 tg110->offsets.crtc);
0675     dm_write_reg_soc15(
0676         tg->ctx,
0677         mmCRTC0_CRTC_BLANK_DATA_COLOR,
0678         tg110->offsets.crtc,
0679         value);
0680 }
0681 
0682 static void dce120_tg_set_overscan_color(struct timing_generator *tg,
0683     const struct tg_color *overscan_color)
0684 {
0685     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0686 
0687     CRTC_REG_SET_3(
0688         CRTC0_CRTC_OVERSCAN_COLOR,
0689         CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
0690         CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
0691         CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
0692 }
0693 
0694 static void dce120_tg_program_timing(struct timing_generator *tg,
0695     const struct dc_crtc_timing *timing,
0696     int vready_offset,
0697     int vstartup_start,
0698     int vupdate_offset,
0699     int vupdate_width,
0700     const enum signal_type signal,
0701     bool use_vbios)
0702 {
0703     if (use_vbios)
0704         dce110_timing_generator_program_timing_generator(tg, timing);
0705     else
0706         dce120_timing_generator_program_blanking(tg, timing);
0707 }
0708 
0709 static bool dce120_tg_is_blanked(struct timing_generator *tg)
0710 {
0711     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0712     uint32_t value = dm_read_reg_soc15(
0713             tg->ctx,
0714             mmCRTC0_CRTC_BLANK_CONTROL,
0715             tg110->offsets.crtc);
0716 
0717     if (get_reg_field_value(
0718         value,
0719         CRTC0_CRTC_BLANK_CONTROL,
0720         CRTC_BLANK_DATA_EN) == 1 &&
0721         get_reg_field_value(
0722         value,
0723         CRTC0_CRTC_BLANK_CONTROL,
0724         CRTC_CURRENT_BLANK_STATE) == 1)
0725             return true;
0726 
0727     return false;
0728 }
0729 
0730 static void dce120_tg_set_blank(struct timing_generator *tg,
0731         bool enable_blanking)
0732 {
0733     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0734 
0735     CRTC_REG_SET(
0736         CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
0737         CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
0738 
0739     if (enable_blanking)
0740         CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
0741     else
0742         dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
0743             tg110->offsets.crtc, 0);
0744 }
0745 
0746 bool dce120_tg_validate_timing(struct timing_generator *tg,
0747     const struct dc_crtc_timing *timing);
0748 
0749 static void dce120_tg_wait_for_state(struct timing_generator *tg,
0750     enum crtc_state state)
0751 {
0752     switch (state) {
0753     case CRTC_STATE_VBLANK:
0754         dce120_timing_generator_wait_for_vblank(tg);
0755         break;
0756 
0757     case CRTC_STATE_VACTIVE:
0758         dce120_timing_generator_wait_for_vactive(tg);
0759         break;
0760 
0761     default:
0762         break;
0763     }
0764 }
0765 
0766 static void dce120_tg_set_colors(struct timing_generator *tg,
0767     const struct tg_color *blank_color,
0768     const struct tg_color *overscan_color)
0769 {
0770     if (blank_color != NULL)
0771         dce120_tg_program_blank_color(tg, blank_color);
0772 
0773     if (overscan_color != NULL)
0774         dce120_tg_set_overscan_color(tg, overscan_color);
0775 }
0776 
0777 static void dce120_timing_generator_set_static_screen_control(
0778     struct timing_generator *tg,
0779     uint32_t event_triggers,
0780     uint32_t num_frames)
0781 {
0782     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0783 
0784     // By register spec, it only takes 8 bit value
0785     if (num_frames > 0xFF)
0786         num_frames = 0xFF;
0787 
0788     CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
0789             CRTC_STATIC_SCREEN_EVENT_MASK, event_triggers,
0790             CRTC_STATIC_SCREEN_FRAME_COUNT, num_frames);
0791 }
0792 
0793 static void dce120_timing_generator_set_test_pattern(
0794     struct timing_generator *tg,
0795     /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
0796      * because this is not DP-specific (which is probably somewhere in DP
0797      * encoder) */
0798     enum controller_dp_test_pattern test_pattern,
0799     enum dc_color_depth color_depth)
0800 {
0801     struct dc_context *ctx = tg->ctx;
0802     uint32_t value;
0803     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
0804     enum test_pattern_color_format bit_depth;
0805     enum test_pattern_dyn_range dyn_range;
0806     enum test_pattern_mode mode;
0807     /* color ramp generator mixes 16-bits color */
0808     uint32_t src_bpc = 16;
0809     /* requested bpc */
0810     uint32_t dst_bpc;
0811     uint32_t index;
0812     /* RGB values of the color bars.
0813      * Produce two RGB colors: RGB0 - white (all Fs)
0814      * and RGB1 - black (all 0s)
0815      * (three RGB components for two colors)
0816      */
0817     uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
0818                         0x0000, 0x0000};
0819     /* dest color (converted to the specified color format) */
0820     uint16_t dst_color[6];
0821     uint32_t inc_base;
0822 
0823     /* translate to bit depth */
0824     switch (color_depth) {
0825     case COLOR_DEPTH_666:
0826         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
0827     break;
0828     case COLOR_DEPTH_888:
0829         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0830     break;
0831     case COLOR_DEPTH_101010:
0832         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
0833     break;
0834     case COLOR_DEPTH_121212:
0835         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
0836     break;
0837     default:
0838         bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
0839     break;
0840     }
0841 
0842     switch (test_pattern) {
0843     case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
0844     case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
0845     {
0846         dyn_range = (test_pattern ==
0847                 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
0848                 TEST_PATTERN_DYN_RANGE_CEA :
0849                 TEST_PATTERN_DYN_RANGE_VESA);
0850         mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
0851 
0852         CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
0853                 CRTC_TEST_PATTERN_VRES, 6,
0854                 CRTC_TEST_PATTERN_HRES, 6);
0855 
0856         CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
0857                 CRTC_TEST_PATTERN_EN, 1,
0858                 CRTC_TEST_PATTERN_MODE, mode,
0859                 CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
0860                 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
0861     }
0862     break;
0863 
0864     case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
0865     case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
0866     {
0867         mode = (test_pattern ==
0868             CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
0869             TEST_PATTERN_MODE_VERTICALBARS :
0870             TEST_PATTERN_MODE_HORIZONTALBARS);
0871 
0872         switch (bit_depth) {
0873         case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0874             dst_bpc = 6;
0875         break;
0876         case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0877             dst_bpc = 8;
0878         break;
0879         case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0880             dst_bpc = 10;
0881         break;
0882         default:
0883             dst_bpc = 8;
0884         break;
0885         }
0886 
0887         /* adjust color to the required colorFormat */
0888         for (index = 0; index < 6; index++) {
0889             /* dst = 2^dstBpc * src / 2^srcBpc = src >>
0890              * (srcBpc - dstBpc);
0891              */
0892             dst_color[index] =
0893                 src_color[index] >> (src_bpc - dst_bpc);
0894         /* CRTC_TEST_PATTERN_DATA has 16 bits,
0895          * lowest 6 are hardwired to ZERO
0896          * color bits should be left aligned aligned to MSB
0897          * XXXXXXXXXX000000 for 10 bit,
0898          * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
0899          */
0900             dst_color[index] <<= (16 - dst_bpc);
0901         }
0902 
0903         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
0904 
0905         /* We have to write the mask before data, similar to pipeline.
0906          * For example, for 8 bpc, if we want RGB0 to be magenta,
0907          * and RGB1 to be cyan,
0908          * we need to make 7 writes:
0909          * MASK   DATA
0910          * 000001 00000000 00000000                     set mask to R0
0911          * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
0912          * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
0913          * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
0914          * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
0915          * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
0916          * 100000 11111111 00000000     B1 255, 0xFF00
0917          *
0918          * we will make a loop of 6 in which we prepare the mask,
0919          * then write, then prepare the color for next write.
0920          * first iteration will write mask only,
0921          * but each next iteration color prepared in
0922          * previous iteration will be written within new mask,
0923          * the last component will written separately,
0924          * mask is not changing between 6th and 7th write
0925          * and color will be prepared by last iteration
0926          */
0927 
0928         /* write color, color values mask in CRTC_TEST_PATTERN_MASK
0929          * is B1, G1, R1, B0, G0, R0
0930          */
0931         value = 0;
0932         for (index = 0; index < 6; index++) {
0933             /* prepare color mask, first write PATTERN_DATA
0934              * will have all zeros
0935              */
0936             set_reg_field_value(
0937                 value,
0938                 (1 << index),
0939                 CRTC0_CRTC_TEST_PATTERN_COLOR,
0940                 CRTC_TEST_PATTERN_MASK);
0941             /* write color component */
0942             dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
0943             /* prepare next color component,
0944              * will be written in the next iteration
0945              */
0946             set_reg_field_value(
0947                 value,
0948                 dst_color[index],
0949                 CRTC0_CRTC_TEST_PATTERN_COLOR,
0950                 CRTC_TEST_PATTERN_DATA);
0951         }
0952         /* write last color component,
0953          * it's been already prepared in the loop
0954          */
0955         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
0956 
0957         /* enable test pattern */
0958         CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
0959                 CRTC_TEST_PATTERN_EN, 1,
0960                 CRTC_TEST_PATTERN_MODE, mode,
0961                 CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
0962                 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
0963     }
0964     break;
0965 
0966     case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
0967     {
0968         mode = (bit_depth ==
0969             TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
0970             TEST_PATTERN_MODE_DUALRAMP_RGB :
0971             TEST_PATTERN_MODE_SINGLERAMP_RGB);
0972 
0973         switch (bit_depth) {
0974         case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0975             dst_bpc = 6;
0976         break;
0977         case TEST_PATTERN_COLOR_FORMAT_BPC_8:
0978             dst_bpc = 8;
0979         break;
0980         case TEST_PATTERN_COLOR_FORMAT_BPC_10:
0981             dst_bpc = 10;
0982         break;
0983         default:
0984             dst_bpc = 8;
0985         break;
0986         }
0987 
0988         /* increment for the first ramp for one color gradation
0989          * 1 gradation for 6-bit color is 2^10
0990          * gradations in 16-bit color
0991          */
0992         inc_base = (src_bpc - dst_bpc);
0993 
0994         switch (bit_depth) {
0995         case TEST_PATTERN_COLOR_FORMAT_BPC_6:
0996         {
0997             CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
0998                     CRTC_TEST_PATTERN_INC0, inc_base,
0999                     CRTC_TEST_PATTERN_INC1, 0,
1000                     CRTC_TEST_PATTERN_HRES, 6,
1001                     CRTC_TEST_PATTERN_VRES, 6,
1002                     CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1003         }
1004         break;
1005         case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1006         {
1007             CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1008                     CRTC_TEST_PATTERN_INC0, inc_base,
1009                     CRTC_TEST_PATTERN_INC1, 0,
1010                     CRTC_TEST_PATTERN_HRES, 8,
1011                     CRTC_TEST_PATTERN_VRES, 6,
1012                     CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1013         }
1014         break;
1015         case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1016         {
1017             CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1018                     CRTC_TEST_PATTERN_INC0, inc_base,
1019                     CRTC_TEST_PATTERN_INC1, inc_base + 2,
1020                     CRTC_TEST_PATTERN_HRES, 8,
1021                     CRTC_TEST_PATTERN_VRES, 5,
1022                     CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1023         }
1024         break;
1025         default:
1026         break;
1027         }
1028 
1029         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1030 
1031         /* enable test pattern */
1032         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1033 
1034         CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1035                 CRTC_TEST_PATTERN_EN, 1,
1036                 CRTC_TEST_PATTERN_MODE, mode,
1037                 CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1038                 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1039     }
1040     break;
1041     case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1042     {
1043         value = 0;
1044         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1045         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1046         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1047     }
1048     break;
1049     default:
1050     break;
1051     }
1052 }
1053 
1054 static bool dce120_arm_vert_intr(
1055         struct timing_generator *tg,
1056         uint8_t width)
1057 {
1058     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1059     uint32_t v_blank_start, v_blank_end, h_position, v_position;
1060 
1061     tg->funcs->get_scanoutpos(
1062                 tg,
1063                 &v_blank_start,
1064                 &v_blank_end,
1065                 &h_position,
1066                 &v_position);
1067 
1068     if (v_blank_start == 0 || v_blank_end == 0)
1069         return false;
1070 
1071     CRTC_REG_SET_2(
1072             CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1073             CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1074             CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1075 
1076     return true;
1077 }
1078 
1079 
1080 static bool dce120_is_tg_enabled(struct timing_generator *tg)
1081 {
1082     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1083     uint32_t value, field;
1084 
1085     value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1086                   tg110->offsets.crtc);
1087     field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1088                     CRTC_CURRENT_MASTER_EN_STATE);
1089 
1090     return field == 1;
1091 }
1092 
1093 static bool dce120_configure_crc(struct timing_generator *tg,
1094                  const struct crc_params *params)
1095 {
1096     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1097 
1098     /* Cannot configure crc on a CRTC that is disabled */
1099     if (!dce120_is_tg_enabled(tg))
1100         return false;
1101 
1102     /* First, disable CRC before we configure it. */
1103     dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1104                tg110->offsets.crtc, 0);
1105 
1106     if (!params->enable)
1107         return true;
1108 
1109     /* Program frame boundaries */
1110     /* Window A x axis start and end. */
1111     CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1112               CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1113               CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1114 
1115     /* Window A y axis start and end. */
1116     CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1117               CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1118               CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1119 
1120     /* Window B x axis start and end. */
1121     CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1122               CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1123               CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1124 
1125     /* Window B y axis start and end. */
1126     CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1127               CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1128               CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1129 
1130     /* Set crc mode and selection, and enable. Only using CRC0*/
1131     CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1132               CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
1133               CRTC_CRC0_SELECT, params->selection,
1134               CRTC_CRC_EN, 1);
1135 
1136     return true;
1137 }
1138 
1139 static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
1140                uint32_t *g_y, uint32_t *b_cb)
1141 {
1142     struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1143     uint32_t value, field;
1144 
1145     value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1146                   tg110->offsets.crtc);
1147     field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1148 
1149     /* Early return if CRC is not enabled for this CRTC */
1150     if (!field)
1151         return false;
1152 
1153     value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1154                   tg110->offsets.crtc);
1155     *r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1156     *g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1157 
1158     value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1159                   tg110->offsets.crtc);
1160     *b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1161 
1162     return true;
1163 }
1164 
1165 static const struct timing_generator_funcs dce120_tg_funcs = {
1166         .validate_timing = dce120_tg_validate_timing,
1167         .program_timing = dce120_tg_program_timing,
1168         .enable_crtc = dce120_timing_generator_enable_crtc,
1169         .disable_crtc = dce110_timing_generator_disable_crtc,
1170         /* used by enable_timing_synchronization. Not need for FPGA */
1171         .is_counter_moving = dce110_timing_generator_is_counter_moving,
1172         /* never be called */
1173         .get_position = dce120_timing_generator_get_crtc_position,
1174         .get_frame_count = dce120_timing_generator_get_vblank_counter,
1175         .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1176         .set_early_control = dce120_timing_generator_set_early_control,
1177         /* used by enable_timing_synchronization. Not need for FPGA */
1178         .wait_for_state = dce120_tg_wait_for_state,
1179         .set_blank = dce120_tg_set_blank,
1180         .is_blanked = dce120_tg_is_blanked,
1181         /* never be called */
1182         .set_colors = dce120_tg_set_colors,
1183         .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1184         .set_blank_color = dce120_timing_generator_program_blank_color,
1185         .disable_vga = dce120_timing_generator_disable_vga,
1186         .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1187         .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1188         .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1189         .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1190         .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1191         .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1192         .set_drr = dce120_timing_generator_set_drr,
1193         .get_last_used_drr_vtotal = NULL,
1194         .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1195         .set_test_pattern = dce120_timing_generator_set_test_pattern,
1196         .arm_vert_intr = dce120_arm_vert_intr,
1197         .is_tg_enabled = dce120_is_tg_enabled,
1198         .configure_crc = dce120_configure_crc,
1199         .get_crc = dce120_get_crc,
1200 };
1201 
1202 
1203 void dce120_timing_generator_construct(
1204     struct dce110_timing_generator *tg110,
1205     struct dc_context *ctx,
1206     uint32_t instance,
1207     const struct dce110_timing_generator_offsets *offsets)
1208 {
1209     tg110->controller_id = CONTROLLER_ID_D0 + instance;
1210     tg110->base.inst = instance;
1211 
1212     tg110->offsets = *offsets;
1213 
1214     tg110->base.funcs = &dce120_tg_funcs;
1215 
1216     tg110->base.ctx = ctx;
1217     tg110->base.bp = ctx->dc_bios;
1218 
1219     tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1220     tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1221 
1222     /*//CRTC requires a minimum HBLANK = 32 pixels and o
1223      * Minimum HSYNC = 8 pixels*/
1224     tg110->min_h_blank = 32;
1225     /*DCE12_CRTC_Block_ARch.doc*/
1226     tg110->min_h_front_porch = 0;
1227     tg110->min_h_back_porch = 0;
1228 
1229     tg110->min_h_sync_width = 4;
1230     tg110->min_v_sync_width = 1;
1231     tg110->min_v_blank = 3;
1232 }