LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dce110 - dce110_timing_generator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 656 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 40 0.0 %

          Line data    Source code
       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 DCE11 register header files */
      29             : #include "dce/dce_11_0_d.h"
      30             : #include "dce/dce_11_0_sh_mask.h"
      31             : 
      32             : #include "dc_types.h"
      33             : #include "dc_bios_types.h"
      34             : #include "dc.h"
      35             : 
      36             : #include "include/grph_object_id.h"
      37             : #include "include/logger_interface.h"
      38             : #include "dce110_timing_generator.h"
      39             : 
      40             : #include "timing_generator.h"
      41             : 
      42             : 
      43             : #define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10
      44             : 
      45             : #define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1)
      46             : #define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1)
      47             : 
      48             : #define CRTC_REG(reg) (reg + tg110->offsets.crtc)
      49             : #define DCP_REG(reg) (reg + tg110->offsets.dcp)
      50             : 
      51             : /* Flowing register offsets are same in files of
      52             :  * dce/dce_11_0_d.h
      53             :  * dce/vi_polaris10_p/vi_polaris10_d.h
      54             :  *
      55             :  * So we can create dce110 timing generator to use it.
      56             :  */
      57             : 
      58             : 
      59             : /*
      60             : * apply_front_porch_workaround
      61             : *
      62             : * This is a workaround for a bug that has existed since R5xx and has not been
      63             : * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
      64             : */
      65             : static void dce110_timing_generator_apply_front_porch_workaround(
      66             :         struct timing_generator *tg,
      67             :         struct dc_crtc_timing *timing)
      68             : {
      69           0 :         if (timing->flags.INTERLACE == 1) {
      70           0 :                 if (timing->v_front_porch < 2)
      71           0 :                         timing->v_front_porch = 2;
      72             :         } else {
      73           0 :                 if (timing->v_front_porch < 1)
      74           0 :                         timing->v_front_porch = 1;
      75             :         }
      76             : }
      77             : 
      78             : /*
      79             :  *****************************************************************************
      80             :  *  Function: is_in_vertical_blank
      81             :  *
      82             :  *  @brief
      83             :  *     check the current status of CRTC to check if we are in Vertical Blank
      84             :  *     regioneased" state
      85             :  *
      86             :  *  @return
      87             :  *     true if currently in blank region, false otherwise
      88             :  *
      89             :  *****************************************************************************
      90             :  */
      91             : static bool dce110_timing_generator_is_in_vertical_blank(
      92             :                 struct timing_generator *tg)
      93             : {
      94           0 :         uint32_t addr = 0;
      95           0 :         uint32_t value = 0;
      96           0 :         uint32_t field = 0;
      97           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
      98             : 
      99           0 :         addr = CRTC_REG(mmCRTC_STATUS);
     100           0 :         value = dm_read_reg(tg->ctx, addr);
     101           0 :         field = get_reg_field_value(value, CRTC_STATUS, CRTC_V_BLANK);
     102             :         return field == 1;
     103             : }
     104             : 
     105           0 : void dce110_timing_generator_set_early_control(
     106             :                 struct timing_generator *tg,
     107             :                 uint32_t early_cntl)
     108             : {
     109             :         uint32_t regval;
     110           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     111           0 :         uint32_t address = CRTC_REG(mmCRTC_CONTROL);
     112             : 
     113           0 :         regval = dm_read_reg(tg->ctx, address);
     114           0 :         set_reg_field_value(regval, early_cntl,
     115             :                         CRTC_CONTROL, CRTC_HBLANK_EARLY_CONTROL);
     116           0 :         dm_write_reg(tg->ctx, address, regval);
     117           0 : }
     118             : 
     119             : /*
     120             :  * Enable CRTC
     121             :  * Enable CRTC - call ASIC Control Object to enable Timing generator.
     122             :  */
     123           0 : bool dce110_timing_generator_enable_crtc(struct timing_generator *tg)
     124             : {
     125             :         enum bp_result result;
     126             : 
     127           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     128           0 :         uint32_t value = 0;
     129             : 
     130             :         /*
     131             :          * 3 is used to make sure V_UPDATE occurs at the beginning of the first
     132             :          * line of vertical front porch
     133             :          */
     134           0 :         set_reg_field_value(
     135             :                 value,
     136             :                 0,
     137             :                 CRTC_MASTER_UPDATE_MODE,
     138             :                 MASTER_UPDATE_MODE);
     139             : 
     140           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
     141             : 
     142             :         /* TODO: may want this on to catch underflow */
     143           0 :         value = 0;
     144           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK), value);
     145             : 
     146           0 :         result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, true);
     147             : 
     148           0 :         return result == BP_RESULT_OK;
     149             : }
     150             : 
     151           0 : void dce110_timing_generator_program_blank_color(
     152             :                 struct timing_generator *tg,
     153             :                 const struct tg_color *black_color)
     154             : {
     155           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     156           0 :         uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
     157           0 :         uint32_t value = dm_read_reg(tg->ctx, addr);
     158             : 
     159           0 :         set_reg_field_value(
     160             :                 value,
     161             :                 black_color->color_b_cb,
     162             :                 CRTC_BLACK_COLOR,
     163             :                 CRTC_BLACK_COLOR_B_CB);
     164           0 :         set_reg_field_value(
     165             :                 value,
     166             :                 black_color->color_g_y,
     167             :                 CRTC_BLACK_COLOR,
     168             :                 CRTC_BLACK_COLOR_G_Y);
     169           0 :         set_reg_field_value(
     170             :                 value,
     171             :                 black_color->color_r_cr,
     172             :                 CRTC_BLACK_COLOR,
     173             :                 CRTC_BLACK_COLOR_R_CR);
     174             : 
     175           0 :         dm_write_reg(tg->ctx, addr, value);
     176           0 : }
     177             : 
     178             : /*
     179             :  *****************************************************************************
     180             :  *  Function: disable_stereo
     181             :  *
     182             :  *  @brief
     183             :  *     Disables active stereo on controller
     184             :  *     Frame Packing need to be disabled in vBlank or when CRTC not running
     185             :  *****************************************************************************
     186             :  */
     187             : #if 0
     188             : @TODOSTEREO
     189             : static void disable_stereo(struct timing_generator *tg)
     190             : {
     191             :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     192             :         uint32_t addr = CRTC_REG(mmCRTC_3D_STRUCTURE_CONTROL);
     193             :         uint32_t value = 0;
     194             :         uint32_t test = 0;
     195             :         uint32_t field = 0;
     196             :         uint32_t struc_en = 0;
     197             :         uint32_t struc_stereo_sel_ovr = 0;
     198             : 
     199             :         value = dm_read_reg(tg->ctx, addr);
     200             :         struc_en = get_reg_field_value(
     201             :                         value,
     202             :                         CRTC_3D_STRUCTURE_CONTROL,
     203             :                         CRTC_3D_STRUCTURE_EN);
     204             : 
     205             :         struc_stereo_sel_ovr = get_reg_field_value(
     206             :                         value,
     207             :                         CRTC_3D_STRUCTURE_CONTROL,
     208             :                         CRTC_3D_STRUCTURE_STEREO_SEL_OVR);
     209             : 
     210             :         /*
     211             :          * When disabling Frame Packing in 2 step mode, we need to program both
     212             :          * registers at the same frame
     213             :          * Programming it in the beginning of VActive makes sure we are ok
     214             :          */
     215             : 
     216             :         if (struc_en != 0 && struc_stereo_sel_ovr == 0) {
     217             :                 tg->funcs->wait_for_vblank(tg);
     218             :                 tg->funcs->wait_for_vactive(tg);
     219             :         }
     220             : 
     221             :         value = 0;
     222             :         dm_write_reg(tg->ctx, addr, value);
     223             : 
     224             :         addr = tg->regs[IDX_CRTC_STEREO_CONTROL];
     225             :         dm_write_reg(tg->ctx, addr, value);
     226             : }
     227             : #endif
     228             : 
     229             : /*
     230             :  * disable_crtc - call ASIC Control Object to disable Timing generator.
     231             :  */
     232           0 : bool dce110_timing_generator_disable_crtc(struct timing_generator *tg)
     233             : {
     234             :         enum bp_result result;
     235             : 
     236           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     237             : 
     238           0 :         result = tg->bp->funcs->enable_crtc(tg->bp, tg110->controller_id, false);
     239             : 
     240             :         /* Need to make sure stereo is disabled according to the DCE5.0 spec */
     241             : 
     242             :         /*
     243             :          * @TODOSTEREO call this when adding stereo support
     244             :          * tg->funcs->disable_stereo(tg);
     245             :          */
     246             : 
     247           0 :         return result == BP_RESULT_OK;
     248             : }
     249             : 
     250             : /*
     251             :  * program_horz_count_by_2
     252             :  * Programs DxCRTC_HORZ_COUNT_BY2_EN - 1 for DVI 30bpp mode, 0 otherwise
     253             :  */
     254           0 : static void program_horz_count_by_2(
     255             :         struct timing_generator *tg,
     256             :         const struct dc_crtc_timing *timing)
     257             : {
     258             :         uint32_t regval;
     259           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     260             : 
     261           0 :         regval = dm_read_reg(tg->ctx,
     262             :                         CRTC_REG(mmCRTC_COUNT_CONTROL));
     263             : 
     264           0 :         set_reg_field_value(regval, 0, CRTC_COUNT_CONTROL,
     265             :                         CRTC_HORZ_COUNT_BY2_EN);
     266             : 
     267           0 :         if (timing->flags.HORZ_COUNT_BY_TWO)
     268           0 :                 set_reg_field_value(regval, 1, CRTC_COUNT_CONTROL,
     269             :                                         CRTC_HORZ_COUNT_BY2_EN);
     270             : 
     271           0 :         dm_write_reg(tg->ctx,
     272             :                         CRTC_REG(mmCRTC_COUNT_CONTROL), regval);
     273           0 : }
     274             : 
     275             : /*
     276             :  * program_timing_generator
     277             :  * Program CRTC Timing Registers - DxCRTC_H_*, DxCRTC_V_*, Pixel repetition.
     278             :  * Call ASIC Control Object to program Timings.
     279             :  */
     280           0 : bool dce110_timing_generator_program_timing_generator(
     281             :         struct timing_generator *tg,
     282             :         const struct dc_crtc_timing *dc_crtc_timing)
     283             : {
     284             :         enum bp_result result;
     285             :         struct bp_hw_crtc_timing_parameters bp_params;
     286             :         struct dc_crtc_timing patched_crtc_timing;
     287           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     288             : 
     289           0 :         uint32_t vsync_offset = dc_crtc_timing->v_border_bottom +
     290           0 :                         dc_crtc_timing->v_front_porch;
     291           0 :         uint32_t v_sync_start =dc_crtc_timing->v_addressable + vsync_offset;
     292             : 
     293           0 :         uint32_t hsync_offset = dc_crtc_timing->h_border_right +
     294           0 :                         dc_crtc_timing->h_front_porch;
     295           0 :         uint32_t h_sync_start = dc_crtc_timing->h_addressable + hsync_offset;
     296             : 
     297           0 :         memset(&bp_params, 0, sizeof(struct bp_hw_crtc_timing_parameters));
     298             : 
     299             :         /* Due to an asic bug we need to apply the Front Porch workaround prior
     300             :          * to programming the timing.
     301             :          */
     302             : 
     303           0 :         patched_crtc_timing = *dc_crtc_timing;
     304             : 
     305           0 :         dce110_timing_generator_apply_front_porch_workaround(tg, &patched_crtc_timing);
     306             : 
     307           0 :         bp_params.controller_id = tg110->controller_id;
     308             : 
     309           0 :         bp_params.h_total = patched_crtc_timing.h_total;
     310           0 :         bp_params.h_addressable =
     311           0 :                 patched_crtc_timing.h_addressable;
     312           0 :         bp_params.v_total = patched_crtc_timing.v_total;
     313           0 :         bp_params.v_addressable = patched_crtc_timing.v_addressable;
     314             : 
     315           0 :         bp_params.h_sync_start = h_sync_start;
     316           0 :         bp_params.h_sync_width = patched_crtc_timing.h_sync_width;
     317           0 :         bp_params.v_sync_start = v_sync_start;
     318           0 :         bp_params.v_sync_width = patched_crtc_timing.v_sync_width;
     319             : 
     320             :         /* Set overscan */
     321           0 :         bp_params.h_overscan_left =
     322           0 :                 patched_crtc_timing.h_border_left;
     323           0 :         bp_params.h_overscan_right =
     324           0 :                 patched_crtc_timing.h_border_right;
     325           0 :         bp_params.v_overscan_top = patched_crtc_timing.v_border_top;
     326           0 :         bp_params.v_overscan_bottom =
     327           0 :                 patched_crtc_timing.v_border_bottom;
     328             : 
     329             :         /* Set flags */
     330           0 :         if (patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY == 1)
     331           0 :                 bp_params.flags.HSYNC_POSITIVE_POLARITY = 1;
     332             : 
     333           0 :         if (patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY == 1)
     334           0 :                 bp_params.flags.VSYNC_POSITIVE_POLARITY = 1;
     335             : 
     336           0 :         if (patched_crtc_timing.flags.INTERLACE == 1)
     337           0 :                 bp_params.flags.INTERLACE = 1;
     338             : 
     339           0 :         if (patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1)
     340           0 :                 bp_params.flags.HORZ_COUNT_BY_TWO = 1;
     341             : 
     342           0 :         result = tg->bp->funcs->program_crtc_timing(tg->bp, &bp_params);
     343             : 
     344           0 :         program_horz_count_by_2(tg, &patched_crtc_timing);
     345             : 
     346           0 :         tg110->base.funcs->enable_advanced_request(tg, true, &patched_crtc_timing);
     347             : 
     348             :         /* Enable stereo - only when we need to pack 3D frame. Other types
     349             :          * of stereo handled in explicit call */
     350             : 
     351           0 :         return result == BP_RESULT_OK;
     352             : }
     353             : 
     354             : /*
     355             :  *****************************************************************************
     356             :  *  Function: set_drr
     357             :  *
     358             :  *  @brief
     359             :  *     Program dynamic refresh rate registers m_DxCRTC_V_TOTAL_*.
     360             :  *
     361             :  *  @param [in] pHwCrtcTiming: point to H
     362             :  *  wCrtcTiming struct
     363             :  *****************************************************************************
     364             :  */
     365           0 : void dce110_timing_generator_set_drr(
     366             :         struct timing_generator *tg,
     367             :         const struct drr_params *params)
     368             : {
     369             :         /* register values */
     370           0 :         uint32_t v_total_min = 0;
     371           0 :         uint32_t v_total_max = 0;
     372           0 :         uint32_t v_total_cntl = 0;
     373           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     374             : 
     375           0 :         uint32_t addr = 0;
     376             : 
     377           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
     378           0 :         v_total_min = dm_read_reg(tg->ctx, addr);
     379             : 
     380           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
     381           0 :         v_total_max = dm_read_reg(tg->ctx, addr);
     382             : 
     383           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
     384           0 :         v_total_cntl = dm_read_reg(tg->ctx, addr);
     385             : 
     386           0 :         if (params != NULL &&
     387           0 :                 params->vertical_total_max > 0 &&
     388           0 :                 params->vertical_total_min > 0) {
     389             : 
     390           0 :                 set_reg_field_value(v_total_max,
     391             :                                 params->vertical_total_max - 1,
     392             :                                 CRTC_V_TOTAL_MAX,
     393             :                                 CRTC_V_TOTAL_MAX);
     394             : 
     395           0 :                 set_reg_field_value(v_total_min,
     396             :                                 params->vertical_total_min - 1,
     397             :                                 CRTC_V_TOTAL_MIN,
     398             :                                 CRTC_V_TOTAL_MIN);
     399             : 
     400           0 :                 set_reg_field_value(v_total_cntl,
     401             :                                 1,
     402             :                                 CRTC_V_TOTAL_CONTROL,
     403             :                                 CRTC_V_TOTAL_MIN_SEL);
     404             : 
     405           0 :                 set_reg_field_value(v_total_cntl,
     406             :                                 1,
     407             :                                 CRTC_V_TOTAL_CONTROL,
     408             :                                 CRTC_V_TOTAL_MAX_SEL);
     409             : 
     410           0 :                 set_reg_field_value(v_total_cntl,
     411             :                                 0,
     412             :                                 CRTC_V_TOTAL_CONTROL,
     413             :                                 CRTC_FORCE_LOCK_ON_EVENT);
     414           0 :                 set_reg_field_value(v_total_cntl,
     415             :                                 0,
     416             :                                 CRTC_V_TOTAL_CONTROL,
     417             :                                 CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
     418             : 
     419           0 :                 set_reg_field_value(v_total_cntl,
     420             :                                 0,
     421             :                                 CRTC_V_TOTAL_CONTROL,
     422             :                                 CRTC_SET_V_TOTAL_MIN_MASK_EN);
     423             : 
     424           0 :                 set_reg_field_value(v_total_cntl,
     425             :                                 0,
     426             :                                 CRTC_V_TOTAL_CONTROL,
     427             :                                 CRTC_SET_V_TOTAL_MIN_MASK);
     428             :         } else {
     429           0 :                 set_reg_field_value(v_total_cntl,
     430             :                         0,
     431             :                         CRTC_V_TOTAL_CONTROL,
     432             :                         CRTC_SET_V_TOTAL_MIN_MASK);
     433           0 :                 set_reg_field_value(v_total_cntl,
     434             :                                 0,
     435             :                                 CRTC_V_TOTAL_CONTROL,
     436             :                                 CRTC_V_TOTAL_MIN_SEL);
     437           0 :                 set_reg_field_value(v_total_cntl,
     438             :                                 0,
     439             :                                 CRTC_V_TOTAL_CONTROL,
     440             :                                 CRTC_V_TOTAL_MAX_SEL);
     441           0 :                 set_reg_field_value(v_total_min,
     442             :                                 0,
     443             :                                 CRTC_V_TOTAL_MIN,
     444             :                                 CRTC_V_TOTAL_MIN);
     445           0 :                 set_reg_field_value(v_total_max,
     446             :                                 0,
     447             :                                 CRTC_V_TOTAL_MAX,
     448             :                                 CRTC_V_TOTAL_MAX);
     449           0 :                 set_reg_field_value(v_total_cntl,
     450             :                                 0,
     451             :                                 CRTC_V_TOTAL_CONTROL,
     452             :                                 CRTC_FORCE_LOCK_ON_EVENT);
     453           0 :                 set_reg_field_value(v_total_cntl,
     454             :                                 0,
     455             :                                 CRTC_V_TOTAL_CONTROL,
     456             :                                 CRTC_FORCE_LOCK_TO_MASTER_VSYNC);
     457             :         }
     458             : 
     459           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
     460           0 :         dm_write_reg(tg->ctx, addr, v_total_min);
     461             : 
     462           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
     463           0 :         dm_write_reg(tg->ctx, addr, v_total_max);
     464             : 
     465           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
     466           0 :         dm_write_reg(tg->ctx, addr, v_total_cntl);
     467           0 : }
     468             : 
     469           0 : void dce110_timing_generator_set_static_screen_control(
     470             :         struct timing_generator *tg,
     471             :         uint32_t event_triggers,
     472             :         uint32_t num_frames)
     473             : {
     474           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     475           0 :         uint32_t static_screen_cntl = 0;
     476           0 :         uint32_t addr = 0;
     477             : 
     478             :         // By register spec, it only takes 8 bit value
     479           0 :         if (num_frames > 0xFF)
     480           0 :                 num_frames = 0xFF;
     481             : 
     482           0 :         addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
     483           0 :         static_screen_cntl = dm_read_reg(tg->ctx, addr);
     484             : 
     485           0 :         set_reg_field_value(static_screen_cntl,
     486             :                                 event_triggers,
     487             :                                 CRTC_STATIC_SCREEN_CONTROL,
     488             :                                 CRTC_STATIC_SCREEN_EVENT_MASK);
     489             : 
     490           0 :         set_reg_field_value(static_screen_cntl,
     491             :                                 num_frames,
     492             :                                 CRTC_STATIC_SCREEN_CONTROL,
     493             :                                 CRTC_STATIC_SCREEN_FRAME_COUNT);
     494             : 
     495           0 :         dm_write_reg(tg->ctx, addr, static_screen_cntl);
     496           0 : }
     497             : 
     498             : /*
     499             :  * get_vblank_counter
     500             :  *
     501             :  * @brief
     502             :  * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
     503             :  * holds the counter of frames.
     504             :  *
     505             :  * @param
     506             :  * struct timing_generator *tg - [in] timing generator which controls the
     507             :  * desired CRTC
     508             :  *
     509             :  * @return
     510             :  * Counter of frames, which should equal to number of vblanks.
     511             :  */
     512           0 : uint32_t dce110_timing_generator_get_vblank_counter(struct timing_generator *tg)
     513             : {
     514           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     515           0 :         uint32_t addr = CRTC_REG(mmCRTC_STATUS_FRAME_COUNT);
     516           0 :         uint32_t value = dm_read_reg(tg->ctx, addr);
     517           0 :         uint32_t field = get_reg_field_value(
     518             :                         value, CRTC_STATUS_FRAME_COUNT, CRTC_FRAME_COUNT);
     519             : 
     520           0 :         return field;
     521             : }
     522             : 
     523             : /*
     524             :  *****************************************************************************
     525             :  *  Function: dce110_timing_generator_get_position
     526             :  *
     527             :  *  @brief
     528             :  *     Returns CRTC vertical/horizontal counters
     529             :  *
     530             :  *  @param [out] position
     531             :  *****************************************************************************
     532             :  */
     533           0 : void dce110_timing_generator_get_position(struct timing_generator *tg,
     534             :         struct crtc_position *position)
     535             : {
     536             :         uint32_t value;
     537           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     538             : 
     539           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_STATUS_POSITION));
     540             : 
     541           0 :         position->horizontal_count = get_reg_field_value(
     542             :                         value,
     543             :                         CRTC_STATUS_POSITION,
     544             :                         CRTC_HORZ_COUNT);
     545             : 
     546           0 :         position->vertical_count = get_reg_field_value(
     547             :                         value,
     548             :                         CRTC_STATUS_POSITION,
     549             :                         CRTC_VERT_COUNT);
     550             : 
     551           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_NOM_VERT_POSITION));
     552             : 
     553           0 :         position->nominal_vcount = get_reg_field_value(
     554             :                         value,
     555             :                         CRTC_NOM_VERT_POSITION,
     556             :                         CRTC_VERT_COUNT_NOM);
     557           0 : }
     558             : 
     559             : /*
     560             :  *****************************************************************************
     561             :  *  Function: get_crtc_scanoutpos
     562             :  *
     563             :  *  @brief
     564             :  *     Returns CRTC vertical/horizontal counters
     565             :  *
     566             :  *  @param [out] vpos, hpos
     567             :  *****************************************************************************
     568             :  */
     569           0 : void dce110_timing_generator_get_crtc_scanoutpos(
     570             :         struct timing_generator *tg,
     571             :         uint32_t *v_blank_start,
     572             :         uint32_t *v_blank_end,
     573             :         uint32_t *h_position,
     574             :         uint32_t *v_position)
     575             : {
     576           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     577             :         struct crtc_position position;
     578             : 
     579           0 :         uint32_t value  = dm_read_reg(tg->ctx,
     580             :                         CRTC_REG(mmCRTC_V_BLANK_START_END));
     581             : 
     582           0 :         *v_blank_start = get_reg_field_value(value,
     583             :                                              CRTC_V_BLANK_START_END,
     584             :                                              CRTC_V_BLANK_START);
     585           0 :         *v_blank_end = get_reg_field_value(value,
     586             :                                            CRTC_V_BLANK_START_END,
     587             :                                            CRTC_V_BLANK_END);
     588             : 
     589           0 :         dce110_timing_generator_get_position(
     590             :                         tg, &position);
     591             : 
     592           0 :         *h_position = position.horizontal_count;
     593           0 :         *v_position = position.vertical_count;
     594           0 : }
     595             : 
     596             : /* TODO: is it safe to assume that mask/shift of Primary and Underlay
     597             :  * are the same?
     598             :  * For example: today CRTC_H_TOTAL == CRTCV_H_TOTAL but is it always
     599             :  * guaranteed? */
     600           0 : void dce110_timing_generator_program_blanking(
     601             :         struct timing_generator *tg,
     602             :         const struct dc_crtc_timing *timing)
     603             : {
     604           0 :         uint32_t vsync_offset = timing->v_border_bottom +
     605           0 :                         timing->v_front_porch;
     606           0 :         uint32_t v_sync_start =timing->v_addressable + vsync_offset;
     607             : 
     608           0 :         uint32_t hsync_offset = timing->h_border_right +
     609           0 :                         timing->h_front_porch;
     610           0 :         uint32_t h_sync_start = timing->h_addressable + hsync_offset;
     611           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     612             : 
     613           0 :         struct dc_context *ctx = tg->ctx;
     614           0 :         uint32_t value = 0;
     615           0 :         uint32_t addr = 0;
     616           0 :         uint32_t tmp = 0;
     617             : 
     618           0 :         addr = CRTC_REG(mmCRTC_H_TOTAL);
     619           0 :         value = dm_read_reg(ctx, addr);
     620           0 :         set_reg_field_value(
     621             :                 value,
     622             :                 timing->h_total - 1,
     623             :                 CRTC_H_TOTAL,
     624             :                 CRTC_H_TOTAL);
     625           0 :         dm_write_reg(ctx, addr, value);
     626             : 
     627           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL);
     628           0 :         value = dm_read_reg(ctx, addr);
     629           0 :         set_reg_field_value(
     630             :                 value,
     631             :                 timing->v_total - 1,
     632             :                 CRTC_V_TOTAL,
     633             :                 CRTC_V_TOTAL);
     634           0 :         dm_write_reg(ctx, addr, value);
     635             : 
     636             :         /* In case of V_TOTAL_CONTROL is on, make sure V_TOTAL_MAX and
     637             :          * V_TOTAL_MIN are equal to V_TOTAL.
     638             :          */
     639           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_MAX);
     640           0 :         value = dm_read_reg(ctx, addr);
     641           0 :         set_reg_field_value(
     642             :                 value,
     643             :                 timing->v_total - 1,
     644             :                 CRTC_V_TOTAL_MAX,
     645             :                 CRTC_V_TOTAL_MAX);
     646           0 :         dm_write_reg(ctx, addr, value);
     647             : 
     648           0 :         addr = CRTC_REG(mmCRTC_V_TOTAL_MIN);
     649           0 :         value = dm_read_reg(ctx, addr);
     650           0 :         set_reg_field_value(
     651             :                 value,
     652             :                 timing->v_total - 1,
     653             :                 CRTC_V_TOTAL_MIN,
     654             :                 CRTC_V_TOTAL_MIN);
     655           0 :         dm_write_reg(ctx, addr, value);
     656             : 
     657           0 :         addr = CRTC_REG(mmCRTC_H_BLANK_START_END);
     658           0 :         value = dm_read_reg(ctx, addr);
     659             : 
     660           0 :         tmp = timing->h_total -
     661           0 :                 (h_sync_start + timing->h_border_left);
     662             : 
     663           0 :         set_reg_field_value(
     664             :                 value,
     665             :                 tmp,
     666             :                 CRTC_H_BLANK_START_END,
     667             :                 CRTC_H_BLANK_END);
     668             : 
     669           0 :         tmp = tmp + timing->h_addressable +
     670           0 :                 timing->h_border_left + timing->h_border_right;
     671             : 
     672           0 :         set_reg_field_value(
     673             :                 value,
     674             :                 tmp,
     675             :                 CRTC_H_BLANK_START_END,
     676             :                 CRTC_H_BLANK_START);
     677             : 
     678           0 :         dm_write_reg(ctx, addr, value);
     679             : 
     680           0 :         addr = CRTC_REG(mmCRTC_V_BLANK_START_END);
     681           0 :         value = dm_read_reg(ctx, addr);
     682             : 
     683           0 :         tmp = timing->v_total - (v_sync_start + timing->v_border_top);
     684             : 
     685           0 :         set_reg_field_value(
     686             :                 value,
     687             :                 tmp,
     688             :                 CRTC_V_BLANK_START_END,
     689             :                 CRTC_V_BLANK_END);
     690             : 
     691           0 :         tmp = tmp + timing->v_addressable + timing->v_border_top +
     692           0 :                 timing->v_border_bottom;
     693             : 
     694           0 :         set_reg_field_value(
     695             :                 value,
     696             :                 tmp,
     697             :                 CRTC_V_BLANK_START_END,
     698             :                 CRTC_V_BLANK_START);
     699             : 
     700           0 :         dm_write_reg(ctx, addr, value);
     701           0 : }
     702             : 
     703           0 : void dce110_timing_generator_set_test_pattern(
     704             :         struct timing_generator *tg,
     705             :         /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
     706             :          * because this is not DP-specific (which is probably somewhere in DP
     707             :          * encoder) */
     708             :         enum controller_dp_test_pattern test_pattern,
     709             :         enum dc_color_depth color_depth)
     710             : {
     711           0 :         struct dc_context *ctx = tg->ctx;
     712             :         uint32_t value;
     713             :         uint32_t addr;
     714           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
     715             :         enum test_pattern_color_format bit_depth;
     716             :         enum test_pattern_dyn_range dyn_range;
     717             :         enum test_pattern_mode mode;
     718             :         /* color ramp generator mixes 16-bits color */
     719           0 :         uint32_t src_bpc = 16;
     720             :         /* requested bpc */
     721             :         uint32_t dst_bpc;
     722             :         uint32_t index;
     723             :         /* RGB values of the color bars.
     724             :          * Produce two RGB colors: RGB0 - white (all Fs)
     725             :          * and RGB1 - black (all 0s)
     726             :          * (three RGB components for two colors)
     727             :          */
     728           0 :         uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
     729             :                                                 0x0000, 0x0000};
     730             :         /* dest color (converted to the specified color format) */
     731             :         uint16_t dst_color[6];
     732             :         uint32_t inc_base;
     733             : 
     734             :         /* translate to bit depth */
     735             :         switch (color_depth) {
     736             :         case COLOR_DEPTH_666:
     737             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
     738             :         break;
     739             :         case COLOR_DEPTH_888:
     740             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
     741             :         break;
     742             :         case COLOR_DEPTH_101010:
     743             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
     744             :         break;
     745             :         case COLOR_DEPTH_121212:
     746             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
     747             :         break;
     748             :         default:
     749             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
     750             :         break;
     751             :         }
     752             : 
     753           0 :         switch (test_pattern) {
     754             :         case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
     755             :         case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
     756             :         {
     757           0 :                 dyn_range = (test_pattern ==
     758             :                                 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
     759           0 :                                 TEST_PATTERN_DYN_RANGE_CEA :
     760             :                                 TEST_PATTERN_DYN_RANGE_VESA);
     761           0 :                 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
     762           0 :                 value = 0;
     763           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
     764             : 
     765           0 :                 set_reg_field_value(
     766             :                         value,
     767             :                         6,
     768             :                         CRTC_TEST_PATTERN_PARAMETERS,
     769             :                         CRTC_TEST_PATTERN_VRES);
     770           0 :                 set_reg_field_value(
     771             :                         value,
     772             :                         6,
     773             :                         CRTC_TEST_PATTERN_PARAMETERS,
     774             :                         CRTC_TEST_PATTERN_HRES);
     775             : 
     776           0 :                 dm_write_reg(ctx, addr, value);
     777             : 
     778           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
     779           0 :                 value = 0;
     780             : 
     781           0 :                 set_reg_field_value(
     782             :                         value,
     783             :                         1,
     784             :                         CRTC_TEST_PATTERN_CONTROL,
     785             :                         CRTC_TEST_PATTERN_EN);
     786             : 
     787           0 :                 set_reg_field_value(
     788             :                         value,
     789             :                         mode,
     790             :                         CRTC_TEST_PATTERN_CONTROL,
     791             :                         CRTC_TEST_PATTERN_MODE);
     792             : 
     793           0 :                 set_reg_field_value(
     794             :                         value,
     795             :                         dyn_range,
     796             :                         CRTC_TEST_PATTERN_CONTROL,
     797             :                         CRTC_TEST_PATTERN_DYNAMIC_RANGE);
     798           0 :                 set_reg_field_value(
     799             :                         value,
     800             :                         bit_depth,
     801             :                         CRTC_TEST_PATTERN_CONTROL,
     802             :                         CRTC_TEST_PATTERN_COLOR_FORMAT);
     803           0 :                 dm_write_reg(ctx, addr, value);
     804             :         }
     805           0 :         break;
     806             : 
     807             :         case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
     808             :         case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
     809             :         {
     810           0 :                 mode = (test_pattern ==
     811             :                         CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
     812           0 :                         TEST_PATTERN_MODE_VERTICALBARS :
     813             :                         TEST_PATTERN_MODE_HORIZONTALBARS);
     814             : 
     815             :                 switch (bit_depth) {
     816             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
     817             :                         dst_bpc = 6;
     818             :                 break;
     819             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
     820             :                         dst_bpc = 8;
     821             :                 break;
     822             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
     823             :                         dst_bpc = 10;
     824             :                 break;
     825             :                 default:
     826             :                         dst_bpc = 8;
     827             :                 break;
     828             :                 }
     829             : 
     830             :                 /* adjust color to the required colorFormat */
     831           0 :                 for (index = 0; index < 6; index++) {
     832             :                         /* dst = 2^dstBpc * src / 2^srcBpc = src >>
     833             :                          * (srcBpc - dstBpc);
     834             :                          */
     835           0 :                         dst_color[index] =
     836           0 :                                 src_color[index] >> (src_bpc - dst_bpc);
     837             :                 /* CRTC_TEST_PATTERN_DATA has 16 bits,
     838             :                  * lowest 6 are hardwired to ZERO
     839             :                  * color bits should be left aligned aligned to MSB
     840             :                  * XXXXXXXXXX000000 for 10 bit,
     841             :                  * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
     842             :                  */
     843           0 :                         dst_color[index] <<= (16 - dst_bpc);
     844             :                 }
     845             : 
     846           0 :                 value = 0;
     847           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
     848           0 :                 dm_write_reg(ctx, addr, value);
     849             : 
     850             :                 /* We have to write the mask before data, similar to pipeline.
     851             :                  * For example, for 8 bpc, if we want RGB0 to be magenta,
     852             :                  * and RGB1 to be cyan,
     853             :                  * we need to make 7 writes:
     854             :                  * MASK   DATA
     855             :                  * 000001 00000000 00000000                     set mask to R0
     856             :                  * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
     857             :                  * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
     858             :                  * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
     859             :                  * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
     860             :                  * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
     861             :                  * 100000 11111111 00000000     B1 255, 0xFF00
     862             :                  *
     863             :                  * we will make a loop of 6 in which we prepare the mask,
     864             :                  * then write, then prepare the color for next write.
     865             :                  * first iteration will write mask only,
     866             :                  * but each next iteration color prepared in
     867             :                  * previous iteration will be written within new mask,
     868             :                  * the last component will written separately,
     869             :                  * mask is not changing between 6th and 7th write
     870             :                  * and color will be prepared by last iteration
     871             :                  */
     872             : 
     873             :                 /* write color, color values mask in CRTC_TEST_PATTERN_MASK
     874             :                  * is B1, G1, R1, B0, G0, R0
     875             :                  */
     876           0 :                 value = 0;
     877           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
     878           0 :                 for (index = 0; index < 6; index++) {
     879             :                         /* prepare color mask, first write PATTERN_DATA
     880             :                          * will have all zeros
     881             :                          */
     882           0 :                         set_reg_field_value(
     883             :                                 value,
     884             :                                 (1 << index),
     885             :                                 CRTC_TEST_PATTERN_COLOR,
     886             :                                 CRTC_TEST_PATTERN_MASK);
     887             :                         /* write color component */
     888           0 :                         dm_write_reg(ctx, addr, value);
     889             :                         /* prepare next color component,
     890             :                          * will be written in the next iteration
     891             :                          */
     892           0 :                         set_reg_field_value(
     893             :                                 value,
     894             :                                 dst_color[index],
     895             :                                 CRTC_TEST_PATTERN_COLOR,
     896             :                                 CRTC_TEST_PATTERN_DATA);
     897             :                 }
     898             :                 /* write last color component,
     899             :                  * it's been already prepared in the loop
     900             :                  */
     901           0 :                 dm_write_reg(ctx, addr, value);
     902             : 
     903             :                 /* enable test pattern */
     904           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
     905           0 :                 value = 0;
     906             : 
     907           0 :                 set_reg_field_value(
     908             :                         value,
     909             :                         1,
     910             :                         CRTC_TEST_PATTERN_CONTROL,
     911             :                         CRTC_TEST_PATTERN_EN);
     912             : 
     913           0 :                 set_reg_field_value(
     914             :                         value,
     915             :                         mode,
     916             :                         CRTC_TEST_PATTERN_CONTROL,
     917             :                         CRTC_TEST_PATTERN_MODE);
     918             : 
     919           0 :                 set_reg_field_value(
     920             :                         value,
     921             :                         0,
     922             :                         CRTC_TEST_PATTERN_CONTROL,
     923             :                         CRTC_TEST_PATTERN_DYNAMIC_RANGE);
     924             : 
     925           0 :                 set_reg_field_value(
     926             :                         value,
     927             :                         bit_depth,
     928             :                         CRTC_TEST_PATTERN_CONTROL,
     929             :                         CRTC_TEST_PATTERN_COLOR_FORMAT);
     930             : 
     931           0 :                 dm_write_reg(ctx, addr, value);
     932             :         }
     933           0 :         break;
     934             : 
     935             :         case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
     936             :         {
     937           0 :                 mode = (bit_depth ==
     938             :                         TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
     939           0 :                         TEST_PATTERN_MODE_DUALRAMP_RGB :
     940             :                         TEST_PATTERN_MODE_SINGLERAMP_RGB);
     941             : 
     942             :                 switch (bit_depth) {
     943             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
     944             :                         dst_bpc = 6;
     945             :                 break;
     946             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
     947             :                         dst_bpc = 8;
     948             :                 break;
     949             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
     950             :                         dst_bpc = 10;
     951             :                 break;
     952             :                 default:
     953             :                         dst_bpc = 8;
     954             :                 break;
     955             :                 }
     956             : 
     957             :                 /* increment for the first ramp for one color gradation
     958             :                  * 1 gradation for 6-bit color is 2^10
     959             :                  * gradations in 16-bit color
     960             :                  */
     961           0 :                 inc_base = (src_bpc - dst_bpc);
     962             : 
     963           0 :                 value = 0;
     964           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS);
     965             : 
     966           0 :                 switch (bit_depth) {
     967             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
     968             :                 {
     969           0 :                         set_reg_field_value(
     970             :                                 value,
     971             :                                 inc_base,
     972             :                                 CRTC_TEST_PATTERN_PARAMETERS,
     973             :                                 CRTC_TEST_PATTERN_INC0);
     974           0 :                         set_reg_field_value(
     975             :                                 value,
     976             :                                 0,
     977             :                                 CRTC_TEST_PATTERN_PARAMETERS,
     978             :                                 CRTC_TEST_PATTERN_INC1);
     979           0 :                         set_reg_field_value(
     980             :                                 value,
     981             :                                 6,
     982             :                                 CRTC_TEST_PATTERN_PARAMETERS,
     983             :                                 CRTC_TEST_PATTERN_HRES);
     984           0 :                         set_reg_field_value(
     985             :                                 value,
     986             :                                 6,
     987             :                                 CRTC_TEST_PATTERN_PARAMETERS,
     988             :                                 CRTC_TEST_PATTERN_VRES);
     989           0 :                         set_reg_field_value(
     990             :                                 value,
     991             :                                 0,
     992             :                                 CRTC_TEST_PATTERN_PARAMETERS,
     993             :                                 CRTC_TEST_PATTERN_RAMP0_OFFSET);
     994             :                 }
     995           0 :                 break;
     996             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
     997             :                 {
     998           0 :                         set_reg_field_value(
     999             :                                 value,
    1000             :                                 inc_base,
    1001             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1002             :                                 CRTC_TEST_PATTERN_INC0);
    1003           0 :                         set_reg_field_value(
    1004             :                                 value,
    1005             :                                 0,
    1006             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1007             :                                 CRTC_TEST_PATTERN_INC1);
    1008           0 :                         set_reg_field_value(
    1009             :                                 value,
    1010             :                                 8,
    1011             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1012             :                                 CRTC_TEST_PATTERN_HRES);
    1013           0 :                         set_reg_field_value(
    1014             :                                 value,
    1015             :                                 6,
    1016             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1017             :                                 CRTC_TEST_PATTERN_VRES);
    1018           0 :                         set_reg_field_value(
    1019             :                                 value,
    1020             :                                 0,
    1021             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1022             :                                 CRTC_TEST_PATTERN_RAMP0_OFFSET);
    1023             :                 }
    1024           0 :                 break;
    1025             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
    1026             :                 {
    1027           0 :                         set_reg_field_value(
    1028             :                                 value,
    1029             :                                 inc_base,
    1030             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1031             :                                 CRTC_TEST_PATTERN_INC0);
    1032           0 :                         set_reg_field_value(
    1033             :                                 value,
    1034             :                                 inc_base + 2,
    1035             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1036             :                                 CRTC_TEST_PATTERN_INC1);
    1037           0 :                         set_reg_field_value(
    1038             :                                 value,
    1039             :                                 8,
    1040             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1041             :                                 CRTC_TEST_PATTERN_HRES);
    1042           0 :                         set_reg_field_value(
    1043             :                                 value,
    1044             :                                 5,
    1045             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1046             :                                 CRTC_TEST_PATTERN_VRES);
    1047           0 :                         set_reg_field_value(
    1048             :                                 value,
    1049             :                                 384 << 6,
    1050             :                                 CRTC_TEST_PATTERN_PARAMETERS,
    1051             :                                 CRTC_TEST_PATTERN_RAMP0_OFFSET);
    1052             :                 }
    1053           0 :                 break;
    1054             :                 default:
    1055             :                 break;
    1056             :                 }
    1057           0 :                 dm_write_reg(ctx, addr, value);
    1058             : 
    1059           0 :                 value = 0;
    1060           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_COLOR);
    1061           0 :                 dm_write_reg(ctx, addr, value);
    1062             : 
    1063             :                 /* enable test pattern */
    1064           0 :                 addr = CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL);
    1065           0 :                 value = 0;
    1066             : 
    1067           0 :                 set_reg_field_value(
    1068             :                         value,
    1069             :                         1,
    1070             :                         CRTC_TEST_PATTERN_CONTROL,
    1071             :                         CRTC_TEST_PATTERN_EN);
    1072             : 
    1073           0 :                 set_reg_field_value(
    1074             :                         value,
    1075             :                         mode,
    1076             :                         CRTC_TEST_PATTERN_CONTROL,
    1077             :                         CRTC_TEST_PATTERN_MODE);
    1078             : 
    1079           0 :                 set_reg_field_value(
    1080             :                         value,
    1081             :                         0,
    1082             :                         CRTC_TEST_PATTERN_CONTROL,
    1083             :                         CRTC_TEST_PATTERN_DYNAMIC_RANGE);
    1084             :                 /* add color depth translation here */
    1085           0 :                 set_reg_field_value(
    1086             :                         value,
    1087             :                         bit_depth,
    1088             :                         CRTC_TEST_PATTERN_CONTROL,
    1089             :                         CRTC_TEST_PATTERN_COLOR_FORMAT);
    1090             : 
    1091           0 :                 dm_write_reg(ctx, addr, value);
    1092             :         }
    1093           0 :         break;
    1094             :         case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
    1095             :         {
    1096           0 :                 value = 0;
    1097           0 :                 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_CONTROL), value);
    1098           0 :                 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_COLOR), value);
    1099           0 :                 dm_write_reg(ctx, CRTC_REG(mmCRTC_TEST_PATTERN_PARAMETERS),
    1100             :                                 value);
    1101             :         }
    1102           0 :         break;
    1103             :         default:
    1104             :         break;
    1105             :         }
    1106           0 : }
    1107             : 
    1108             : /*
    1109             :  * dce110_timing_generator_validate_timing
    1110             :  * The timing generators support a maximum display size of is 8192 x 8192 pixels,
    1111             :  * including both active display and blanking periods. Check H Total and V Total.
    1112             :  */
    1113           0 : bool dce110_timing_generator_validate_timing(
    1114             :         struct timing_generator *tg,
    1115             :         const struct dc_crtc_timing *timing,
    1116             :         enum signal_type signal)
    1117             : {
    1118             :         uint32_t h_blank;
    1119             :         uint32_t h_back_porch, hsync_offset, h_sync_start;
    1120             : 
    1121           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1122             : 
    1123           0 :         ASSERT(timing != NULL);
    1124             : 
    1125           0 :         if (!timing)
    1126             :                 return false;
    1127             : 
    1128           0 :         hsync_offset = timing->h_border_right + timing->h_front_porch;
    1129           0 :         h_sync_start = timing->h_addressable + hsync_offset;
    1130             : 
    1131             :         /* Currently we don't support 3D, so block all 3D timings */
    1132           0 :         if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE)
    1133             :                 return false;
    1134             : 
    1135             :         /* Temporarily blocking interlacing mode until it's supported */
    1136           0 :         if (timing->flags.INTERLACE == 1)
    1137             :                 return false;
    1138             : 
    1139             :         /* Check maximum number of pixels supported by Timing Generator
    1140             :          * (Currently will never fail, in order to fail needs display which
    1141             :          * needs more than 8192 horizontal and
    1142             :          * more than 8192 vertical total pixels)
    1143             :          */
    1144           0 :         if (timing->h_total > tg110->max_h_total ||
    1145           0 :                 timing->v_total > tg110->max_v_total)
    1146             :                 return false;
    1147             : 
    1148           0 :         h_blank = (timing->h_total - timing->h_addressable -
    1149             :                 timing->h_border_right -
    1150           0 :                 timing->h_border_left);
    1151             : 
    1152           0 :         if (h_blank < tg110->min_h_blank)
    1153             :                 return false;
    1154             : 
    1155           0 :         if (timing->h_front_porch < tg110->min_h_front_porch)
    1156             :                 return false;
    1157             : 
    1158           0 :         h_back_porch = h_blank - (h_sync_start -
    1159           0 :                 timing->h_addressable -
    1160           0 :                 timing->h_border_right -
    1161           0 :                 timing->h_sync_width);
    1162             : 
    1163           0 :         if (h_back_porch < tg110->min_h_back_porch)
    1164             :                 return false;
    1165             : 
    1166           0 :         return true;
    1167             : }
    1168             : 
    1169             : /*
    1170             :  * Wait till we are at the beginning of VBlank.
    1171             :  */
    1172           0 : void dce110_timing_generator_wait_for_vblank(struct timing_generator *tg)
    1173             : {
    1174             :         /* We want to catch beginning of VBlank here, so if the first try are
    1175             :          * in VBlank, we might be very close to Active, in this case wait for
    1176             :          * another frame
    1177             :          */
    1178           0 :         while (dce110_timing_generator_is_in_vertical_blank(tg)) {
    1179           0 :                 if (!dce110_timing_generator_is_counter_moving(tg)) {
    1180             :                         /* error - no point to wait if counter is not moving */
    1181             :                         break;
    1182             :                 }
    1183             :         }
    1184             : 
    1185           0 :         while (!dce110_timing_generator_is_in_vertical_blank(tg)) {
    1186           0 :                 if (!dce110_timing_generator_is_counter_moving(tg)) {
    1187             :                         /* error - no point to wait if counter is not moving */
    1188             :                         break;
    1189             :                 }
    1190             :         }
    1191           0 : }
    1192             : 
    1193             : /*
    1194             :  * Wait till we are in VActive (anywhere in VActive)
    1195             :  */
    1196           0 : void dce110_timing_generator_wait_for_vactive(struct timing_generator *tg)
    1197             : {
    1198           0 :         while (dce110_timing_generator_is_in_vertical_blank(tg)) {
    1199           0 :                 if (!dce110_timing_generator_is_counter_moving(tg)) {
    1200             :                         /* error - no point to wait if counter is not moving */
    1201             :                         break;
    1202             :                 }
    1203             :         }
    1204           0 : }
    1205             : 
    1206             : /*
    1207             :  *****************************************************************************
    1208             :  *  Function: dce110_timing_generator_setup_global_swap_lock
    1209             :  *
    1210             :  *  @brief
    1211             :  *     Setups Global Swap Lock group for current pipe
    1212             :  *     Pipe can join or leave GSL group, become a TimingServer or TimingClient
    1213             :  *
    1214             :  *  @param [in] gsl_params: setup data
    1215             :  *****************************************************************************
    1216             :  */
    1217           0 : void dce110_timing_generator_setup_global_swap_lock(
    1218             :         struct timing_generator *tg,
    1219             :         const struct dcp_gsl_params *gsl_params)
    1220             : {
    1221             :         uint32_t value;
    1222           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1223           0 :         uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
    1224           0 :         uint32_t check_point = FLIP_READY_BACK_LOOKUP;
    1225             : 
    1226           0 :         value = dm_read_reg(tg->ctx, address);
    1227             : 
    1228             :         /* This pipe will belong to GSL Group zero. */
    1229           0 :         set_reg_field_value(value,
    1230             :                             1,
    1231             :                             DCP_GSL_CONTROL,
    1232             :                             DCP_GSL0_EN);
    1233             : 
    1234           0 :         set_reg_field_value(value,
    1235             :                             gsl_params->gsl_master == tg->inst,
    1236             :                             DCP_GSL_CONTROL,
    1237             :                             DCP_GSL_MASTER_EN);
    1238             : 
    1239           0 :         set_reg_field_value(value,
    1240             :                             HFLIP_READY_DELAY,
    1241             :                             DCP_GSL_CONTROL,
    1242             :                             DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
    1243             : 
    1244             :         /* Keep signal low (pending high) during 6 lines.
    1245             :          * Also defines minimum interval before re-checking signal. */
    1246           0 :         set_reg_field_value(value,
    1247             :                             HFLIP_CHECK_DELAY,
    1248             :                             DCP_GSL_CONTROL,
    1249             :                             DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
    1250             : 
    1251           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmDCP_GSL_CONTROL), value);
    1252           0 :         value = 0;
    1253             : 
    1254           0 :         set_reg_field_value(value,
    1255             :                             gsl_params->gsl_master,
    1256             :                             DCIO_GSL0_CNTL,
    1257             :                             DCIO_GSL0_VSYNC_SEL);
    1258             : 
    1259           0 :         set_reg_field_value(value,
    1260             :                             0,
    1261             :                             DCIO_GSL0_CNTL,
    1262             :                             DCIO_GSL0_TIMING_SYNC_SEL);
    1263             : 
    1264           0 :         set_reg_field_value(value,
    1265             :                             0,
    1266             :                             DCIO_GSL0_CNTL,
    1267             :                             DCIO_GSL0_GLOBAL_UNLOCK_SEL);
    1268             : 
    1269           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmDCIO_GSL0_CNTL), value);
    1270             : 
    1271             : 
    1272             :         {
    1273             :                 uint32_t value_crtc_vtotal;
    1274             : 
    1275           0 :                 value_crtc_vtotal = dm_read_reg(tg->ctx,
    1276             :                                 CRTC_REG(mmCRTC_V_TOTAL));
    1277             : 
    1278           0 :                 set_reg_field_value(value,
    1279             :                                     0,/* DCP_GSL_PURPOSE_SURFACE_FLIP */
    1280             :                                     DCP_GSL_CONTROL,
    1281             :                                     DCP_GSL_SYNC_SOURCE);
    1282             : 
    1283             :                 /* Checkpoint relative to end of frame */
    1284           0 :                 check_point = get_reg_field_value(value_crtc_vtotal,
    1285             :                                                   CRTC_V_TOTAL,
    1286             :                                                   CRTC_V_TOTAL);
    1287             : 
    1288           0 :                 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_GSL_WINDOW), 0);
    1289             :         }
    1290             : 
    1291           0 :         set_reg_field_value(value,
    1292             :                             1,
    1293             :                             DCP_GSL_CONTROL,
    1294             :                             DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
    1295             : 
    1296           0 :         dm_write_reg(tg->ctx, address, value);
    1297             : 
    1298             :         /********************************************************************/
    1299           0 :         address = CRTC_REG(mmCRTC_GSL_CONTROL);
    1300             : 
    1301           0 :         value = dm_read_reg(tg->ctx, address);
    1302           0 :         set_reg_field_value(value,
    1303             :                             check_point - FLIP_READY_BACK_LOOKUP,
    1304             :                             CRTC_GSL_CONTROL,
    1305             :                             CRTC_GSL_CHECK_LINE_NUM);
    1306             : 
    1307           0 :         set_reg_field_value(value,
    1308             :                             VFLIP_READY_DELAY,
    1309             :                             CRTC_GSL_CONTROL,
    1310             :                             CRTC_GSL_FORCE_DELAY);
    1311             : 
    1312           0 :         dm_write_reg(tg->ctx, address, value);
    1313           0 : }
    1314             : 
    1315           0 : void dce110_timing_generator_tear_down_global_swap_lock(
    1316             :         struct timing_generator *tg)
    1317             : {
    1318             :         /* Clear all the register writes done by
    1319             :          * dce110_timing_generator_setup_global_swap_lock
    1320             :          */
    1321             : 
    1322             :         uint32_t value;
    1323           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1324           0 :         uint32_t address = DCP_REG(mmDCP_GSL_CONTROL);
    1325             : 
    1326           0 :         value = 0;
    1327             : 
    1328             :         /* This pipe will belong to GSL Group zero. */
    1329             :         /* Settig HW default values from reg specs */
    1330           0 :         set_reg_field_value(value,
    1331             :                         0,
    1332             :                         DCP_GSL_CONTROL,
    1333             :                         DCP_GSL0_EN);
    1334             : 
    1335           0 :         set_reg_field_value(value,
    1336             :                         0,
    1337             :                         DCP_GSL_CONTROL,
    1338             :                         DCP_GSL_MASTER_EN);
    1339             : 
    1340           0 :         set_reg_field_value(value,
    1341             :                         0x2,
    1342             :                         DCP_GSL_CONTROL,
    1343             :                         DCP_GSL_HSYNC_FLIP_FORCE_DELAY);
    1344             : 
    1345           0 :         set_reg_field_value(value,
    1346             :                         0x6,
    1347             :                         DCP_GSL_CONTROL,
    1348             :                         DCP_GSL_HSYNC_FLIP_CHECK_DELAY);
    1349             : 
    1350             :         /* Restore DCP_GSL_PURPOSE_SURFACE_FLIP */
    1351             :         {
    1352           0 :                 dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_V_TOTAL));
    1353             : 
    1354           0 :                 set_reg_field_value(value,
    1355             :                                 0,
    1356             :                                 DCP_GSL_CONTROL,
    1357             :                                 DCP_GSL_SYNC_SOURCE);
    1358             :         }
    1359             : 
    1360           0 :         set_reg_field_value(value,
    1361             :                         0,
    1362             :                         DCP_GSL_CONTROL,
    1363             :                         DCP_GSL_DELAY_SURFACE_UPDATE_PENDING);
    1364             : 
    1365           0 :         dm_write_reg(tg->ctx, address, value);
    1366             : 
    1367             :         /********************************************************************/
    1368           0 :         address = CRTC_REG(mmCRTC_GSL_CONTROL);
    1369             : 
    1370           0 :         value = 0;
    1371           0 :         set_reg_field_value(value,
    1372             :                         0,
    1373             :                         CRTC_GSL_CONTROL,
    1374             :                         CRTC_GSL_CHECK_LINE_NUM);
    1375             : 
    1376           0 :         set_reg_field_value(value,
    1377             :                         0x2,
    1378             :                         CRTC_GSL_CONTROL,
    1379             :                         CRTC_GSL_FORCE_DELAY);
    1380             : 
    1381           0 :         dm_write_reg(tg->ctx, address, value);
    1382           0 : }
    1383             : /*
    1384             :  *****************************************************************************
    1385             :  *  Function: is_counter_moving
    1386             :  *
    1387             :  *  @brief
    1388             :  *     check if the timing generator is currently going
    1389             :  *
    1390             :  *  @return
    1391             :  *     true if currently going, false if currently paused or stopped.
    1392             :  *
    1393             :  *****************************************************************************
    1394             :  */
    1395           0 : bool dce110_timing_generator_is_counter_moving(struct timing_generator *tg)
    1396             : {
    1397             :         struct crtc_position position1, position2;
    1398             : 
    1399           0 :         tg->funcs->get_position(tg, &position1);
    1400           0 :         tg->funcs->get_position(tg, &position2);
    1401             : 
    1402           0 :         if (position1.horizontal_count == position2.horizontal_count &&
    1403           0 :                 position1.vertical_count == position2.vertical_count)
    1404             :                 return false;
    1405             :         else
    1406           0 :                 return true;
    1407             : }
    1408             : 
    1409           0 : void dce110_timing_generator_enable_advanced_request(
    1410             :         struct timing_generator *tg,
    1411             :         bool enable,
    1412             :         const struct dc_crtc_timing *timing)
    1413             : {
    1414           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1415           0 :         uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL);
    1416           0 :         uint32_t value = dm_read_reg(tg->ctx, addr);
    1417             : 
    1418           0 :         if (enable) {
    1419           0 :                 set_reg_field_value(
    1420             :                         value,
    1421             :                         0,
    1422             :                         CRTC_START_LINE_CONTROL,
    1423             :                         CRTC_LEGACY_REQUESTOR_EN);
    1424             :         } else {
    1425           0 :                 set_reg_field_value(
    1426             :                         value,
    1427             :                         1,
    1428             :                         CRTC_START_LINE_CONTROL,
    1429             :                         CRTC_LEGACY_REQUESTOR_EN);
    1430             :         }
    1431             : 
    1432           0 :         if ((timing->v_sync_width + timing->v_front_porch) <= 3) {
    1433           0 :                 set_reg_field_value(
    1434             :                         value,
    1435             :                         3,
    1436             :                         CRTC_START_LINE_CONTROL,
    1437             :                         CRTC_ADVANCED_START_LINE_POSITION);
    1438           0 :                 set_reg_field_value(
    1439             :                         value,
    1440             :                         0,
    1441             :                         CRTC_START_LINE_CONTROL,
    1442             :                         CRTC_PREFETCH_EN);
    1443             :         } else {
    1444           0 :                 set_reg_field_value(
    1445             :                         value,
    1446             :                         4,
    1447             :                         CRTC_START_LINE_CONTROL,
    1448             :                         CRTC_ADVANCED_START_LINE_POSITION);
    1449           0 :                 set_reg_field_value(
    1450             :                         value,
    1451             :                         1,
    1452             :                         CRTC_START_LINE_CONTROL,
    1453             :                         CRTC_PREFETCH_EN);
    1454             :         }
    1455             : 
    1456           0 :         set_reg_field_value(
    1457             :                 value,
    1458             :                 1,
    1459             :                 CRTC_START_LINE_CONTROL,
    1460             :                 CRTC_PROGRESSIVE_START_LINE_EARLY);
    1461             : 
    1462           0 :         set_reg_field_value(
    1463             :                 value,
    1464             :                 1,
    1465             :                 CRTC_START_LINE_CONTROL,
    1466             :                 CRTC_INTERLACE_START_LINE_EARLY);
    1467             : 
    1468           0 :         dm_write_reg(tg->ctx, addr, value);
    1469           0 : }
    1470             : 
    1471             : /*TODO: Figure out if we need this function. */
    1472           0 : void dce110_timing_generator_set_lock_master(struct timing_generator *tg,
    1473             :                 bool lock)
    1474             : {
    1475           0 :         struct dc_context *ctx = tg->ctx;
    1476           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1477           0 :         uint32_t addr = CRTC_REG(mmCRTC_MASTER_UPDATE_LOCK);
    1478           0 :         uint32_t value = dm_read_reg(ctx, addr);
    1479             : 
    1480           0 :         set_reg_field_value(
    1481             :                 value,
    1482             :                 lock ? 1 : 0,
    1483             :                 CRTC_MASTER_UPDATE_LOCK,
    1484             :                 MASTER_UPDATE_LOCK);
    1485             : 
    1486           0 :         dm_write_reg(ctx, addr, value);
    1487           0 : }
    1488             : 
    1489           0 : void dce110_timing_generator_enable_reset_trigger(
    1490             :         struct timing_generator *tg,
    1491             :         int source_tg_inst)
    1492             : {
    1493             :         uint32_t value;
    1494           0 :         uint32_t rising_edge = 0;
    1495           0 :         uint32_t falling_edge = 0;
    1496           0 :         enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
    1497           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1498             : 
    1499             :         /* Setup trigger edge */
    1500             :         {
    1501           0 :                 uint32_t pol_value = dm_read_reg(tg->ctx,
    1502             :                                 CRTC_REG(mmCRTC_V_SYNC_A_CNTL));
    1503             : 
    1504             :                 /* Register spec has reversed definition:
    1505             :                  *      0 for positive, 1 for negative */
    1506           0 :                 if (get_reg_field_value(pol_value,
    1507             :                                 CRTC_V_SYNC_A_CNTL,
    1508             :                                 CRTC_V_SYNC_A_POL) == 0) {
    1509             :                         rising_edge = 1;
    1510             :                 } else {
    1511           0 :                         falling_edge = 1;
    1512             :                 }
    1513             :         }
    1514             : 
    1515           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
    1516             : 
    1517           0 :         trig_src_select = TRIGGER_SOURCE_SELECT_GSL_GROUP0;
    1518             : 
    1519           0 :         set_reg_field_value(value,
    1520             :                         trig_src_select,
    1521             :                         CRTC_TRIGB_CNTL,
    1522             :                         CRTC_TRIGB_SOURCE_SELECT);
    1523             : 
    1524           0 :         set_reg_field_value(value,
    1525             :                         TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
    1526             :                         CRTC_TRIGB_CNTL,
    1527             :                         CRTC_TRIGB_POLARITY_SELECT);
    1528             : 
    1529           0 :         set_reg_field_value(value,
    1530             :                         rising_edge,
    1531             :                         CRTC_TRIGB_CNTL,
    1532             :                         CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
    1533             : 
    1534           0 :         set_reg_field_value(value,
    1535             :                         falling_edge,
    1536             :                         CRTC_TRIGB_CNTL,
    1537             :                         CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
    1538             : 
    1539           0 :         set_reg_field_value(value,
    1540             :                         0, /* send every signal */
    1541             :                         CRTC_TRIGB_CNTL,
    1542             :                         CRTC_TRIGB_FREQUENCY_SELECT);
    1543             : 
    1544           0 :         set_reg_field_value(value,
    1545             :                         0, /* no delay */
    1546             :                         CRTC_TRIGB_CNTL,
    1547             :                         CRTC_TRIGB_DELAY);
    1548             : 
    1549           0 :         set_reg_field_value(value,
    1550             :                         1, /* clear trigger status */
    1551             :                         CRTC_TRIGB_CNTL,
    1552             :                         CRTC_TRIGB_CLEAR);
    1553             : 
    1554           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
    1555             : 
    1556             :         /**************************************************************/
    1557             : 
    1558           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
    1559             : 
    1560           0 :         set_reg_field_value(value,
    1561             :                         2, /* force H count to H_TOTAL and V count to V_TOTAL */
    1562             :                         CRTC_FORCE_COUNT_NOW_CNTL,
    1563             :                         CRTC_FORCE_COUNT_NOW_MODE);
    1564             : 
    1565           0 :         set_reg_field_value(value,
    1566             :                         1, /* TriggerB - we never use TriggerA */
    1567             :                         CRTC_FORCE_COUNT_NOW_CNTL,
    1568             :                         CRTC_FORCE_COUNT_NOW_TRIG_SEL);
    1569             : 
    1570           0 :         set_reg_field_value(value,
    1571             :                         1, /* clear trigger status */
    1572             :                         CRTC_FORCE_COUNT_NOW_CNTL,
    1573             :                         CRTC_FORCE_COUNT_NOW_CLEAR);
    1574             : 
    1575           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
    1576           0 : }
    1577             : 
    1578           0 : void dce110_timing_generator_enable_crtc_reset(
    1579             :                 struct timing_generator *tg,
    1580             :                 int source_tg_inst,
    1581             :                 struct crtc_trigger_info *crtc_tp)
    1582             : {
    1583           0 :         uint32_t value = 0;
    1584           0 :         uint32_t rising_edge = 0;
    1585           0 :         uint32_t falling_edge = 0;
    1586           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1587             : 
    1588             :         /* Setup trigger edge */
    1589           0 :         switch (crtc_tp->event) {
    1590             :         case CRTC_EVENT_VSYNC_RISING:
    1591           0 :                         rising_edge = 1;
    1592           0 :                         break;
    1593             : 
    1594             :         case CRTC_EVENT_VSYNC_FALLING:
    1595           0 :                 falling_edge = 1;
    1596           0 :                 break;
    1597             :         }
    1598             : 
    1599           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
    1600             : 
    1601           0 :         set_reg_field_value(value,
    1602             :                             source_tg_inst,
    1603             :                             CRTC_TRIGB_CNTL,
    1604             :                             CRTC_TRIGB_SOURCE_SELECT);
    1605             : 
    1606           0 :         set_reg_field_value(value,
    1607             :                             TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
    1608             :                             CRTC_TRIGB_CNTL,
    1609             :                             CRTC_TRIGB_POLARITY_SELECT);
    1610             : 
    1611           0 :         set_reg_field_value(value,
    1612             :                             rising_edge,
    1613             :                             CRTC_TRIGB_CNTL,
    1614             :                             CRTC_TRIGB_RISING_EDGE_DETECT_CNTL);
    1615             : 
    1616           0 :         set_reg_field_value(value,
    1617             :                             falling_edge,
    1618             :                             CRTC_TRIGB_CNTL,
    1619             :                             CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL);
    1620             : 
    1621           0 :         set_reg_field_value(value,
    1622             :                             1, /* clear trigger status */
    1623             :                             CRTC_TRIGB_CNTL,
    1624             :                             CRTC_TRIGB_CLEAR);
    1625             : 
    1626           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
    1627             : 
    1628             :         /**************************************************************/
    1629             : 
    1630           0 :         switch (crtc_tp->delay) {
    1631             :         case TRIGGER_DELAY_NEXT_LINE:
    1632           0 :                 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
    1633             : 
    1634           0 :                 set_reg_field_value(value,
    1635             :                                     0, /* force H count to H_TOTAL and V count to V_TOTAL */
    1636             :                                     CRTC_FORCE_COUNT_NOW_CNTL,
    1637             :                                     CRTC_FORCE_COUNT_NOW_MODE);
    1638             : 
    1639           0 :                 set_reg_field_value(value,
    1640             :                                     0, /* TriggerB - we never use TriggerA */
    1641             :                                     CRTC_FORCE_COUNT_NOW_CNTL,
    1642             :                                     CRTC_FORCE_COUNT_NOW_TRIG_SEL);
    1643             : 
    1644           0 :                 set_reg_field_value(value,
    1645             :                                     1, /* clear trigger status */
    1646             :                                     CRTC_FORCE_COUNT_NOW_CNTL,
    1647             :                                     CRTC_FORCE_COUNT_NOW_CLEAR);
    1648             : 
    1649           0 :                 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
    1650             : 
    1651           0 :                 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
    1652             : 
    1653           0 :                 set_reg_field_value(value,
    1654             :                                     1,
    1655             :                                     CRTC_VERT_SYNC_CONTROL,
    1656             :                                     CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
    1657             : 
    1658           0 :                 set_reg_field_value(value,
    1659             :                                     2,
    1660             :                                     CRTC_VERT_SYNC_CONTROL,
    1661             :                                     CRTC_AUTO_FORCE_VSYNC_MODE);
    1662             : 
    1663           0 :                 break;
    1664             : 
    1665             :         case TRIGGER_DELAY_NEXT_PIXEL:
    1666           0 :                 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
    1667             : 
    1668           0 :                 set_reg_field_value(value,
    1669             :                                     1,
    1670             :                                     CRTC_VERT_SYNC_CONTROL,
    1671             :                                     CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
    1672             : 
    1673           0 :                 set_reg_field_value(value,
    1674             :                                     0,
    1675             :                                     CRTC_VERT_SYNC_CONTROL,
    1676             :                                     CRTC_AUTO_FORCE_VSYNC_MODE);
    1677             : 
    1678           0 :                 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
    1679             : 
    1680           0 :                 value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
    1681             : 
    1682           0 :                 set_reg_field_value(value,
    1683             :                                     2, /* force H count to H_TOTAL and V count to V_TOTAL */
    1684             :                                     CRTC_FORCE_COUNT_NOW_CNTL,
    1685             :                                     CRTC_FORCE_COUNT_NOW_MODE);
    1686             : 
    1687           0 :                 set_reg_field_value(value,
    1688             :                                     1, /* TriggerB - we never use TriggerA */
    1689             :                                     CRTC_FORCE_COUNT_NOW_CNTL,
    1690             :                                     CRTC_FORCE_COUNT_NOW_TRIG_SEL);
    1691             : 
    1692           0 :                 set_reg_field_value(value,
    1693             :                                     1, /* clear trigger status */
    1694             :                                     CRTC_FORCE_COUNT_NOW_CNTL,
    1695             :                                     CRTC_FORCE_COUNT_NOW_CLEAR);
    1696             : 
    1697           0 :                 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
    1698           0 :                 break;
    1699             :         }
    1700             : 
    1701           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE));
    1702             : 
    1703           0 :         set_reg_field_value(value,
    1704             :                             2,
    1705             :                             CRTC_MASTER_UPDATE_MODE,
    1706             :                             MASTER_UPDATE_MODE);
    1707             : 
    1708           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_MASTER_UPDATE_MODE), value);
    1709           0 : }
    1710           0 : void dce110_timing_generator_disable_reset_trigger(
    1711             :         struct timing_generator *tg)
    1712             : {
    1713             :         uint32_t value;
    1714           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1715             : 
    1716           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
    1717             : 
    1718           0 :         set_reg_field_value(value,
    1719             :                             0, /* force counter now mode is disabled */
    1720             :                             CRTC_FORCE_COUNT_NOW_CNTL,
    1721             :                             CRTC_FORCE_COUNT_NOW_MODE);
    1722             : 
    1723           0 :         set_reg_field_value(value,
    1724             :                             1, /* clear trigger status */
    1725             :                             CRTC_FORCE_COUNT_NOW_CNTL,
    1726             :                             CRTC_FORCE_COUNT_NOW_CLEAR);
    1727             : 
    1728           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL), value);
    1729             : 
    1730           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
    1731             : 
    1732           0 :         set_reg_field_value(value,
    1733             :                             1,
    1734             :                             CRTC_VERT_SYNC_CONTROL,
    1735             :                             CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR);
    1736             : 
    1737           0 :         set_reg_field_value(value,
    1738             :                             0,
    1739             :                             CRTC_VERT_SYNC_CONTROL,
    1740             :                             CRTC_AUTO_FORCE_VSYNC_MODE);
    1741             : 
    1742           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERT_SYNC_CONTROL), value);
    1743             : 
    1744             :         /********************************************************************/
    1745           0 :         value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL));
    1746             : 
    1747           0 :         set_reg_field_value(value,
    1748             :                             TRIGGER_SOURCE_SELECT_LOGIC_ZERO,
    1749             :                             CRTC_TRIGB_CNTL,
    1750             :                             CRTC_TRIGB_SOURCE_SELECT);
    1751             : 
    1752           0 :         set_reg_field_value(value,
    1753             :                             TRIGGER_POLARITY_SELECT_LOGIC_ZERO,
    1754             :                             CRTC_TRIGB_CNTL,
    1755             :                             CRTC_TRIGB_POLARITY_SELECT);
    1756             : 
    1757           0 :         set_reg_field_value(value,
    1758             :                             1, /* clear trigger status */
    1759             :                             CRTC_TRIGB_CNTL,
    1760             :                             CRTC_TRIGB_CLEAR);
    1761             : 
    1762           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_TRIGB_CNTL), value);
    1763           0 : }
    1764             : 
    1765             : /*
    1766             :  *****************************************************************************
    1767             :  *  @brief
    1768             :  *     Checks whether CRTC triggered reset occurred
    1769             :  *
    1770             :  *  @return
    1771             :  *     true if triggered reset occurred, false otherwise
    1772             :  *****************************************************************************
    1773             :  */
    1774           0 : bool dce110_timing_generator_did_triggered_reset_occur(
    1775             :         struct timing_generator *tg)
    1776             : {
    1777           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1778           0 :         uint32_t value = dm_read_reg(tg->ctx,
    1779             :                         CRTC_REG(mmCRTC_FORCE_COUNT_NOW_CNTL));
    1780           0 :         uint32_t value1 = dm_read_reg(tg->ctx,
    1781             :                         CRTC_REG(mmCRTC_VERT_SYNC_CONTROL));
    1782           0 :         bool force = get_reg_field_value(value,
    1783             :                                          CRTC_FORCE_COUNT_NOW_CNTL,
    1784             :                                          CRTC_FORCE_COUNT_NOW_OCCURRED) != 0;
    1785           0 :         bool vert_sync = get_reg_field_value(value1,
    1786             :                                              CRTC_VERT_SYNC_CONTROL,
    1787             :                                              CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED) != 0;
    1788             : 
    1789           0 :         return (force || vert_sync);
    1790             : }
    1791             : 
    1792             : /*
    1793             :  * dce110_timing_generator_disable_vga
    1794             :  * Turn OFF VGA Mode and Timing  - DxVGA_CONTROL
    1795             :  * VGA Mode and VGA Timing is used by VBIOS on CRT Monitors;
    1796             :  */
    1797           0 : void dce110_timing_generator_disable_vga(
    1798             :         struct timing_generator *tg)
    1799             : {
    1800           0 :         uint32_t addr = 0;
    1801           0 :         uint32_t value = 0;
    1802             : 
    1803           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1804             : 
    1805           0 :         switch (tg110->controller_id) {
    1806             :         case CONTROLLER_ID_D0:
    1807             :                 addr = mmD1VGA_CONTROL;
    1808             :                 break;
    1809             :         case CONTROLLER_ID_D1:
    1810             :                 addr = mmD2VGA_CONTROL;
    1811             :                 break;
    1812             :         case CONTROLLER_ID_D2:
    1813             :                 addr = mmD3VGA_CONTROL;
    1814             :                 break;
    1815             :         case CONTROLLER_ID_D3:
    1816             :                 addr = mmD4VGA_CONTROL;
    1817             :                 break;
    1818             :         case CONTROLLER_ID_D4:
    1819             :                 addr = mmD5VGA_CONTROL;
    1820             :                 break;
    1821             :         case CONTROLLER_ID_D5:
    1822             :                 addr = mmD6VGA_CONTROL;
    1823             :                 break;
    1824             :         default:
    1825             :                 break;
    1826             :         }
    1827           0 :         value = dm_read_reg(tg->ctx, addr);
    1828             : 
    1829           0 :         set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_MODE_ENABLE);
    1830           0 :         set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_TIMING_SELECT);
    1831           0 :         set_reg_field_value(
    1832             :                         value, 0, D1VGA_CONTROL, D1VGA_SYNC_POLARITY_SELECT);
    1833           0 :         set_reg_field_value(value, 0, D1VGA_CONTROL, D1VGA_OVERSCAN_COLOR_EN);
    1834             : 
    1835           0 :         dm_write_reg(tg->ctx, addr, value);
    1836           0 : }
    1837             : 
    1838             : /*
    1839             :  * set_overscan_color_black
    1840             :  *
    1841             :  * @param :black_color is one of the color space
    1842             :  *    :this routine will set overscan black color according to the color space.
    1843             :  * @return none
    1844             :  */
    1845           0 : void dce110_timing_generator_set_overscan_color_black(
    1846             :         struct timing_generator *tg,
    1847             :         const struct tg_color *color)
    1848             : {
    1849           0 :         struct dc_context *ctx = tg->ctx;
    1850             :         uint32_t addr;
    1851           0 :         uint32_t value = 0;
    1852           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1853             : 
    1854           0 :         set_reg_field_value(
    1855             :                         value,
    1856             :                         color->color_b_cb,
    1857             :                         CRTC_OVERSCAN_COLOR,
    1858             :                         CRTC_OVERSCAN_COLOR_BLUE);
    1859             : 
    1860           0 :         set_reg_field_value(
    1861             :                         value,
    1862             :                         color->color_r_cr,
    1863             :                         CRTC_OVERSCAN_COLOR,
    1864             :                         CRTC_OVERSCAN_COLOR_RED);
    1865             : 
    1866           0 :         set_reg_field_value(
    1867             :                         value,
    1868             :                         color->color_g_y,
    1869             :                         CRTC_OVERSCAN_COLOR,
    1870             :                         CRTC_OVERSCAN_COLOR_GREEN);
    1871             : 
    1872           0 :         addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
    1873           0 :         dm_write_reg(ctx, addr, value);
    1874           0 :         addr = CRTC_REG(mmCRTC_BLACK_COLOR);
    1875           0 :         dm_write_reg(ctx, addr, value);
    1876             :         /* This is desirable to have a constant DAC output voltage during the
    1877             :          * blank time that is higher than the 0 volt reference level that the
    1878             :          * DAC outputs when the NBLANK signal
    1879             :          * is asserted low, such as for output to an analog TV. */
    1880           0 :         addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
    1881           0 :         dm_write_reg(ctx, addr, value);
    1882             : 
    1883             :         /* TO DO we have to program EXT registers and we need to know LB DATA
    1884             :          * format because it is used when more 10 , i.e. 12 bits per color
    1885             :          *
    1886             :          * m_mmDxCRTC_OVERSCAN_COLOR_EXT
    1887             :          * m_mmDxCRTC_BLACK_COLOR_EXT
    1888             :          * m_mmDxCRTC_BLANK_DATA_COLOR_EXT
    1889             :          */
    1890             : 
    1891           0 : }
    1892             : 
    1893           0 : void dce110_tg_program_blank_color(struct timing_generator *tg,
    1894             :                 const struct tg_color *black_color)
    1895             : {
    1896           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1897           0 :         uint32_t addr = CRTC_REG(mmCRTC_BLACK_COLOR);
    1898           0 :         uint32_t value = dm_read_reg(tg->ctx, addr);
    1899             : 
    1900           0 :         set_reg_field_value(
    1901             :                 value,
    1902             :                 black_color->color_b_cb,
    1903             :                 CRTC_BLACK_COLOR,
    1904             :                 CRTC_BLACK_COLOR_B_CB);
    1905           0 :         set_reg_field_value(
    1906             :                 value,
    1907             :                 black_color->color_g_y,
    1908             :                 CRTC_BLACK_COLOR,
    1909             :                 CRTC_BLACK_COLOR_G_Y);
    1910           0 :         set_reg_field_value(
    1911             :                 value,
    1912             :                 black_color->color_r_cr,
    1913             :                 CRTC_BLACK_COLOR,
    1914             :                 CRTC_BLACK_COLOR_R_CR);
    1915             : 
    1916           0 :         dm_write_reg(tg->ctx, addr, value);
    1917             : 
    1918           0 :         addr = CRTC_REG(mmCRTC_BLANK_DATA_COLOR);
    1919           0 :         dm_write_reg(tg->ctx, addr, value);
    1920           0 : }
    1921             : 
    1922           0 : void dce110_tg_set_overscan_color(struct timing_generator *tg,
    1923             :         const struct tg_color *overscan_color)
    1924             : {
    1925           0 :         struct dc_context *ctx = tg->ctx;
    1926           0 :         uint32_t value = 0;
    1927             :         uint32_t addr;
    1928           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1929             : 
    1930           0 :         set_reg_field_value(
    1931             :                 value,
    1932             :                 overscan_color->color_b_cb,
    1933             :                 CRTC_OVERSCAN_COLOR,
    1934             :                 CRTC_OVERSCAN_COLOR_BLUE);
    1935             : 
    1936           0 :         set_reg_field_value(
    1937             :                 value,
    1938             :                 overscan_color->color_g_y,
    1939             :                 CRTC_OVERSCAN_COLOR,
    1940             :                 CRTC_OVERSCAN_COLOR_GREEN);
    1941             : 
    1942           0 :         set_reg_field_value(
    1943             :                 value,
    1944             :                 overscan_color->color_r_cr,
    1945             :                 CRTC_OVERSCAN_COLOR,
    1946             :                 CRTC_OVERSCAN_COLOR_RED);
    1947             : 
    1948           0 :         addr = CRTC_REG(mmCRTC_OVERSCAN_COLOR);
    1949           0 :         dm_write_reg(ctx, addr, value);
    1950           0 : }
    1951             : 
    1952           0 : void dce110_tg_program_timing(struct timing_generator *tg,
    1953             :         const struct dc_crtc_timing *timing,
    1954             :         int vready_offset,
    1955             :         int vstartup_start,
    1956             :         int vupdate_offset,
    1957             :         int vupdate_width,
    1958             :         const enum signal_type signal,
    1959             :         bool use_vbios)
    1960             : {
    1961           0 :         if (use_vbios)
    1962           0 :                 dce110_timing_generator_program_timing_generator(tg, timing);
    1963             :         else
    1964           0 :                 dce110_timing_generator_program_blanking(tg, timing);
    1965           0 : }
    1966             : 
    1967           0 : bool dce110_tg_is_blanked(struct timing_generator *tg)
    1968             : {
    1969           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1970           0 :         uint32_t value = dm_read_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL));
    1971             : 
    1972           0 :         if (get_reg_field_value(
    1973             :                         value,
    1974             :                         CRTC_BLANK_CONTROL,
    1975           0 :                         CRTC_BLANK_DATA_EN) == 1 &&
    1976           0 :                 get_reg_field_value(
    1977             :                         value,
    1978             :                         CRTC_BLANK_CONTROL,
    1979             :                         CRTC_CURRENT_BLANK_STATE) == 1)
    1980             :                 return true;
    1981             :         return false;
    1982             : }
    1983             : 
    1984           0 : void dce110_tg_set_blank(struct timing_generator *tg,
    1985             :                 bool enable_blanking)
    1986             : {
    1987           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    1988           0 :         uint32_t value = 0;
    1989             : 
    1990           0 :         set_reg_field_value(
    1991             :                 value,
    1992             :                 1,
    1993             :                 CRTC_DOUBLE_BUFFER_CONTROL,
    1994             :                 CRTC_BLANK_DATA_DOUBLE_BUFFER_EN);
    1995             : 
    1996           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_DOUBLE_BUFFER_CONTROL), value);
    1997           0 :         value = 0;
    1998             : 
    1999           0 :         if (enable_blanking) {
    2000           0 :                 set_reg_field_value(
    2001             :                         value,
    2002             :                         1,
    2003             :                         CRTC_BLANK_CONTROL,
    2004             :                         CRTC_BLANK_DATA_EN);
    2005             : 
    2006           0 :                 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), value);
    2007             : 
    2008             :         } else
    2009           0 :                 dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_BLANK_CONTROL), 0);
    2010           0 : }
    2011             : 
    2012           0 : bool dce110_tg_validate_timing(struct timing_generator *tg,
    2013             :         const struct dc_crtc_timing *timing)
    2014             : {
    2015           0 :         return dce110_timing_generator_validate_timing(tg, timing, SIGNAL_TYPE_NONE);
    2016             : }
    2017             : 
    2018           0 : void dce110_tg_wait_for_state(struct timing_generator *tg,
    2019             :         enum crtc_state state)
    2020             : {
    2021           0 :         switch (state) {
    2022             :         case CRTC_STATE_VBLANK:
    2023           0 :                 dce110_timing_generator_wait_for_vblank(tg);
    2024           0 :                 break;
    2025             : 
    2026             :         case CRTC_STATE_VACTIVE:
    2027           0 :                 dce110_timing_generator_wait_for_vactive(tg);
    2028           0 :                 break;
    2029             : 
    2030             :         default:
    2031             :                 break;
    2032             :         }
    2033           0 : }
    2034             : 
    2035           0 : void dce110_tg_set_colors(struct timing_generator *tg,
    2036             :         const struct tg_color *blank_color,
    2037             :         const struct tg_color *overscan_color)
    2038             : {
    2039           0 :         if (blank_color != NULL)
    2040           0 :                 dce110_tg_program_blank_color(tg, blank_color);
    2041           0 :         if (overscan_color != NULL)
    2042           0 :                 dce110_tg_set_overscan_color(tg, overscan_color);
    2043           0 : }
    2044             : 
    2045             : /* Gets first line of blank region of the display timing for CRTC
    2046             :  * and programms is as a trigger to fire vertical interrupt
    2047             :  */
    2048           0 : bool dce110_arm_vert_intr(struct timing_generator *tg, uint8_t width)
    2049             : {
    2050           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    2051           0 :         uint32_t v_blank_start = 0;
    2052           0 :         uint32_t v_blank_end = 0;
    2053           0 :         uint32_t val = 0;
    2054             :         uint32_t h_position, v_position;
    2055             : 
    2056           0 :         tg->funcs->get_scanoutpos(
    2057             :                         tg,
    2058             :                         &v_blank_start,
    2059             :                         &v_blank_end,
    2060             :                         &h_position,
    2061             :                         &v_position);
    2062             : 
    2063           0 :         if (v_blank_start == 0 || v_blank_end == 0)
    2064             :                 return false;
    2065             : 
    2066           0 :         set_reg_field_value(
    2067             :                 val,
    2068             :                 v_blank_start,
    2069             :                 CRTC_VERTICAL_INTERRUPT0_POSITION,
    2070             :                 CRTC_VERTICAL_INTERRUPT0_LINE_START);
    2071             : 
    2072             :         /* Set interval width for interrupt to fire to 1 scanline */
    2073           0 :         set_reg_field_value(
    2074             :                 val,
    2075             :                 v_blank_start + width,
    2076             :                 CRTC_VERTICAL_INTERRUPT0_POSITION,
    2077             :                 CRTC_VERTICAL_INTERRUPT0_LINE_END);
    2078             : 
    2079           0 :         dm_write_reg(tg->ctx, CRTC_REG(mmCRTC_VERTICAL_INTERRUPT0_POSITION), val);
    2080             : 
    2081           0 :         return true;
    2082             : }
    2083             : 
    2084           0 : static bool dce110_is_tg_enabled(struct timing_generator *tg)
    2085             : {
    2086           0 :         uint32_t addr = 0;
    2087           0 :         uint32_t value = 0;
    2088           0 :         uint32_t field = 0;
    2089           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    2090             : 
    2091           0 :         addr = CRTC_REG(mmCRTC_CONTROL);
    2092           0 :         value = dm_read_reg(tg->ctx, addr);
    2093           0 :         field = get_reg_field_value(value, CRTC_CONTROL,
    2094             :                                     CRTC_CURRENT_MASTER_EN_STATE);
    2095           0 :         return field == 1;
    2096             : }
    2097             : 
    2098           0 : bool dce110_configure_crc(struct timing_generator *tg,
    2099             :                           const struct crc_params *params)
    2100             : {
    2101           0 :         uint32_t cntl_addr = 0;
    2102           0 :         uint32_t addr = 0;
    2103             :         uint32_t value;
    2104           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    2105             : 
    2106             :         /* Cannot configure crc on a CRTC that is disabled */
    2107           0 :         if (!dce110_is_tg_enabled(tg))
    2108             :                 return false;
    2109             : 
    2110           0 :         cntl_addr = CRTC_REG(mmCRTC_CRC_CNTL);
    2111             : 
    2112             :         /* First, disable CRC before we configure it. */
    2113           0 :         dm_write_reg(tg->ctx, cntl_addr, 0);
    2114             : 
    2115           0 :         if (!params->enable)
    2116             :                 return true;
    2117             : 
    2118             :         /* Program frame boundaries */
    2119             :         /* Window A x axis start and end. */
    2120           0 :         value = 0;
    2121           0 :         addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_X_CONTROL);
    2122           0 :         set_reg_field_value(value, params->windowa_x_start,
    2123             :                             CRTC_CRC0_WINDOWA_X_CONTROL,
    2124             :                             CRTC_CRC0_WINDOWA_X_START);
    2125           0 :         set_reg_field_value(value, params->windowa_x_end,
    2126             :                             CRTC_CRC0_WINDOWA_X_CONTROL,
    2127             :                             CRTC_CRC0_WINDOWA_X_END);
    2128           0 :         dm_write_reg(tg->ctx, addr, value);
    2129             : 
    2130             :         /* Window A y axis start and end. */
    2131           0 :         value = 0;
    2132           0 :         addr = CRTC_REG(mmCRTC_CRC0_WINDOWA_Y_CONTROL);
    2133           0 :         set_reg_field_value(value, params->windowa_y_start,
    2134             :                             CRTC_CRC0_WINDOWA_Y_CONTROL,
    2135             :                             CRTC_CRC0_WINDOWA_Y_START);
    2136           0 :         set_reg_field_value(value, params->windowa_y_end,
    2137             :                             CRTC_CRC0_WINDOWA_Y_CONTROL,
    2138             :                             CRTC_CRC0_WINDOWA_Y_END);
    2139           0 :         dm_write_reg(tg->ctx, addr, value);
    2140             : 
    2141             :         /* Window B x axis start and end. */
    2142           0 :         value = 0;
    2143           0 :         addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_X_CONTROL);
    2144           0 :         set_reg_field_value(value, params->windowb_x_start,
    2145             :                             CRTC_CRC0_WINDOWB_X_CONTROL,
    2146             :                             CRTC_CRC0_WINDOWB_X_START);
    2147           0 :         set_reg_field_value(value, params->windowb_x_end,
    2148             :                             CRTC_CRC0_WINDOWB_X_CONTROL,
    2149             :                             CRTC_CRC0_WINDOWB_X_END);
    2150           0 :         dm_write_reg(tg->ctx, addr, value);
    2151             : 
    2152             :         /* Window B y axis start and end. */
    2153           0 :         value = 0;
    2154           0 :         addr = CRTC_REG(mmCRTC_CRC0_WINDOWB_Y_CONTROL);
    2155           0 :         set_reg_field_value(value, params->windowb_y_start,
    2156             :                             CRTC_CRC0_WINDOWB_Y_CONTROL,
    2157             :                             CRTC_CRC0_WINDOWB_Y_START);
    2158           0 :         set_reg_field_value(value, params->windowb_y_end,
    2159             :                             CRTC_CRC0_WINDOWB_Y_CONTROL,
    2160             :                             CRTC_CRC0_WINDOWB_Y_END);
    2161           0 :         dm_write_reg(tg->ctx, addr, value);
    2162             : 
    2163             :         /* Set crc mode and selection, and enable. Only using CRC0*/
    2164           0 :         value = 0;
    2165           0 :         set_reg_field_value(value, params->continuous_mode ? 1 : 0,
    2166             :                             CRTC_CRC_CNTL, CRTC_CRC_CONT_EN);
    2167           0 :         set_reg_field_value(value, params->selection,
    2168             :                             CRTC_CRC_CNTL, CRTC_CRC0_SELECT);
    2169           0 :         set_reg_field_value(value, 1, CRTC_CRC_CNTL, CRTC_CRC_EN);
    2170           0 :         dm_write_reg(tg->ctx, cntl_addr, value);
    2171             : 
    2172           0 :         return true;
    2173             : }
    2174             : 
    2175           0 : bool dce110_get_crc(struct timing_generator *tg,
    2176             :                     uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
    2177             : {
    2178           0 :         uint32_t addr = 0;
    2179           0 :         uint32_t value = 0;
    2180           0 :         uint32_t field = 0;
    2181           0 :         struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
    2182             : 
    2183           0 :         addr = CRTC_REG(mmCRTC_CRC_CNTL);
    2184           0 :         value = dm_read_reg(tg->ctx, addr);
    2185           0 :         field = get_reg_field_value(value, CRTC_CRC_CNTL, CRTC_CRC_EN);
    2186             : 
    2187             :         /* Early return if CRC is not enabled for this CRTC */
    2188           0 :         if (!field)
    2189             :                 return false;
    2190             : 
    2191           0 :         addr = CRTC_REG(mmCRTC_CRC0_DATA_RG);
    2192           0 :         value = dm_read_reg(tg->ctx, addr);
    2193           0 :         *r_cr = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_R_CR);
    2194           0 :         *g_y = get_reg_field_value(value, CRTC_CRC0_DATA_RG, CRC0_G_Y);
    2195             : 
    2196           0 :         addr = CRTC_REG(mmCRTC_CRC0_DATA_B);
    2197           0 :         value = dm_read_reg(tg->ctx, addr);
    2198           0 :         *b_cb = get_reg_field_value(value, CRTC_CRC0_DATA_B, CRC0_B_CB);
    2199             : 
    2200           0 :         return true;
    2201             : }
    2202             : 
    2203             : static const struct timing_generator_funcs dce110_tg_funcs = {
    2204             :                 .validate_timing = dce110_tg_validate_timing,
    2205             :                 .program_timing = dce110_tg_program_timing,
    2206             :                 .enable_crtc = dce110_timing_generator_enable_crtc,
    2207             :                 .disable_crtc = dce110_timing_generator_disable_crtc,
    2208             :                 .is_counter_moving = dce110_timing_generator_is_counter_moving,
    2209             :                 .get_position = dce110_timing_generator_get_position,
    2210             :                 .get_frame_count = dce110_timing_generator_get_vblank_counter,
    2211             :                 .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos,
    2212             :                 .set_early_control = dce110_timing_generator_set_early_control,
    2213             :                 .wait_for_state = dce110_tg_wait_for_state,
    2214             :                 .set_blank = dce110_tg_set_blank,
    2215             :                 .is_blanked = dce110_tg_is_blanked,
    2216             :                 .set_colors = dce110_tg_set_colors,
    2217             :                 .set_overscan_blank_color =
    2218             :                                 dce110_timing_generator_set_overscan_color_black,
    2219             :                 .set_blank_color = dce110_timing_generator_program_blank_color,
    2220             :                 .disable_vga = dce110_timing_generator_disable_vga,
    2221             :                 .did_triggered_reset_occur =
    2222             :                                 dce110_timing_generator_did_triggered_reset_occur,
    2223             :                 .setup_global_swap_lock =
    2224             :                                 dce110_timing_generator_setup_global_swap_lock,
    2225             :                 .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger,
    2226             :                 .enable_crtc_reset = dce110_timing_generator_enable_crtc_reset,
    2227             :                 .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger,
    2228             :                 .tear_down_global_swap_lock =
    2229             :                                 dce110_timing_generator_tear_down_global_swap_lock,
    2230             :                 .enable_advanced_request =
    2231             :                                 dce110_timing_generator_enable_advanced_request,
    2232             :                 .set_drr =
    2233             :                                 dce110_timing_generator_set_drr,
    2234             :                 .get_last_used_drr_vtotal = NULL,
    2235             :                 .set_static_screen_control =
    2236             :                         dce110_timing_generator_set_static_screen_control,
    2237             :                 .set_test_pattern = dce110_timing_generator_set_test_pattern,
    2238             :                 .arm_vert_intr = dce110_arm_vert_intr,
    2239             :                 .is_tg_enabled = dce110_is_tg_enabled,
    2240             :                 .configure_crc = dce110_configure_crc,
    2241             :                 .get_crc = dce110_get_crc,
    2242             : };
    2243             : 
    2244           0 : void dce110_timing_generator_construct(
    2245             :         struct dce110_timing_generator *tg110,
    2246             :         struct dc_context *ctx,
    2247             :         uint32_t instance,
    2248             :         const struct dce110_timing_generator_offsets *offsets)
    2249             : {
    2250           0 :         tg110->controller_id = CONTROLLER_ID_D0 + instance;
    2251           0 :         tg110->base.inst = instance;
    2252             : 
    2253           0 :         tg110->offsets = *offsets;
    2254             : 
    2255           0 :         tg110->base.funcs = &dce110_tg_funcs;
    2256             : 
    2257           0 :         tg110->base.ctx = ctx;
    2258           0 :         tg110->base.bp = ctx->dc_bios;
    2259             : 
    2260           0 :         tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1;
    2261           0 :         tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1;
    2262             : 
    2263           0 :         tg110->min_h_blank = 56;
    2264           0 :         tg110->min_h_front_porch = 4;
    2265           0 :         tg110->min_h_back_porch = 4;
    2266           0 : }

Generated by: LCOV version 1.14