root/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dce120_timing_generator_is_in_vertical_blank
  2. dce120_timing_generator_validate_timing
  3. dce120_tg_validate_timing
  4. dce120_timing_generator_enable_crtc
  5. dce120_timing_generator_set_early_control
  6. dce120_timing_generator_get_vblank_counter
  7. dce120_timing_generator_get_crtc_position
  8. dce120_timing_generator_wait_for_vblank
  9. dce120_timing_generator_wait_for_vactive
  10. dce120_timing_generator_setup_global_swap_lock
  11. dce120_timing_generator_tear_down_global_swap_lock
  12. dce120_timing_generator_enable_reset_trigger
  13. dce120_timing_generator_disable_reset_trigger
  14. dce120_timing_generator_did_triggered_reset_occur
  15. dce120_timing_generator_disable_vga
  16. dce120_timing_generator_program_blanking
  17. dce120_timing_generator_program_blank_color
  18. dce120_timing_generator_set_overscan_color_black
  19. dce120_timing_generator_set_drr
  20. dce120_timing_generator_get_position
  21. dce120_timing_generator_get_crtc_scanoutpos
  22. dce120_timing_generator_enable_advanced_request
  23. dce120_tg_program_blank_color
  24. dce120_tg_set_overscan_color
  25. dce120_tg_program_timing
  26. dce120_tg_is_blanked
  27. dce120_tg_set_blank
  28. dce120_tg_wait_for_state
  29. dce120_tg_set_colors
  30. dce120_timing_generator_set_static_screen_control
  31. dce120_timing_generator_set_test_pattern
  32. dce120_arm_vert_intr
  33. dce120_is_tg_enabled
  34. dce120_configure_crc
  35. dce120_get_crc
  36. dce120_timing_generator_construct

   1 /*
   2  * Copyright 2012-15 Advanced Micro Devices, Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: AMD
  23  *
  24  */
  25 
  26 #include "dm_services.h"
  27 
  28 #include "dce/dce_12_0_offset.h"
  29 #include "dce/dce_12_0_sh_mask.h"
  30 #include "soc15_hw_ip.h"
  31 #include "vega10_ip_offset.h"
  32 
  33 #include "dc_types.h"
  34 #include "dc_bios_types.h"
  35 
  36 #include "include/grph_object_id.h"
  37 #include "include/logger_interface.h"
  38 #include "dce120_timing_generator.h"
  39 
  40 #include "timing_generator.h"
  41 
  42 #define CRTC_REG_UPDATE_N(reg_name, n, ...)     \
  43                 generic_reg_update_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
  44 
  45 #define CRTC_REG_SET_N(reg_name, n, ...)        \
  46                 generic_reg_set_soc15(tg110->base.ctx, tg110->offsets.crtc, reg_name, n, __VA_ARGS__)
  47 
  48 #define CRTC_REG_UPDATE(reg, field, val)        \
  49                 CRTC_REG_UPDATE_N(reg, 1, FD(reg##__##field), val)
  50 
  51 #define CRTC_REG_UPDATE_2(reg, field1, val1, field2, val2)      \
  52                 CRTC_REG_UPDATE_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
  53 
  54 #define CRTC_REG_UPDATE_3(reg, field1, val1, field2, val2, field3, val3)        \
  55                 CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
  56 
  57 #define CRTC_REG_UPDATE_4(reg, field1, val1, field2, val2, field3, val3, field4, val4)  \
  58                 CRTC_REG_UPDATE_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3, FD(reg##__##field4), val4)
  59 
  60 #define CRTC_REG_UPDATE_5(reg, field1, val1, field2, val2, field3, val3, field4, val4, field5, val5)    \
  61                 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)
  62 
  63 #define CRTC_REG_SET(reg, field, val)   \
  64                 CRTC_REG_SET_N(reg, 1, FD(reg##__##field), val)
  65 
  66 #define CRTC_REG_SET_2(reg, field1, val1, field2, val2) \
  67                 CRTC_REG_SET_N(reg, 2, FD(reg##__##field1), val1, FD(reg##__##field2), val2)
  68 
  69 #define CRTC_REG_SET_3(reg, field1, val1, field2, val2, field3, val3)   \
  70                 CRTC_REG_SET_N(reg, 3, FD(reg##__##field1), val1, FD(reg##__##field2), val2, FD(reg##__##field3), val3)
  71 
  72 /**
  73  *****************************************************************************
  74  *  Function: is_in_vertical_blank
  75  *
  76  *  @brief
  77  *     check the current status of CRTC to check if we are in Vertical Blank
  78  *     regioneased" state
  79  *
  80  *  @return
  81  *     true if currently in blank region, false otherwise
  82  *
  83  *****************************************************************************
  84  */
  85 static bool dce120_timing_generator_is_in_vertical_blank(
  86                 struct timing_generator *tg)
  87 {
  88         uint32_t field = 0;
  89         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
  90         uint32_t value = dm_read_reg_soc15(
  91                                         tg->ctx,
  92                                         mmCRTC0_CRTC_STATUS,
  93                                         tg110->offsets.crtc);
  94 
  95         field = get_reg_field_value(value, CRTC0_CRTC_STATUS, CRTC_V_BLANK);
  96         return field == 1;
  97 }
  98 
  99 
 100 /* determine if given timing can be supported by TG */
 101 bool dce120_timing_generator_validate_timing(
 102         struct timing_generator *tg,
 103         const struct dc_crtc_timing *timing,
 104         enum signal_type signal)
 105 {
 106         uint32_t interlace_factor = timing->flags.INTERLACE ? 2 : 1;
 107         uint32_t v_blank =
 108                                         (timing->v_total - timing->v_addressable -
 109                                         timing->v_border_top - timing->v_border_bottom) *
 110                                         interlace_factor;
 111         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 112 
 113         if (!dce110_timing_generator_validate_timing(
 114                                         tg,
 115                                         timing,
 116                                         signal))
 117                 return false;
 118 
 119 
 120         if (v_blank < tg110->min_v_blank        ||
 121                  timing->h_sync_width  < tg110->min_h_sync_width ||
 122                  timing->v_sync_width  < tg110->min_v_sync_width)
 123                 return false;
 124 
 125         return true;
 126 }
 127 
 128 bool dce120_tg_validate_timing(struct timing_generator *tg,
 129         const struct dc_crtc_timing *timing)
 130 {
 131         return dce120_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
 132 }
 133 
 134 /******** HW programming ************/
 135 /* Disable/Enable Timing Generator */
 136 bool dce120_timing_generator_enable_crtc(struct timing_generator *tg)
 137 {
 138         enum bp_result result;
 139         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 140 
 141         /* Set MASTER_UPDATE_MODE to 0
 142          * This is needed for DRR, and also suggested to be default value by Syed.*/
 143 
 144         CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_MODE,
 145                         MASTER_UPDATE_MODE, 0);
 146 
 147         CRTC_REG_UPDATE(CRTC0_CRTC_MASTER_UPDATE_LOCK,
 148                         UNDERFLOW_UPDATE_LOCK, 0);
 149 
 150         /* TODO API for AtomFirmware didn't change*/
 151         result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
 152 
 153         return result == BP_RESULT_OK;
 154 }
 155 
 156 void dce120_timing_generator_set_early_control(
 157                 struct timing_generator *tg,
 158                 uint32_t early_cntl)
 159 {
 160         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 161 
 162         CRTC_REG_UPDATE(CRTC0_CRTC_CONTROL,
 163                         CRTC_HBLANK_EARLY_CONTROL, early_cntl);
 164 }
 165 
 166 /**************** TG current status ******************/
 167 
 168 /* return the current frame counter. Used by Linux kernel DRM */
 169 uint32_t dce120_timing_generator_get_vblank_counter(
 170                 struct timing_generator *tg)
 171 {
 172         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 173         uint32_t value = dm_read_reg_soc15(
 174                                 tg->ctx,
 175                                 mmCRTC0_CRTC_STATUS_FRAME_COUNT,
 176                                 tg110->offsets.crtc);
 177         uint32_t field = get_reg_field_value(
 178                                 value, CRTC0_CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
 179 
 180         return field;
 181 }
 182 
 183 /* Get current H and V position */
 184 void dce120_timing_generator_get_crtc_position(
 185         struct timing_generator *tg,
 186         struct crtc_position *position)
 187 {
 188         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 189         uint32_t value = dm_read_reg_soc15(
 190                                 tg->ctx,
 191                                 mmCRTC0_CRTC_STATUS_POSITION,
 192                                 tg110->offsets.crtc);
 193 
 194         position->horizontal_count = get_reg_field_value(value,
 195                         CRTC0_CRTC_STATUS_POSITION, CRTC_HORZ_COUNT);
 196 
 197         position->vertical_count = get_reg_field_value(value,
 198                         CRTC0_CRTC_STATUS_POSITION, CRTC_VERT_COUNT);
 199 
 200         value = dm_read_reg_soc15(
 201                                 tg->ctx,
 202                                 mmCRTC0_CRTC_NOM_VERT_POSITION,
 203                                 tg110->offsets.crtc);
 204 
 205         position->nominal_vcount = get_reg_field_value(value,
 206                         CRTC0_CRTC_NOM_VERT_POSITION, CRTC_VERT_COUNT_NOM);
 207 }
 208 
 209 /* wait until TG is in beginning of vertical blank region */
 210 void dce120_timing_generator_wait_for_vblank(struct timing_generator *tg)
 211 {
 212         /* We want to catch beginning of VBlank here, so if the first try are
 213          * in VBlank, we might be very close to Active, in this case wait for
 214          * another frame
 215          */
 216         while (dce120_timing_generator_is_in_vertical_blank(tg)) {
 217                 if (!tg->funcs->is_counter_moving(tg)) {
 218                         /* error - no point to wait if counter is not moving */
 219                         break;
 220                 }
 221         }
 222 
 223         while (!dce120_timing_generator_is_in_vertical_blank(tg)) {
 224                 if (!tg->funcs->is_counter_moving(tg)) {
 225                         /* error - no point to wait if counter is not moving */
 226                         break;
 227                 }
 228         }
 229 }
 230 
 231 /* wait until TG is in beginning of active region */
 232 void dce120_timing_generator_wait_for_vactive(struct timing_generator *tg)
 233 {
 234         while (dce120_timing_generator_is_in_vertical_blank(tg)) {
 235                 if (!tg->funcs->is_counter_moving(tg)) {
 236                         /* error - no point to wait if counter is not moving */
 237                         break;
 238                 }
 239         }
 240 }
 241 
 242 /*********** Timing Generator Synchronization routines ****/
 243 
 244 /* Setups Global Swap Lock group, TimingServer or TimingClient*/
 245 void dce120_timing_generator_setup_global_swap_lock(
 246         struct timing_generator *tg,
 247         const struct dcp_gsl_params *gsl_params)
 248 {
 249         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 250         uint32_t value_crtc_vtotal =
 251                                                         dm_read_reg_soc15(tg->ctx,
 252                                                         mmCRTC0_CRTC_V_TOTAL,
 253                                                         tg110->offsets.crtc);
 254         /* Checkpoint relative to end of frame */
 255         uint32_t check_point =
 256                                                         get_reg_field_value(value_crtc_vtotal,
 257                                                         CRTC0_CRTC_V_TOTAL,
 258                                                         CRTC_V_TOTAL);
 259 
 260 
 261         dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_GSL_WINDOW, tg110->offsets.crtc, 0);
 262 
 263         CRTC_REG_UPDATE_N(DCP0_DCP_GSL_CONTROL, 6,
 264                 /* This pipe will belong to GSL Group zero. */
 265                 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 1,
 266                 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), gsl_params->gsl_master == tg->inst,
 267                 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
 268                 /* Keep signal low (pending high) during 6 lines.
 269                  * Also defines minimum interval before re-checking signal. */
 270                 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
 271                 /* DCP_GSL_PURPOSE_SURFACE_FLIP */
 272                 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
 273                 FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 1);
 274 
 275         CRTC_REG_SET_2(
 276                         CRTC0_CRTC_GSL_CONTROL,
 277                         CRTC_GSL_CHECK_LINE_NUM, check_point - FLIP_READY_BACK_LOOKUP,
 278                         CRTC_GSL_FORCE_DELAY, VFLIP_READY_DELAY);
 279 }
 280 
 281 /* Clear all the register writes done by setup_global_swap_lock */
 282 void dce120_timing_generator_tear_down_global_swap_lock(
 283         struct timing_generator *tg)
 284 {
 285         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 286 
 287         /* Settig HW default values from reg specs */
 288         CRTC_REG_SET_N(DCP0_DCP_GSL_CONTROL, 6,
 289                         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL0_EN), 0,
 290                         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_MASTER_EN), 0,
 291                         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY), HFLIP_READY_DELAY,
 292                         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY), HFLIP_CHECK_DELAY,
 293                         /* DCP_GSL_PURPOSE_SURFACE_FLIP */
 294                         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE), 0,
 295                         FD(DCP0_DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING), 0);
 296 
 297         CRTC_REG_SET_2(CRTC0_CRTC_GSL_CONTROL,
 298                        CRTC_GSL_CHECK_LINE_NUM, 0,
 299                        CRTC_GSL_FORCE_DELAY, 0x2); /*TODO Why this value here ?*/
 300 }
 301 
 302 /* Reset slave controllers on master VSync */
 303 void dce120_timing_generator_enable_reset_trigger(
 304         struct timing_generator *tg,
 305         int source)
 306 {
 307         enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
 308         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 309         uint32_t rising_edge = 0;
 310         uint32_t falling_edge = 0;
 311         /* Setup trigger edge */
 312         uint32_t pol_value = dm_read_reg_soc15(
 313                                                                         tg->ctx,
 314                                                                         mmCRTC0_CRTC_V_SYNC_A_CNTL,
 315                                                                         tg110->offsets.crtc);
 316 
 317         /* Register spec has reversed definition:
 318          *      0 for positive, 1 for negative */
 319         if (get_reg_field_value(pol_value,
 320                         CRTC0_CRTC_V_SYNC_A_CNTL,
 321                         CRTC_V_SYNC_A_POL) == 0) {
 322                 rising_edge = 1;
 323         } else {
 324                 falling_edge = 1;
 325         }
 326 
 327         /* TODO What about other sources ?*/
 328         trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
 329 
 330         CRTC_REG_UPDATE_N(CRTC0_CRTC_TRIGB_CNTL, 7,
 331                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT), trig_src_select,
 332                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT), TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
 333                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL), rising_edge,
 334                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL), falling_edge,
 335                 /* send every signal */
 336                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT), 0,
 337                 /* no delay */
 338                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY), 0,
 339                 /* clear trigger status */
 340                 FD(CRTC0_CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR), 1);
 341 
 342         CRTC_REG_UPDATE_3(
 343                         CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 344                         CRTC_FORCE_COUNT_NOW_MODE, 2,
 345                         CRTC_FORCE_COUNT_NOW_TRIG_SEL, 1,
 346                         CRTC_FORCE_COUNT_NOW_CLEAR, 1);
 347 }
 348 
 349 /* disabling trigger-reset */
 350 void dce120_timing_generator_disable_reset_trigger(
 351         struct timing_generator *tg)
 352 {
 353         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 354 
 355         CRTC_REG_UPDATE_2(
 356                 CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 357                 CRTC_FORCE_COUNT_NOW_MODE, 0,
 358                 CRTC_FORCE_COUNT_NOW_CLEAR, 1);
 359 
 360         CRTC_REG_UPDATE_3(
 361                 CRTC0_CRTC_TRIGB_CNTL,
 362                 CRTC_TRIGB_SOURCE_SELECT, TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
 363                 CRTC_TRIGB_POLARITY_SELECT, TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
 364                 /* clear trigger status */
 365                 CRTC_TRIGB_CLEAR, 1);
 366 
 367 }
 368 
 369 /* Checks whether CRTC triggered reset occurred */
 370 bool dce120_timing_generator_did_triggered_reset_occur(
 371         struct timing_generator *tg)
 372 {
 373         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 374         uint32_t value = dm_read_reg_soc15(
 375                         tg->ctx,
 376                         mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 377                         tg110->offsets.crtc);
 378 
 379         return get_reg_field_value(value,
 380                         CRTC0_CRTC_FORCE_COUNT_NOW_CNTL,
 381                         CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
 382 }
 383 
 384 
 385 /******** Stuff to move to other virtual HW objects *****************/
 386 /* Move to enable accelerated mode */
 387 void dce120_timing_generator_disable_vga(struct timing_generator *tg)
 388 {
 389         uint32_t offset = 0;
 390         uint32_t value = 0;
 391         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 392 
 393         switch (tg110->controller_id) {
 394         case CONTROLLER_ID_D0:
 395                 offset = 0;
 396                 break;
 397         case CONTROLLER_ID_D1:
 398                 offset = mmD2VGA_CONTROL - mmD1VGA_CONTROL;
 399                 break;
 400         case CONTROLLER_ID_D2:
 401                 offset = mmD3VGA_CONTROL - mmD1VGA_CONTROL;
 402                 break;
 403         case CONTROLLER_ID_D3:
 404                 offset = mmD4VGA_CONTROL - mmD1VGA_CONTROL;
 405                 break;
 406         case CONTROLLER_ID_D4:
 407                 offset = mmD5VGA_CONTROL - mmD1VGA_CONTROL;
 408                 break;
 409         case CONTROLLER_ID_D5:
 410                 offset = mmD6VGA_CONTROL - mmD1VGA_CONTROL;
 411                 break;
 412         default:
 413                 break;
 414         }
 415 
 416         value = dm_read_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset);
 417 
 418         set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
 419         set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
 420         set_reg_field_value(
 421                         value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
 422         set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
 423 
 424         dm_write_reg_soc15(tg->ctx, mmD1VGA_CONTROL, offset, value);
 425 }
 426 /* TODO: Should we move it to transform */
 427 /* Fully program CRTC timing in timing generator */
 428 void dce120_timing_generator_program_blanking(
 429         struct timing_generator *tg,
 430         const struct dc_crtc_timing *timing)
 431 {
 432         uint32_t tmp1 = 0;
 433         uint32_t tmp2 = 0;
 434         uint32_t vsync_offset = timing->v_border_bottom +
 435                         timing->v_front_porch;
 436         uint32_t v_sync_start = timing->v_addressable + vsync_offset;
 437 
 438         uint32_t hsync_offset = timing->h_border_right +
 439                         timing->h_front_porch;
 440         uint32_t h_sync_start = timing->h_addressable + hsync_offset;
 441         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 442 
 443         CRTC_REG_UPDATE(
 444                 CRTC0_CRTC_H_TOTAL,
 445                 CRTC_H_TOTAL,
 446                 timing->h_total - 1);
 447 
 448         CRTC_REG_UPDATE(
 449                 CRTC0_CRTC_V_TOTAL,
 450                 CRTC_V_TOTAL,
 451                 timing->v_total - 1);
 452 
 453         /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
 454          * V_TOTAL_MIN are equal to V_TOTAL.
 455          */
 456         CRTC_REG_UPDATE(
 457                 CRTC0_CRTC_V_TOTAL_MAX,
 458                 CRTC_V_TOTAL_MAX,
 459                 timing->v_total - 1);
 460 
 461         CRTC_REG_UPDATE(
 462                 CRTC0_CRTC_V_TOTAL_MIN,
 463                 CRTC_V_TOTAL_MIN,
 464                 timing->v_total - 1);
 465 
 466         tmp1 = timing->h_total -
 467                         (h_sync_start + timing->h_border_left);
 468         tmp2 = tmp1 + timing->h_addressable +
 469                         timing->h_border_left + timing->h_border_right;
 470 
 471         CRTC_REG_UPDATE_2(
 472                         CRTC0_CRTC_H_BLANK_START_END,
 473                         CRTC_H_BLANK_END, tmp1,
 474                         CRTC_H_BLANK_START, tmp2);
 475 
 476         tmp1 = timing->v_total - (v_sync_start + timing->v_border_top);
 477         tmp2 = tmp1 + timing->v_addressable + timing->v_border_top +
 478                         timing->v_border_bottom;
 479 
 480         CRTC_REG_UPDATE_2(
 481                 CRTC0_CRTC_V_BLANK_START_END,
 482                 CRTC_V_BLANK_END, tmp1,
 483                 CRTC_V_BLANK_START, tmp2);
 484 }
 485 
 486 /* TODO: Should we move it to opp? */
 487 /* Combine with below and move YUV/RGB color conversion to SW layer */
 488 void dce120_timing_generator_program_blank_color(
 489         struct timing_generator *tg,
 490         const struct tg_color *black_color)
 491 {
 492         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 493 
 494         CRTC_REG_UPDATE_3(
 495                 CRTC0_CRTC_BLACK_COLOR,
 496                 CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 497                 CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 498                 CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 499 }
 500 /* Combine with above and move YUV/RGB color conversion to SW layer */
 501 void dce120_timing_generator_set_overscan_color_black(
 502         struct timing_generator *tg,
 503         const struct tg_color *color)
 504 {
 505         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 506         uint32_t value = 0;
 507         CRTC_REG_SET_3(
 508                 CRTC0_CRTC_OVERSCAN_COLOR,
 509                 CRTC_OVERSCAN_COLOR_BLUE, color->color_b_cb,
 510                 CRTC_OVERSCAN_COLOR_GREEN, color->color_g_y,
 511                 CRTC_OVERSCAN_COLOR_RED, color->color_r_cr);
 512 
 513         value = dm_read_reg_soc15(
 514                         tg->ctx,
 515                         mmCRTC0_CRTC_OVERSCAN_COLOR,
 516                         tg110->offsets.crtc);
 517 
 518         dm_write_reg_soc15(
 519                         tg->ctx,
 520                         mmCRTC0_CRTC_BLACK_COLOR,
 521                         tg110->offsets.crtc,
 522                         value);
 523 
 524         /* This is desirable to have a constant DAC output voltage during the
 525          * blank time that is higher than the 0 volt reference level that the
 526          * DAC outputs when the NBLANK signal
 527          * is asserted low, such as for output to an analog TV. */
 528         dm_write_reg_soc15(
 529                 tg->ctx,
 530                 mmCRTC0_CRTC_BLANK_DATA_COLOR,
 531                 tg110->offsets.crtc,
 532                 value);
 533 
 534         /* TO DO we have to program EXT registers and we need to know LB DATA
 535          * format because it is used when more 10 , i.e. 12 bits per color
 536          *
 537          * m_mmDxCRTC_OVERSCAN_COLOR_EXT
 538          * m_mmDxCRTC_BLACK_COLOR_EXT
 539          * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
 540          */
 541 }
 542 
 543 void dce120_timing_generator_set_drr(
 544         struct timing_generator *tg,
 545         const struct drr_params *params)
 546 {
 547 
 548         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 549 
 550         if (params != NULL &&
 551                 params->vertical_total_max > 0 &&
 552                 params->vertical_total_min > 0) {
 553 
 554                 CRTC_REG_UPDATE(
 555                                 CRTC0_CRTC_V_TOTAL_MIN,
 556                                 CRTC_V_TOTAL_MIN, params->vertical_total_min - 1);
 557                 CRTC_REG_UPDATE(
 558                                 CRTC0_CRTC_V_TOTAL_MAX,
 559                                 CRTC_V_TOTAL_MAX, params->vertical_total_max - 1);
 560                 CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 6,
 561                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 1,
 562                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 1,
 563                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 564                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 565                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN), 0,
 566                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
 567                 CRTC_REG_UPDATE(
 568                                 CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 569                                 CRTC_STATIC_SCREEN_EVENT_MASK,
 570                                 0x180);
 571 
 572         } else {
 573                 CRTC_REG_SET_N(CRTC0_CRTC_V_TOTAL_CONTROL, 5,
 574                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL), 0,
 575                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL), 0,
 576                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT), 0,
 577                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC), 0,
 578                                 FD(CRTC0_CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK), 0);
 579                 CRTC_REG_UPDATE(
 580                                 CRTC0_CRTC_V_TOTAL_MIN,
 581                                 CRTC_V_TOTAL_MIN, 0);
 582                 CRTC_REG_UPDATE(
 583                                 CRTC0_CRTC_V_TOTAL_MAX,
 584                                 CRTC_V_TOTAL_MAX, 0);
 585                 CRTC_REG_UPDATE(
 586                                 CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 587                                 CRTC_STATIC_SCREEN_EVENT_MASK,
 588                                 0);
 589         }
 590 }
 591 
 592 /**
 593  *****************************************************************************
 594  *  Function: dce120_timing_generator_get_position
 595  *
 596  *  @brief
 597  *     Returns CRTC vertical/horizontal counters
 598  *
 599  *  @param [out] position
 600  *****************************************************************************
 601  */
 602 void dce120_timing_generator_get_position(struct timing_generator *tg,
 603         struct crtc_position *position)
 604 {
 605         uint32_t value;
 606         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 607 
 608         value = dm_read_reg_soc15(
 609                         tg->ctx,
 610                         mmCRTC0_CRTC_STATUS_POSITION,
 611                         tg110->offsets.crtc);
 612 
 613         position->horizontal_count = get_reg_field_value(
 614                         value,
 615                         CRTC0_CRTC_STATUS_POSITION,
 616                         CRTC_HORZ_COUNT);
 617 
 618         position->vertical_count = get_reg_field_value(
 619                         value,
 620                         CRTC0_CRTC_STATUS_POSITION,
 621                         CRTC_VERT_COUNT);
 622 
 623         value = dm_read_reg_soc15(
 624                         tg->ctx,
 625                         mmCRTC0_CRTC_NOM_VERT_POSITION,
 626                         tg110->offsets.crtc);
 627 
 628         position->nominal_vcount = get_reg_field_value(
 629                         value,
 630                         CRTC0_CRTC_NOM_VERT_POSITION,
 631                         CRTC_VERT_COUNT_NOM);
 632 }
 633 
 634 
 635 void dce120_timing_generator_get_crtc_scanoutpos(
 636         struct timing_generator *tg,
 637         uint32_t *v_blank_start,
 638         uint32_t *v_blank_end,
 639         uint32_t *h_position,
 640         uint32_t *v_position)
 641 {
 642         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 643         struct crtc_position position;
 644 
 645         uint32_t v_blank_start_end = dm_read_reg_soc15(
 646                         tg->ctx,
 647                         mmCRTC0_CRTC_V_BLANK_START_END,
 648                         tg110->offsets.crtc);
 649 
 650         *v_blank_start = get_reg_field_value(v_blank_start_end,
 651                                              CRTC0_CRTC_V_BLANK_START_END,
 652                                              CRTC_V_BLANK_START);
 653         *v_blank_end = get_reg_field_value(v_blank_start_end,
 654                                            CRTC0_CRTC_V_BLANK_START_END,
 655                                            CRTC_V_BLANK_END);
 656 
 657         dce120_timing_generator_get_crtc_position(
 658                         tg, &position);
 659 
 660         *h_position = position.horizontal_count;
 661         *v_position = position.vertical_count;
 662 }
 663 
 664 void dce120_timing_generator_enable_advanced_request(
 665         struct timing_generator *tg,
 666         bool enable,
 667         const struct dc_crtc_timing *timing)
 668 {
 669         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 670         uint32_t v_sync_width_and_b_porch =
 671                                 timing->v_total - timing->v_addressable -
 672                                 timing->v_border_bottom - timing->v_front_porch;
 673         uint32_t value = dm_read_reg_soc15(
 674                                 tg->ctx,
 675                                 mmCRTC0_CRTC_START_LINE_CONTROL,
 676                                 tg110->offsets.crtc);
 677 
 678         set_reg_field_value(
 679                 value,
 680                 enable ? 0 : 1,
 681                 CRTC0_CRTC_START_LINE_CONTROL,
 682                 CRTC_LEGACY_REQUESTOR_EN);
 683 
 684         /* Program advanced line position acc.to the best case from fetching data perspective to hide MC latency
 685          * and prefilling Line Buffer in V Blank (to 10 lines as LB can store max 10 lines)
 686          */
 687         if (v_sync_width_and_b_porch > 10)
 688                 v_sync_width_and_b_porch = 10;
 689 
 690         set_reg_field_value(
 691                 value,
 692                 v_sync_width_and_b_porch,
 693                 CRTC0_CRTC_START_LINE_CONTROL,
 694                 CRTC_ADVANCED_START_LINE_POSITION);
 695 
 696         dm_write_reg_soc15(tg->ctx,
 697                         mmCRTC0_CRTC_START_LINE_CONTROL,
 698                         tg110->offsets.crtc,
 699                         value);
 700 }
 701 
 702 void dce120_tg_program_blank_color(struct timing_generator *tg,
 703         const struct tg_color *black_color)
 704 {
 705         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 706         uint32_t value = 0;
 707 
 708         CRTC_REG_UPDATE_3(
 709                 CRTC0_CRTC_BLACK_COLOR,
 710                 CRTC_BLACK_COLOR_B_CB, black_color->color_b_cb,
 711                 CRTC_BLACK_COLOR_G_Y, black_color->color_g_y,
 712                 CRTC_BLACK_COLOR_R_CR, black_color->color_r_cr);
 713 
 714         value = dm_read_reg_soc15(
 715                                 tg->ctx,
 716                                 mmCRTC0_CRTC_BLACK_COLOR,
 717                                 tg110->offsets.crtc);
 718         dm_write_reg_soc15(
 719                 tg->ctx,
 720                 mmCRTC0_CRTC_BLANK_DATA_COLOR,
 721                 tg110->offsets.crtc,
 722                 value);
 723 }
 724 
 725 void dce120_tg_set_overscan_color(struct timing_generator *tg,
 726         const struct tg_color *overscan_color)
 727 {
 728         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 729 
 730         CRTC_REG_SET_3(
 731                 CRTC0_CRTC_OVERSCAN_COLOR,
 732                 CRTC_OVERSCAN_COLOR_BLUE, overscan_color->color_b_cb,
 733                 CRTC_OVERSCAN_COLOR_GREEN, overscan_color->color_g_y,
 734                 CRTC_OVERSCAN_COLOR_RED, overscan_color->color_r_cr);
 735 }
 736 
 737 static void dce120_tg_program_timing(struct timing_generator *tg,
 738         const struct dc_crtc_timing *timing,
 739         int vready_offset,
 740         int vstartup_start,
 741         int vupdate_offset,
 742         int vupdate_width,
 743         const enum signal_type signal,
 744         bool use_vbios)
 745 {
 746         if (use_vbios)
 747                 dce110_timing_generator_program_timing_generator(tg, timing);
 748         else
 749                 dce120_timing_generator_program_blanking(tg, timing);
 750 }
 751 
 752 bool dce120_tg_is_blanked(struct timing_generator *tg)
 753 {
 754         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 755         uint32_t value = dm_read_reg_soc15(
 756                         tg->ctx,
 757                         mmCRTC0_CRTC_BLANK_CONTROL,
 758                         tg110->offsets.crtc);
 759 
 760         if (get_reg_field_value(
 761                 value,
 762                 CRTC0_CRTC_BLANK_CONTROL,
 763                 CRTC_BLANK_DATA_EN) == 1 &&
 764             get_reg_field_value(
 765                 value,
 766                 CRTC0_CRTC_BLANK_CONTROL,
 767                 CRTC_CURRENT_BLANK_STATE) == 1)
 768                         return true;
 769 
 770         return false;
 771 }
 772 
 773 void dce120_tg_set_blank(struct timing_generator *tg,
 774                 bool enable_blanking)
 775 {
 776         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 777 
 778         CRTC_REG_SET(
 779                 CRTC0_CRTC_DOUBLE_BUFFER_CONTROL,
 780                 CRTC_BLANK_DATA_DOUBLE_BUFFER_EN, 1);
 781 
 782         if (enable_blanking)
 783                 CRTC_REG_SET(CRTC0_CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
 784         else
 785                 dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_BLANK_CONTROL,
 786                         tg110->offsets.crtc, 0);
 787 }
 788 
 789 bool dce120_tg_validate_timing(struct timing_generator *tg,
 790         const struct dc_crtc_timing *timing);
 791 
 792 void dce120_tg_wait_for_state(struct timing_generator *tg,
 793         enum crtc_state state)
 794 {
 795         switch (state) {
 796         case CRTC_STATE_VBLANK:
 797                 dce120_timing_generator_wait_for_vblank(tg);
 798                 break;
 799 
 800         case CRTC_STATE_VACTIVE:
 801                 dce120_timing_generator_wait_for_vactive(tg);
 802                 break;
 803 
 804         default:
 805                 break;
 806         }
 807 }
 808 
 809 void dce120_tg_set_colors(struct timing_generator *tg,
 810         const struct tg_color *blank_color,
 811         const struct tg_color *overscan_color)
 812 {
 813         if (blank_color != NULL)
 814                 dce120_tg_program_blank_color(tg, blank_color);
 815 
 816         if (overscan_color != NULL)
 817                 dce120_tg_set_overscan_color(tg, overscan_color);
 818 }
 819 
 820 static void dce120_timing_generator_set_static_screen_control(
 821         struct timing_generator *tg,
 822         uint32_t value)
 823 {
 824         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 825 
 826         CRTC_REG_UPDATE_2(CRTC0_CRTC_STATIC_SCREEN_CONTROL,
 827                         CRTC_STATIC_SCREEN_EVENT_MASK, value,
 828                         CRTC_STATIC_SCREEN_FRAME_COUNT, 2);
 829 }
 830 
 831 void dce120_timing_generator_set_test_pattern(
 832         struct timing_generator *tg,
 833         /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
 834          * because this is not DP-specific (which is probably somewhere in DP
 835          * encoder) */
 836         enum controller_dp_test_pattern test_pattern,
 837         enum dc_color_depth color_depth)
 838 {
 839         struct dc_context *ctx = tg->ctx;
 840         uint32_t value;
 841         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 842         enum test_pattern_color_format bit_depth;
 843         enum test_pattern_dyn_range dyn_range;
 844         enum test_pattern_mode mode;
 845         /* color ramp generator mixes 16-bits color */
 846         uint32_t src_bpc = 16;
 847         /* requested bpc */
 848         uint32_t dst_bpc;
 849         uint32_t index;
 850         /* RGB values of the color bars.
 851          * Produce two RGB colors: RGB0 - white (all Fs)
 852          * and RGB1 - black (all 0s)
 853          * (three RGB components for two colors)
 854          */
 855         uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
 856                                                 0x0000, 0x0000};
 857         /* dest color (converted to the specified color format) */
 858         uint16_t dst_color[6];
 859         uint32_t inc_base;
 860 
 861         /* translate to bit depth */
 862         switch (color_depth) {
 863         case COLOR_DEPTH_666:
 864                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
 865         break;
 866         case COLOR_DEPTH_888:
 867                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 868         break;
 869         case COLOR_DEPTH_101010:
 870                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
 871         break;
 872         case COLOR_DEPTH_121212:
 873                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
 874         break;
 875         default:
 876                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
 877         break;
 878         }
 879 
 880         switch (test_pattern) {
 881         case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
 882         case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
 883         {
 884                 dyn_range = (test_pattern ==
 885                                 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
 886                                 TEST_PATTERN_DYN_RANGE_CEA :
 887                                 TEST_PATTERN_DYN_RANGE_VESA);
 888                 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
 889 
 890                 CRTC_REG_UPDATE_2(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
 891                                 CRTC_TEST_PATTERN_VRES, 6,
 892                                 CRTC_TEST_PATTERN_HRES, 6);
 893 
 894                 CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 895                                 CRTC_TEST_PATTERN_EN, 1,
 896                                 CRTC_TEST_PATTERN_MODE, mode,
 897                                 CRTC_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
 898                                 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
 899         }
 900         break;
 901 
 902         case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
 903         case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
 904         {
 905                 mode = (test_pattern ==
 906                         CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
 907                         TEST_PATTERN_MODE_VERTICALBARS :
 908                         TEST_PATTERN_MODE_HORIZONTALBARS);
 909 
 910                 switch (bit_depth) {
 911                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
 912                         dst_bpc = 6;
 913                 break;
 914                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
 915                         dst_bpc = 8;
 916                 break;
 917                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
 918                         dst_bpc = 10;
 919                 break;
 920                 default:
 921                         dst_bpc = 8;
 922                 break;
 923                 }
 924 
 925                 /* adjust color to the required colorFormat */
 926                 for (index = 0; index < 6; index++) {
 927                         /* dst = 2^dstBpc * src / 2^srcBpc = src >>
 928                          * (srcBpc - dstBpc);
 929                          */
 930                         dst_color[index] =
 931                                 src_color[index] >> (src_bpc - dst_bpc);
 932                 /* CRTC_TEST_PATTERN_DATA has 16 bits,
 933                  * lowest 6 are hardwired to ZERO
 934                  * color bits should be left aligned aligned to MSB
 935                  * XXXXXXXXXX000000 for 10 bit,
 936                  * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
 937                  */
 938                         dst_color[index] <<= (16 - dst_bpc);
 939                 }
 940 
 941                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, 0);
 942 
 943                 /* We have to write the mask before data, similar to pipeline.
 944                  * For example, for 8 bpc, if we want RGB0 to be magenta,
 945                  * and RGB1 to be cyan,
 946                  * we need to make 7 writes:
 947                  * MASK   DATA
 948                  * 000001 00000000 00000000                     set mask to R0
 949                  * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
 950                  * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
 951                  * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
 952                  * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
 953                  * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
 954                  * 100000 11111111 00000000     B1 255, 0xFF00
 955                  *
 956                  * we will make a loop of 6 in which we prepare the mask,
 957                  * then write, then prepare the color for next write.
 958                  * first iteration will write mask only,
 959                  * but each next iteration color prepared in
 960                  * previous iteration will be written within new mask,
 961                  * the last component will written separately,
 962                  * mask is not changing between 6th and 7th write
 963                  * and color will be prepared by last iteration
 964                  */
 965 
 966                 /* write color, color values mask in CRTC_TEST_PATTERN_MASK
 967                  * is B1, G1, R1, B0, G0, R0
 968                  */
 969                 value = 0;
 970                 for (index = 0; index < 6; index++) {
 971                         /* prepare color mask, first write PATTERN_DATA
 972                          * will have all zeros
 973                          */
 974                         set_reg_field_value(
 975                                 value,
 976                                 (1 << index),
 977                                 CRTC0_CRTC_TEST_PATTERN_COLOR,
 978                                 CRTC_TEST_PATTERN_MASK);
 979                         /* write color component */
 980                         dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 981                         /* prepare next color component,
 982                          * will be written in the next iteration
 983                          */
 984                         set_reg_field_value(
 985                                 value,
 986                                 dst_color[index],
 987                                 CRTC0_CRTC_TEST_PATTERN_COLOR,
 988                                 CRTC_TEST_PATTERN_DATA);
 989                 }
 990                 /* write last color component,
 991                  * it's been already prepared in the loop
 992                  */
 993                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
 994 
 995                 /* enable test pattern */
 996                 CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
 997                                 CRTC_TEST_PATTERN_EN, 1,
 998                                 CRTC_TEST_PATTERN_MODE, mode,
 999                                 CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1000                                 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1001         }
1002         break;
1003 
1004         case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
1005         {
1006                 mode = (bit_depth ==
1007                         TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
1008                         TEST_PATTERN_MODE_DUALRAMP_RGB :
1009                         TEST_PATTERN_MODE_SINGLERAMP_RGB);
1010 
1011                 switch (bit_depth) {
1012                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1013                         dst_bpc = 6;
1014                 break;
1015                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1016                         dst_bpc = 8;
1017                 break;
1018                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1019                         dst_bpc = 10;
1020                 break;
1021                 default:
1022                         dst_bpc = 8;
1023                 break;
1024                 }
1025 
1026                 /* increment for the first ramp for one color gradation
1027                  * 1 gradation for 6-bit color is 2^10
1028                  * gradations in 16-bit color
1029                  */
1030                 inc_base = (src_bpc - dst_bpc);
1031 
1032                 switch (bit_depth) {
1033                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
1034                 {
1035                         CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1036                                         CRTC_TEST_PATTERN_INC0, inc_base,
1037                                         CRTC_TEST_PATTERN_INC1, 0,
1038                                         CRTC_TEST_PATTERN_HRES, 6,
1039                                         CRTC_TEST_PATTERN_VRES, 6,
1040                                         CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1041                 }
1042                 break;
1043                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
1044                 {
1045                         CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1046                                         CRTC_TEST_PATTERN_INC0, inc_base,
1047                                         CRTC_TEST_PATTERN_INC1, 0,
1048                                         CRTC_TEST_PATTERN_HRES, 8,
1049                                         CRTC_TEST_PATTERN_VRES, 6,
1050                                         CRTC_TEST_PATTERN_RAMP0_OFFSET, 0);
1051                 }
1052                 break;
1053                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
1054                 {
1055                         CRTC_REG_UPDATE_5(CRTC0_CRTC_TEST_PATTERN_PARAMETERS,
1056                                         CRTC_TEST_PATTERN_INC0, inc_base,
1057                                         CRTC_TEST_PATTERN_INC1, inc_base + 2,
1058                                         CRTC_TEST_PATTERN_HRES, 8,
1059                                         CRTC_TEST_PATTERN_VRES, 5,
1060                                         CRTC_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
1061                 }
1062                 break;
1063                 default:
1064                 break;
1065                 }
1066 
1067                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, 0);
1068 
1069                 /* enable test pattern */
1070                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc, 0);
1071 
1072                 CRTC_REG_UPDATE_4(CRTC0_CRTC_TEST_PATTERN_CONTROL,
1073                                 CRTC_TEST_PATTERN_EN, 1,
1074                                 CRTC_TEST_PATTERN_MODE, mode,
1075                                 CRTC_TEST_PATTERN_DYNAMIC_RANGE, 0,
1076                                 CRTC_TEST_PATTERN_COLOR_FORMAT, bit_depth);
1077         }
1078         break;
1079         case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
1080         {
1081                 value = 0;
1082                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_CONTROL, tg110->offsets.crtc,  value);
1083                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_COLOR, tg110->offsets.crtc, value);
1084                 dm_write_reg_soc15(ctx, mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS, tg110->offsets.crtc, value);
1085         }
1086         break;
1087         default:
1088         break;
1089         }
1090 }
1091 
1092 static bool dce120_arm_vert_intr(
1093                 struct timing_generator *tg,
1094                 uint8_t width)
1095 {
1096         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1097         uint32_t v_blank_start, v_blank_end, h_position, v_position;
1098 
1099         tg->funcs->get_scanoutpos(
1100                                 tg,
1101                                 &v_blank_start,
1102                                 &v_blank_end,
1103                                 &h_position,
1104                                 &v_position);
1105 
1106         if (v_blank_start == 0 || v_blank_end == 0)
1107                 return false;
1108 
1109         CRTC_REG_SET_2(
1110                         CRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION,
1111                         CRTC_VERTICAL_INTERRUPT0_LINE_START, v_blank_start,
1112                         CRTC_VERTICAL_INTERRUPT0_LINE_END, v_blank_start + width);
1113 
1114         return true;
1115 }
1116 
1117 
1118 static bool dce120_is_tg_enabled(struct timing_generator *tg)
1119 {
1120         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1121         uint32_t value, field;
1122 
1123         value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CONTROL,
1124                                   tg110->offsets.crtc);
1125         field = get_reg_field_value(value, CRTC0_CRTC_CONTROL,
1126                                     CRTC_CURRENT_MASTER_EN_STATE);
1127 
1128         return field == 1;
1129 }
1130 
1131 static bool dce120_configure_crc(struct timing_generator *tg,
1132                                  const struct crc_params *params)
1133 {
1134         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1135 
1136         /* Cannot configure crc on a CRTC that is disabled */
1137         if (!dce120_is_tg_enabled(tg))
1138                 return false;
1139 
1140         /* First, disable CRC before we configure it. */
1141         dm_write_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1142                            tg110->offsets.crtc, 0);
1143 
1144         if (!params->enable)
1145                 return true;
1146 
1147         /* Program frame boundaries */
1148         /* Window A x axis start and end. */
1149         CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_X_CONTROL,
1150                           CRTC_CRC0_WINDOWA_X_START, params->windowa_x_start,
1151                           CRTC_CRC0_WINDOWA_X_END, params->windowa_x_end);
1152 
1153         /* Window A y axis start and end. */
1154         CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL,
1155                           CRTC_CRC0_WINDOWA_Y_START, params->windowa_y_start,
1156                           CRTC_CRC0_WINDOWA_Y_END, params->windowa_y_end);
1157 
1158         /* Window B x axis start and end. */
1159         CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_X_CONTROL,
1160                           CRTC_CRC0_WINDOWB_X_START, params->windowb_x_start,
1161                           CRTC_CRC0_WINDOWB_X_END, params->windowb_x_end);
1162 
1163         /* Window B y axis start and end. */
1164         CRTC_REG_UPDATE_2(CRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL,
1165                           CRTC_CRC0_WINDOWB_Y_START, params->windowb_y_start,
1166                           CRTC_CRC0_WINDOWB_Y_END, params->windowb_y_end);
1167 
1168         /* Set crc mode and selection, and enable. Only using CRC0*/
1169         CRTC_REG_UPDATE_3(CRTC0_CRTC_CRC_CNTL,
1170                           CRTC_CRC_EN, params->continuous_mode ? 1 : 0,
1171                           CRTC_CRC0_SELECT, params->selection,
1172                           CRTC_CRC_EN, 1);
1173 
1174         return true;
1175 }
1176 
1177 static bool dce120_get_crc(struct timing_generator *tg, uint32_t *r_cr,
1178                            uint32_t *g_y, uint32_t *b_cb)
1179 {
1180         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
1181         uint32_t value, field;
1182 
1183         value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC_CNTL,
1184                                   tg110->offsets.crtc);
1185         field = get_reg_field_value(value, CRTC0_CRTC_CRC_CNTL, CRTC_CRC_EN);
1186 
1187         /* Early return if CRC is not enabled for this CRTC */
1188         if (!field)
1189                 return false;
1190 
1191         value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_RG,
1192                                   tg110->offsets.crtc);
1193         *r_cr = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_R_CR);
1194         *g_y = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_RG, CRC0_G_Y);
1195 
1196         value = dm_read_reg_soc15(tg->ctx, mmCRTC0_CRTC_CRC0_DATA_B,
1197                                   tg110->offsets.crtc);
1198         *b_cb = get_reg_field_value(value, CRTC0_CRTC_CRC0_DATA_B, CRC0_B_CB);
1199 
1200         return true;
1201 }
1202 
1203 static const struct timing_generator_funcs dce120_tg_funcs = {
1204                 .validate_timing = dce120_tg_validate_timing,
1205                 .program_timing = dce120_tg_program_timing,
1206                 .enable_crtc = dce120_timing_generator_enable_crtc,
1207                 .disable_crtc = dce110_timing_generator_disable_crtc,
1208                 /* used by enable_timing_synchronization. Not need for FPGA */
1209                 .is_counter_moving = dce110_timing_generator_is_counter_moving,
1210                 /* never be called */
1211                 .get_position = dce120_timing_generator_get_crtc_position,
1212                 .get_frame_count = dce120_timing_generator_get_vblank_counter,
1213                 .get_scanoutpos = dce120_timing_generator_get_crtc_scanoutpos,
1214                 .set_early_control = dce120_timing_generator_set_early_control,
1215                 /* used by enable_timing_synchronization. Not need for FPGA */
1216                 .wait_for_state = dce120_tg_wait_for_state,
1217                 .set_blank = dce120_tg_set_blank,
1218                 .is_blanked = dce120_tg_is_blanked,
1219                 /* never be called */
1220                 .set_colors = dce120_tg_set_colors,
1221                 .set_overscan_blank_color = dce120_timing_generator_set_overscan_color_black,
1222                 .set_blank_color = dce120_timing_generator_program_blank_color,
1223                 .disable_vga = dce120_timing_generator_disable_vga,
1224                 .did_triggered_reset_occur = dce120_timing_generator_did_triggered_reset_occur,
1225                 .setup_global_swap_lock = dce120_timing_generator_setup_global_swap_lock,
1226                 .enable_reset_trigger = dce120_timing_generator_enable_reset_trigger,
1227                 .disable_reset_trigger = dce120_timing_generator_disable_reset_trigger,
1228                 .tear_down_global_swap_lock = dce120_timing_generator_tear_down_global_swap_lock,
1229                 .enable_advanced_request = dce120_timing_generator_enable_advanced_request,
1230                 .set_drr = dce120_timing_generator_set_drr,
1231                 .set_static_screen_control = dce120_timing_generator_set_static_screen_control,
1232                 .set_test_pattern = dce120_timing_generator_set_test_pattern,
1233                 .arm_vert_intr = dce120_arm_vert_intr,
1234                 .is_tg_enabled = dce120_is_tg_enabled,
1235                 .configure_crc = dce120_configure_crc,
1236                 .get_crc = dce120_get_crc,
1237 };
1238 
1239 
1240 void dce120_timing_generator_construct(
1241         struct dce110_timing_generator *tg110,
1242         struct dc_context *ctx,
1243         uint32_t instance,
1244         const struct dce110_timing_generator_offsets *offsets)
1245 {
1246         tg110->controller_id = CONTROLLER_ID_D0 + instance;
1247         tg110->base.inst = instance;
1248 
1249         tg110->offsets = *offsets;
1250 
1251         tg110->base.funcs = &dce120_tg_funcs;
1252 
1253         tg110->base.ctx = ctx;
1254         tg110->base.bp = ctx->dc_bios;
1255 
1256         tg110->max_h_total = CRTC0_CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
1257         tg110->max_v_total = CRTC0_CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
1258 
1259         /*//CRTC requires a minimum HBLANK = 32 pixels and o
1260          * Minimum HSYNC = 8 pixels*/
1261         tg110->min_h_blank = 32;
1262         /*DCE12_CRTC_Block_ARch.doc*/
1263         tg110->min_h_front_porch = 0;
1264         tg110->min_h_back_porch = 0;
1265 
1266         tg110->min_h_sync_width = 8;
1267         tg110->min_v_sync_width = 1;
1268         tg110->min_v_blank = 3;
1269 }

/* [<][>][^][v][top][bottom][index][help] */