LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn10 - dcn10_optc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 485 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 51 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             : 
      27             : #include "reg_helper.h"
      28             : #include "dcn10_optc.h"
      29             : #include "dc.h"
      30             : 
      31             : #define REG(reg)\
      32             :         optc1->tg_regs->reg
      33             : 
      34             : #define CTX \
      35             :         optc1->base.ctx
      36             : 
      37             : #undef FN
      38             : #define FN(reg_name, field_name) \
      39             :         optc1->tg_shift->field_name, optc1->tg_mask->field_name
      40             : 
      41             : #define STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN 0x100
      42             : 
      43             : /**
      44             : * apply_front_porch_workaround  TODO FPGA still need?
      45             : *
      46             : * This is a workaround for a bug that has existed since R5xx and has not been
      47             : * fixed keep Front porch at minimum 2 for Interlaced mode or 1 for progressive.
      48             : */
      49             : static void apply_front_porch_workaround(struct dc_crtc_timing *timing)
      50             : {
      51           0 :         if (timing->flags.INTERLACE == 1) {
      52           0 :                 if (timing->v_front_porch < 2)
      53           0 :                         timing->v_front_porch = 2;
      54             :         } else {
      55           0 :                 if (timing->v_front_porch < 1)
      56           0 :                         timing->v_front_porch = 1;
      57             :         }
      58             : }
      59             : 
      60           0 : void optc1_program_global_sync(
      61             :                 struct timing_generator *optc,
      62             :                 int vready_offset,
      63             :                 int vstartup_start,
      64             :                 int vupdate_offset,
      65             :                 int vupdate_width)
      66             : {
      67           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
      68             : 
      69           0 :         optc1->vready_offset = vready_offset;
      70           0 :         optc1->vstartup_start = vstartup_start;
      71           0 :         optc1->vupdate_offset = vupdate_offset;
      72           0 :         optc1->vupdate_width = vupdate_width;
      73             : 
      74           0 :         if (optc1->vstartup_start == 0) {
      75           0 :                 BREAK_TO_DEBUGGER();
      76           0 :                 return;
      77             :         }
      78             : 
      79           0 :         REG_SET(OTG_VSTARTUP_PARAM, 0,
      80             :                 VSTARTUP_START, optc1->vstartup_start);
      81             : 
      82           0 :         REG_SET_2(OTG_VUPDATE_PARAM, 0,
      83             :                         VUPDATE_OFFSET, optc1->vupdate_offset,
      84             :                         VUPDATE_WIDTH, optc1->vupdate_width);
      85             : 
      86           0 :         REG_SET(OTG_VREADY_PARAM, 0,
      87             :                         VREADY_OFFSET, optc1->vready_offset);
      88             : }
      89             : 
      90           0 : static void optc1_disable_stereo(struct timing_generator *optc)
      91             : {
      92           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
      93             : 
      94           0 :         REG_SET(OTG_STEREO_CONTROL, 0,
      95             :                 OTG_STEREO_EN, 0);
      96             : 
      97           0 :         REG_SET_2(OTG_3D_STRUCTURE_CONTROL, 0,
      98             :                 OTG_3D_STRUCTURE_EN, 0,
      99             :                 OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
     100           0 : }
     101             : 
     102           0 : void optc1_setup_vertical_interrupt0(
     103             :                 struct timing_generator *optc,
     104             :                 uint32_t start_line,
     105             :                 uint32_t end_line)
     106             : {
     107           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     108             : 
     109           0 :         REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0,
     110             :                         OTG_VERTICAL_INTERRUPT0_LINE_START, start_line,
     111             :                         OTG_VERTICAL_INTERRUPT0_LINE_END, end_line);
     112           0 : }
     113             : 
     114           0 : void optc1_setup_vertical_interrupt1(
     115             :                 struct timing_generator *optc,
     116             :                 uint32_t start_line)
     117             : {
     118           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     119             : 
     120           0 :         REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0,
     121             :                                 OTG_VERTICAL_INTERRUPT1_LINE_START, start_line);
     122           0 : }
     123             : 
     124           0 : void optc1_setup_vertical_interrupt2(
     125             :                 struct timing_generator *optc,
     126             :                 uint32_t start_line)
     127             : {
     128           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     129             : 
     130           0 :         REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0,
     131             :                         OTG_VERTICAL_INTERRUPT2_LINE_START, start_line);
     132           0 : }
     133             : 
     134             : /**
     135             :  * program_timing_generator   used by mode timing set
     136             :  * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition.
     137             :  * Including SYNC. Call BIOS command table to program Timings.
     138             :  */
     139           0 : void optc1_program_timing(
     140             :         struct timing_generator *optc,
     141             :         const struct dc_crtc_timing *dc_crtc_timing,
     142             :         int vready_offset,
     143             :         int vstartup_start,
     144             :         int vupdate_offset,
     145             :         int vupdate_width,
     146             :         const enum signal_type signal,
     147             :         bool use_vbios)
     148             : {
     149             :         struct dc_crtc_timing patched_crtc_timing;
     150             :         uint32_t asic_blank_end;
     151             :         uint32_t asic_blank_start;
     152             :         uint32_t v_total;
     153             :         uint32_t v_sync_end;
     154             :         uint32_t h_sync_polarity, v_sync_polarity;
     155           0 :         uint32_t start_point = 0;
     156           0 :         uint32_t field_num = 0;
     157           0 :         enum h_timing_div_mode h_div = H_TIMING_NO_DIV;
     158             : 
     159           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     160             : 
     161           0 :         optc1->signal = signal;
     162           0 :         optc1->vready_offset = vready_offset;
     163           0 :         optc1->vstartup_start = vstartup_start;
     164           0 :         optc1->vupdate_offset = vupdate_offset;
     165           0 :         optc1->vupdate_width = vupdate_width;
     166           0 :         patched_crtc_timing = *dc_crtc_timing;
     167           0 :         apply_front_porch_workaround(&patched_crtc_timing);
     168           0 :         optc1->orginal_patched_timing = patched_crtc_timing;
     169             : 
     170             :         /* Load horizontal timing */
     171             : 
     172             :         /* CRTC_H_TOTAL = vesa.h_total - 1 */
     173           0 :         REG_SET(OTG_H_TOTAL, 0,
     174             :                         OTG_H_TOTAL,  patched_crtc_timing.h_total - 1);
     175             : 
     176             :         /* h_sync_start = 0, h_sync_end = vesa.h_sync_width */
     177           0 :         REG_UPDATE_2(OTG_H_SYNC_A,
     178             :                         OTG_H_SYNC_A_START, 0,
     179             :                         OTG_H_SYNC_A_END, patched_crtc_timing.h_sync_width);
     180             : 
     181             :         /* blank_start = line end - front porch */
     182           0 :         asic_blank_start = patched_crtc_timing.h_total -
     183             :                         patched_crtc_timing.h_front_porch;
     184             : 
     185             :         /* blank_end = blank_start - active */
     186           0 :         asic_blank_end = asic_blank_start -
     187           0 :                         patched_crtc_timing.h_border_right -
     188             :                         patched_crtc_timing.h_addressable -
     189             :                         patched_crtc_timing.h_border_left;
     190             : 
     191           0 :         REG_UPDATE_2(OTG_H_BLANK_START_END,
     192             :                         OTG_H_BLANK_START, asic_blank_start,
     193             :                         OTG_H_BLANK_END, asic_blank_end);
     194             : 
     195             :         /* h_sync polarity */
     196           0 :         h_sync_polarity = patched_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ?
     197           0 :                         0 : 1;
     198             : 
     199           0 :         REG_UPDATE(OTG_H_SYNC_A_CNTL,
     200             :                         OTG_H_SYNC_A_POL, h_sync_polarity);
     201             : 
     202           0 :         v_total = patched_crtc_timing.v_total - 1;
     203             : 
     204           0 :         REG_SET(OTG_V_TOTAL, 0,
     205             :                         OTG_V_TOTAL, v_total);
     206             : 
     207             :         /* In case of V_TOTAL_CONTROL is on, make sure OTG_V_TOTAL_MAX and
     208             :          * OTG_V_TOTAL_MIN are equal to V_TOTAL.
     209             :          */
     210           0 :         REG_SET(OTG_V_TOTAL_MAX, 0,
     211             :                 OTG_V_TOTAL_MAX, v_total);
     212           0 :         REG_SET(OTG_V_TOTAL_MIN, 0,
     213             :                 OTG_V_TOTAL_MIN, v_total);
     214             : 
     215             :         /* v_sync_start = 0, v_sync_end = v_sync_width */
     216           0 :         v_sync_end = patched_crtc_timing.v_sync_width;
     217             : 
     218           0 :         REG_UPDATE_2(OTG_V_SYNC_A,
     219             :                         OTG_V_SYNC_A_START, 0,
     220             :                         OTG_V_SYNC_A_END, v_sync_end);
     221             : 
     222             :         /* blank_start = frame end - front porch */
     223           0 :         asic_blank_start = patched_crtc_timing.v_total -
     224             :                         patched_crtc_timing.v_front_porch;
     225             : 
     226             :         /* blank_end = blank_start - active */
     227           0 :         asic_blank_end = asic_blank_start -
     228           0 :                         patched_crtc_timing.v_border_bottom -
     229             :                         patched_crtc_timing.v_addressable -
     230             :                         patched_crtc_timing.v_border_top;
     231             : 
     232           0 :         REG_UPDATE_2(OTG_V_BLANK_START_END,
     233             :                         OTG_V_BLANK_START, asic_blank_start,
     234             :                         OTG_V_BLANK_END, asic_blank_end);
     235             : 
     236             :         /* v_sync polarity */
     237           0 :         v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ?
     238           0 :                         0 : 1;
     239             : 
     240           0 :         REG_UPDATE(OTG_V_SYNC_A_CNTL,
     241             :                 OTG_V_SYNC_A_POL, v_sync_polarity);
     242             : 
     243           0 :         if (optc1->signal == SIGNAL_TYPE_DISPLAY_PORT ||
     244           0 :                         optc1->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
     245             :                         optc1->signal == SIGNAL_TYPE_EDP) {
     246           0 :                 start_point = 1;
     247           0 :                 if (patched_crtc_timing.flags.INTERLACE == 1)
     248           0 :                         field_num = 1;
     249             :         }
     250             : 
     251             :         /* Interlace */
     252           0 :         if (REG(OTG_INTERLACE_CONTROL)) {
     253           0 :                 if (patched_crtc_timing.flags.INTERLACE == 1)
     254           0 :                         REG_UPDATE(OTG_INTERLACE_CONTROL,
     255             :                                         OTG_INTERLACE_ENABLE, 1);
     256             :                 else
     257           0 :                         REG_UPDATE(OTG_INTERLACE_CONTROL,
     258             :                                         OTG_INTERLACE_ENABLE, 0);
     259             :         }
     260             : 
     261             :         /* VTG enable set to 0 first VInit */
     262           0 :         REG_UPDATE(CONTROL,
     263             :                         VTG0_ENABLE, 0);
     264             : 
     265             :         /* original code is using VTG offset to address OTG reg, seems wrong */
     266           0 :         REG_UPDATE_2(OTG_CONTROL,
     267             :                         OTG_START_POINT_CNTL, start_point,
     268             :                         OTG_FIELD_NUMBER_CNTL, field_num);
     269             : 
     270           0 :         optc->funcs->program_global_sync(optc,
     271             :                         vready_offset,
     272             :                         vstartup_start,
     273             :                         vupdate_offset,
     274             :                         vupdate_width);
     275             : 
     276           0 :         optc->funcs->set_vtg_params(optc, dc_crtc_timing, true);
     277             : 
     278             :         /* TODO
     279             :          * patched_crtc_timing.flags.HORZ_COUNT_BY_TWO == 1
     280             :          * program_horz_count_by_2
     281             :          * for DVI 30bpp mode, 0 otherwise
     282             :          * program_horz_count_by_2(optc, &patched_crtc_timing);
     283             :          */
     284             : 
     285             :         /* Enable stereo - only when we need to pack 3D frame. Other types
     286             :          * of stereo handled in explicit call
     287             :          */
     288             : 
     289           0 :         if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2)
     290           0 :                 h_div = H_TIMING_DIV_BY2;
     291             : 
     292           0 :         if (REG(OPTC_DATA_FORMAT_CONTROL) && optc1->tg_mask->OPTC_DATA_FORMAT != 0) {
     293           0 :                 uint32_t data_fmt = 0;
     294             : 
     295           0 :                 if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
     296             :                         data_fmt = 1;
     297           0 :                 else if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
     298           0 :                         data_fmt = 2;
     299             : 
     300           0 :                 REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt);
     301             :         }
     302             : 
     303           0 :         if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) {
     304           0 :                 if (optc1->opp_count == 4)
     305           0 :                         h_div = H_TIMING_DIV_BY4;
     306             : 
     307           0 :                 REG_UPDATE(OTG_H_TIMING_CNTL,
     308             :                 OTG_H_TIMING_DIV_MODE, h_div);
     309             :         } else {
     310           0 :                 REG_UPDATE(OTG_H_TIMING_CNTL,
     311             :                 OTG_H_TIMING_DIV_BY2, h_div);
     312             :         }
     313           0 : }
     314             : 
     315             : /**
     316             :  * optc1_set_vtg_params - Set Vertical Timing Generator (VTG) parameters
     317             :  *
     318             :  * @optc: timing_generator struct used to extract the optc parameters
     319             :  * @dc_crtc_timing: Timing parameters configured
     320             :  * @program_fp2: Boolean value indicating if FP2 will be programmed or not
     321             :  *
     322             :  * OTG is responsible for generating the global sync signals, including
     323             :  * vertical timing information for each HUBP in the dcfclk domain. Each VTG is
     324             :  * associated with one OTG that provides HUBP with vertical timing information
     325             :  * (i.e., there is 1:1 correspondence between OTG and VTG). This function is
     326             :  * responsible for setting the OTG parameters to the VTG during the pipe
     327             :  * programming.
     328             :  */
     329           0 : void optc1_set_vtg_params(struct timing_generator *optc,
     330             :                 const struct dc_crtc_timing *dc_crtc_timing, bool program_fp2)
     331             : {
     332             :         struct dc_crtc_timing patched_crtc_timing;
     333             :         uint32_t asic_blank_end;
     334             :         uint32_t v_init;
     335           0 :         uint32_t v_fp2 = 0;
     336             :         int32_t vertical_line_start;
     337             : 
     338           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     339             : 
     340           0 :         patched_crtc_timing = *dc_crtc_timing;
     341           0 :         apply_front_porch_workaround(&patched_crtc_timing);
     342             : 
     343             :         /* VCOUNT_INIT is the start of blank */
     344           0 :         v_init = patched_crtc_timing.v_total - patched_crtc_timing.v_front_porch;
     345             : 
     346             :         /* end of blank = v_init - active */
     347           0 :         asic_blank_end = v_init -
     348           0 :                         patched_crtc_timing.v_border_bottom -
     349             :                         patched_crtc_timing.v_addressable -
     350             :                         patched_crtc_timing.v_border_top;
     351             : 
     352             :         /* if VSTARTUP is before VSYNC, FP2 is the offset, otherwise 0 */
     353           0 :         vertical_line_start = asic_blank_end - optc1->vstartup_start + 1;
     354           0 :         if (vertical_line_start < 0)
     355           0 :                 v_fp2 = -vertical_line_start;
     356             : 
     357             :         /* Interlace */
     358           0 :         if (REG(OTG_INTERLACE_CONTROL)) {
     359           0 :                 if (patched_crtc_timing.flags.INTERLACE == 1) {
     360           0 :                         v_init = v_init / 2;
     361           0 :                         if ((optc1->vstartup_start/2)*2 > asic_blank_end)
     362           0 :                                 v_fp2 = v_fp2 / 2;
     363             :                 }
     364             :         }
     365             : 
     366           0 :         if (program_fp2)
     367           0 :                 REG_UPDATE_2(CONTROL,
     368             :                                 VTG0_FP2, v_fp2,
     369             :                                 VTG0_VCOUNT_INIT, v_init);
     370             :         else
     371           0 :                 REG_UPDATE(CONTROL, VTG0_VCOUNT_INIT, v_init);
     372           0 : }
     373             : 
     374           0 : void optc1_set_blank_data_double_buffer(struct timing_generator *optc, bool enable)
     375             : {
     376           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     377             : 
     378           0 :         uint32_t blank_data_double_buffer_enable = enable ? 1 : 0;
     379             : 
     380           0 :         REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
     381             :                         OTG_BLANK_DATA_DOUBLE_BUFFER_EN, blank_data_double_buffer_enable);
     382           0 : }
     383             : 
     384             : /**
     385             :  * optc1_set_timing_double_buffer() - DRR double buffering control
     386             :  *
     387             :  * Sets double buffer point for V_TOTAL, H_TOTAL, VTOTAL_MIN,
     388             :  * VTOTAL_MAX, VTOTAL_MIN_SEL and VTOTAL_MAX_SEL registers.
     389             :  *
     390             :  * Options: any time,  start of frame, dp start of frame (range timing)
     391             :  */
     392           0 : void optc1_set_timing_double_buffer(struct timing_generator *optc, bool enable)
     393             : {
     394           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     395           0 :         uint32_t mode = enable ? 2 : 0;
     396             : 
     397           0 :         REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
     398             :                    OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mode);
     399           0 : }
     400             : 
     401             : /**
     402             :  * unblank_crtc
     403             :  * Call ASIC Control Object to UnBlank CRTC.
     404             :  */
     405           0 : static void optc1_unblank_crtc(struct timing_generator *optc)
     406             : {
     407           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     408             : 
     409           0 :         REG_UPDATE_2(OTG_BLANK_CONTROL,
     410             :                         OTG_BLANK_DATA_EN, 0,
     411             :                         OTG_BLANK_DE_MODE, 0);
     412             : 
     413             :         /* W/A for automated testing
     414             :          * Automated testing will fail underflow test as there
     415             :          * sporadic underflows which occur during the optc blank
     416             :          * sequence.  As a w/a, clear underflow on unblank.
     417             :          * This prevents the failure, but will not mask actual
     418             :          * underflow that affect real use cases.
     419             :          */
     420           0 :         optc1_clear_optc_underflow(optc);
     421           0 : }
     422             : 
     423             : /**
     424             :  * blank_crtc
     425             :  * Call ASIC Control Object to Blank CRTC.
     426             :  */
     427             : 
     428           0 : static void optc1_blank_crtc(struct timing_generator *optc)
     429             : {
     430           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     431             : 
     432           0 :         REG_UPDATE_2(OTG_BLANK_CONTROL,
     433             :                         OTG_BLANK_DATA_EN, 1,
     434             :                         OTG_BLANK_DE_MODE, 0);
     435             : 
     436           0 :         optc1_set_blank_data_double_buffer(optc, false);
     437           0 : }
     438             : 
     439           0 : void optc1_set_blank(struct timing_generator *optc,
     440             :                 bool enable_blanking)
     441             : {
     442           0 :         if (enable_blanking)
     443           0 :                 optc1_blank_crtc(optc);
     444             :         else
     445           0 :                 optc1_unblank_crtc(optc);
     446           0 : }
     447             : 
     448           0 : bool optc1_is_blanked(struct timing_generator *optc)
     449             : {
     450           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     451             :         uint32_t blank_en;
     452             :         uint32_t blank_state;
     453             : 
     454           0 :         REG_GET_2(OTG_BLANK_CONTROL,
     455             :                         OTG_BLANK_DATA_EN, &blank_en,
     456             :                         OTG_CURRENT_BLANK_STATE, &blank_state);
     457             : 
     458           0 :         return blank_en && blank_state;
     459             : }
     460             : 
     461           0 : void optc1_enable_optc_clock(struct timing_generator *optc, bool enable)
     462             : {
     463           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     464             : 
     465           0 :         if (enable) {
     466           0 :                 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
     467             :                                 OPTC_INPUT_CLK_EN, 1,
     468             :                                 OPTC_INPUT_CLK_GATE_DIS, 1);
     469             : 
     470           0 :                 REG_WAIT(OPTC_INPUT_CLOCK_CONTROL,
     471             :                                 OPTC_INPUT_CLK_ON, 1,
     472             :                                 1, 1000);
     473             : 
     474             :                 /* Enable clock */
     475           0 :                 REG_UPDATE_2(OTG_CLOCK_CONTROL,
     476             :                                 OTG_CLOCK_EN, 1,
     477             :                                 OTG_CLOCK_GATE_DIS, 1);
     478           0 :                 REG_WAIT(OTG_CLOCK_CONTROL,
     479             :                                 OTG_CLOCK_ON, 1,
     480             :                                 1, 1000);
     481             :         } else  {
     482             : 
     483             :                 //last chance to clear underflow, otherwise, it will always there due to clock is off.
     484           0 :                 if (optc->funcs->is_optc_underflow_occurred(optc) == true)
     485           0 :                         optc->funcs->clear_optc_underflow(optc);
     486             : 
     487           0 :                 REG_UPDATE_2(OTG_CLOCK_CONTROL,
     488             :                                 OTG_CLOCK_GATE_DIS, 0,
     489             :                                 OTG_CLOCK_EN, 0);
     490             : 
     491           0 :                 REG_UPDATE_2(OPTC_INPUT_CLOCK_CONTROL,
     492             :                                 OPTC_INPUT_CLK_GATE_DIS, 0,
     493             :                                 OPTC_INPUT_CLK_EN, 0);
     494             :         }
     495           0 : }
     496             : 
     497             : /**
     498             :  * Enable CRTC
     499             :  * Enable CRTC - call ASIC Control Object to enable Timing generator.
     500             :  */
     501           0 : static bool optc1_enable_crtc(struct timing_generator *optc)
     502             : {
     503             :         /* TODO FPGA wait for answer
     504             :          * OTG_MASTER_UPDATE_MODE != CRTC_MASTER_UPDATE_MODE
     505             :          * OTG_MASTER_UPDATE_LOCK != CRTC_MASTER_UPDATE_LOCK
     506             :          */
     507           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     508             : 
     509             :         /* opp instance for OTG. For DCN1.0, ODM is remoed.
     510             :          * OPP and OPTC should 1:1 mapping
     511             :          */
     512           0 :         REG_UPDATE(OPTC_DATA_SOURCE_SELECT,
     513             :                         OPTC_SRC_SEL, optc->inst);
     514             : 
     515             :         /* VTG enable first is for HW workaround */
     516           0 :         REG_UPDATE(CONTROL,
     517             :                         VTG0_ENABLE, 1);
     518             : 
     519           0 :         REG_SEQ_START();
     520             : 
     521             :         /* Enable CRTC */
     522           0 :         REG_UPDATE_2(OTG_CONTROL,
     523             :                         OTG_DISABLE_POINT_CNTL, 3,
     524             :                         OTG_MASTER_EN, 1);
     525             : 
     526           0 :         REG_SEQ_SUBMIT();
     527           0 :         REG_SEQ_WAIT_DONE();
     528             : 
     529           0 :         return true;
     530             : }
     531             : 
     532             : /* disable_crtc - call ASIC Control Object to disable Timing generator. */
     533           0 : bool optc1_disable_crtc(struct timing_generator *optc)
     534             : {
     535           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     536             : 
     537             :         /* disable otg request until end of the first line
     538             :          * in the vertical blank region
     539             :          */
     540           0 :         REG_UPDATE_2(OTG_CONTROL,
     541             :                         OTG_DISABLE_POINT_CNTL, 3,
     542             :                         OTG_MASTER_EN, 0);
     543             : 
     544           0 :         REG_UPDATE(CONTROL,
     545             :                         VTG0_ENABLE, 0);
     546             : 
     547             :         /* CRTC disabled, so disable  clock. */
     548           0 :         REG_WAIT(OTG_CLOCK_CONTROL,
     549             :                         OTG_BUSY, 0,
     550             :                         1, 100000);
     551             : 
     552           0 :         return true;
     553             : }
     554             : 
     555             : 
     556           0 : void optc1_program_blank_color(
     557             :                 struct timing_generator *optc,
     558             :                 const struct tg_color *black_color)
     559             : {
     560           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     561             : 
     562           0 :         REG_SET_3(OTG_BLACK_COLOR, 0,
     563             :                         OTG_BLACK_COLOR_B_CB, black_color->color_b_cb,
     564             :                         OTG_BLACK_COLOR_G_Y, black_color->color_g_y,
     565             :                         OTG_BLACK_COLOR_R_CR, black_color->color_r_cr);
     566           0 : }
     567             : 
     568           0 : bool optc1_validate_timing(
     569             :         struct timing_generator *optc,
     570             :         const struct dc_crtc_timing *timing)
     571             : {
     572             :         uint32_t v_blank;
     573             :         uint32_t h_blank;
     574             :         uint32_t min_v_blank;
     575           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     576             : 
     577           0 :         ASSERT(timing != NULL);
     578             : 
     579           0 :         v_blank = (timing->v_total - timing->v_addressable -
     580           0 :                                         timing->v_border_top - timing->v_border_bottom);
     581             : 
     582           0 :         h_blank = (timing->h_total - timing->h_addressable -
     583           0 :                 timing->h_border_right -
     584           0 :                 timing->h_border_left);
     585             : 
     586           0 :         if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE &&
     587           0 :                 timing->timing_3d_format != TIMING_3D_FORMAT_HW_FRAME_PACKING &&
     588           0 :                 timing->timing_3d_format != TIMING_3D_FORMAT_TOP_AND_BOTTOM &&
     589           0 :                 timing->timing_3d_format != TIMING_3D_FORMAT_SIDE_BY_SIDE &&
     590           0 :                 timing->timing_3d_format != TIMING_3D_FORMAT_FRAME_ALTERNATE &&
     591             :                 timing->timing_3d_format != TIMING_3D_FORMAT_INBAND_FA)
     592             :                 return false;
     593             : 
     594             :         /* Temporarily blocking interlacing mode until it's supported */
     595           0 :         if (timing->flags.INTERLACE == 1)
     596             :                 return false;
     597             : 
     598             :         /* Check maximum number of pixels supported by Timing Generator
     599             :          * (Currently will never fail, in order to fail needs display which
     600             :          * needs more than 8192 horizontal and
     601             :          * more than 8192 vertical total pixels)
     602             :          */
     603           0 :         if (timing->h_total > optc1->max_h_total ||
     604           0 :                 timing->v_total > optc1->max_v_total)
     605             :                 return false;
     606             : 
     607             : 
     608           0 :         if (h_blank < optc1->min_h_blank)
     609             :                 return false;
     610             : 
     611           0 :         if (timing->h_sync_width  < optc1->min_h_sync_width ||
     612           0 :                  timing->v_sync_width  < optc1->min_v_sync_width)
     613             :                 return false;
     614             : 
     615           0 :         min_v_blank = timing->flags.INTERLACE?optc1->min_v_blank_interlace:optc1->min_v_blank;
     616             : 
     617           0 :         if (v_blank < min_v_blank)
     618             :                 return false;
     619             : 
     620           0 :         return true;
     621             : 
     622             : }
     623             : 
     624             : /*
     625             :  * get_vblank_counter
     626             :  *
     627             :  * @brief
     628             :  * Get counter for vertical blanks. use register CRTC_STATUS_FRAME_COUNT which
     629             :  * holds the counter of frames.
     630             :  *
     631             :  * @param
     632             :  * struct timing_generator *optc - [in] timing generator which controls the
     633             :  * desired CRTC
     634             :  *
     635             :  * @return
     636             :  * Counter of frames, which should equal to number of vblanks.
     637             :  */
     638           0 : uint32_t optc1_get_vblank_counter(struct timing_generator *optc)
     639             : {
     640           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     641             :         uint32_t frame_count;
     642             : 
     643           0 :         REG_GET(OTG_STATUS_FRAME_COUNT,
     644             :                 OTG_FRAME_COUNT, &frame_count);
     645             : 
     646           0 :         return frame_count;
     647             : }
     648             : 
     649           0 : void optc1_lock(struct timing_generator *optc)
     650             : {
     651           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     652           0 :         uint32_t regval = 0;
     653             : 
     654           0 :         regval = REG_READ(OTG_CONTROL);
     655             : 
     656             :         /* otg is not running, do not need to be locked */
     657           0 :         if ((regval & 0x1) == 0x0)
     658             :                 return;
     659             : 
     660           0 :         REG_SET(OTG_GLOBAL_CONTROL0, 0,
     661             :                         OTG_MASTER_UPDATE_LOCK_SEL, optc->inst);
     662           0 :         REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
     663             :                         OTG_MASTER_UPDATE_LOCK, 1);
     664             : 
     665             :         /* Should be fast, status does not update on maximus */
     666           0 :         if (optc->ctx->dce_environment != DCE_ENV_FPGA_MAXIMUS) {
     667             : 
     668           0 :                 REG_WAIT(OTG_MASTER_UPDATE_LOCK,
     669             :                                 UPDATE_LOCK_STATUS, 1,
     670             :                                 1, 10);
     671             :         }
     672             : }
     673             : 
     674           0 : void optc1_unlock(struct timing_generator *optc)
     675             : {
     676           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     677             : 
     678           0 :         REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
     679             :                         OTG_MASTER_UPDATE_LOCK, 0);
     680           0 : }
     681             : 
     682           0 : bool optc1_is_locked(struct timing_generator *optc)
     683             : {
     684           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     685             :         uint32_t locked;
     686             : 
     687           0 :         REG_GET(OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, &locked);
     688             : 
     689           0 :         return (locked == 1);
     690             : }
     691             : 
     692           0 : void optc1_get_position(struct timing_generator *optc,
     693             :                 struct crtc_position *position)
     694             : {
     695           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     696             : 
     697           0 :         REG_GET_2(OTG_STATUS_POSITION,
     698             :                         OTG_HORZ_COUNT, &position->horizontal_count,
     699             :                         OTG_VERT_COUNT, &position->vertical_count);
     700             : 
     701           0 :         REG_GET(OTG_NOM_VERT_POSITION,
     702             :                         OTG_VERT_COUNT_NOM, &position->nominal_vcount);
     703           0 : }
     704             : 
     705           0 : bool optc1_is_counter_moving(struct timing_generator *optc)
     706             : {
     707             :         struct crtc_position position1, position2;
     708             : 
     709           0 :         optc->funcs->get_position(optc, &position1);
     710           0 :         optc->funcs->get_position(optc, &position2);
     711             : 
     712           0 :         if (position1.horizontal_count == position2.horizontal_count &&
     713           0 :                 position1.vertical_count == position2.vertical_count)
     714             :                 return false;
     715             :         else
     716           0 :                 return true;
     717             : }
     718             : 
     719           0 : bool optc1_did_triggered_reset_occur(
     720             :         struct timing_generator *optc)
     721             : {
     722           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     723             :         uint32_t occurred_force, occurred_vsync;
     724             : 
     725           0 :         REG_GET(OTG_FORCE_COUNT_NOW_CNTL,
     726             :                 OTG_FORCE_COUNT_NOW_OCCURRED, &occurred_force);
     727             : 
     728           0 :         REG_GET(OTG_VERT_SYNC_CONTROL,
     729             :                 OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, &occurred_vsync);
     730             : 
     731           0 :         return occurred_vsync != 0 || occurred_force != 0;
     732             : }
     733             : 
     734           0 : void optc1_disable_reset_trigger(struct timing_generator *optc)
     735             : {
     736           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     737             : 
     738           0 :         REG_WRITE(OTG_TRIGA_CNTL, 0);
     739             : 
     740           0 :         REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
     741             :                 OTG_FORCE_COUNT_NOW_CLEAR, 1);
     742             : 
     743           0 :         REG_SET(OTG_VERT_SYNC_CONTROL, 0,
     744             :                 OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, 1);
     745           0 : }
     746             : 
     747           0 : void optc1_enable_reset_trigger(struct timing_generator *optc, int source_tg_inst)
     748             : {
     749           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     750             :         uint32_t falling_edge;
     751             : 
     752           0 :         REG_GET(OTG_V_SYNC_A_CNTL,
     753             :                         OTG_V_SYNC_A_POL, &falling_edge);
     754             : 
     755           0 :         if (falling_edge)
     756           0 :                 REG_SET_3(OTG_TRIGA_CNTL, 0,
     757             :                                 /* vsync signal from selected OTG pipe based
     758             :                                  * on OTG_TRIG_SOURCE_PIPE_SELECT setting
     759             :                                  */
     760             :                                 OTG_TRIGA_SOURCE_SELECT, 20,
     761             :                                 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
     762             :                                 /* always detect falling edge */
     763             :                                 OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 1);
     764             :         else
     765           0 :                 REG_SET_3(OTG_TRIGA_CNTL, 0,
     766             :                                 /* vsync signal from selected OTG pipe based
     767             :                                  * on OTG_TRIG_SOURCE_PIPE_SELECT setting
     768             :                                  */
     769             :                                 OTG_TRIGA_SOURCE_SELECT, 20,
     770             :                                 OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
     771             :                                 /* always detect rising edge */
     772             :                                 OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1);
     773             : 
     774           0 :         REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
     775             :                         /* force H count to H_TOTAL and V count to V_TOTAL in
     776             :                          * progressive mode and V_TOTAL-1 in interlaced mode
     777             :                          */
     778             :                         OTG_FORCE_COUNT_NOW_MODE, 2);
     779           0 : }
     780             : 
     781           0 : void optc1_enable_crtc_reset(
     782             :                 struct timing_generator *optc,
     783             :                 int source_tg_inst,
     784             :                 struct crtc_trigger_info *crtc_tp)
     785             : {
     786           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     787           0 :         uint32_t falling_edge = 0;
     788           0 :         uint32_t rising_edge = 0;
     789             : 
     790           0 :         switch (crtc_tp->event) {
     791             : 
     792             :         case CRTC_EVENT_VSYNC_RISING:
     793           0 :                 rising_edge = 1;
     794           0 :                 break;
     795             : 
     796             :         case CRTC_EVENT_VSYNC_FALLING:
     797           0 :                 falling_edge = 1;
     798           0 :                 break;
     799             :         }
     800             : 
     801           0 :         REG_SET_4(OTG_TRIGA_CNTL, 0,
     802             :                  /* vsync signal from selected OTG pipe based
     803             :                   * on OTG_TRIG_SOURCE_PIPE_SELECT setting
     804             :                   */
     805             :                   OTG_TRIGA_SOURCE_SELECT, 20,
     806             :                   OTG_TRIGA_SOURCE_PIPE_SELECT, source_tg_inst,
     807             :                   /* always detect falling edge */
     808             :                   OTG_TRIGA_RISING_EDGE_DETECT_CNTL, rising_edge,
     809             :                   OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, falling_edge);
     810             : 
     811           0 :         switch (crtc_tp->delay) {
     812             :         case TRIGGER_DELAY_NEXT_LINE:
     813           0 :                 REG_SET(OTG_VERT_SYNC_CONTROL, 0,
     814             :                                 OTG_AUTO_FORCE_VSYNC_MODE, 1);
     815           0 :                 break;
     816             :         case TRIGGER_DELAY_NEXT_PIXEL:
     817           0 :                 REG_SET(OTG_FORCE_COUNT_NOW_CNTL, 0,
     818             :                         /* force H count to H_TOTAL and V count to V_TOTAL in
     819             :                          * progressive mode and V_TOTAL-1 in interlaced mode
     820             :                          */
     821             :                         OTG_FORCE_COUNT_NOW_MODE, 2);
     822           0 :                 break;
     823             :         }
     824           0 : }
     825             : 
     826           0 : void optc1_wait_for_state(struct timing_generator *optc,
     827             :                 enum crtc_state state)
     828             : {
     829           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     830             : 
     831           0 :         switch (state) {
     832             :         case CRTC_STATE_VBLANK:
     833           0 :                 REG_WAIT(OTG_STATUS,
     834             :                                 OTG_V_BLANK, 1,
     835             :                                 1, 100000); /* 1 vupdate at 10hz */
     836           0 :                 break;
     837             : 
     838             :         case CRTC_STATE_VACTIVE:
     839           0 :                 REG_WAIT(OTG_STATUS,
     840             :                                 OTG_V_ACTIVE_DISP, 1,
     841             :                                 1, 100000); /* 1 vupdate at 10hz */
     842           0 :                 break;
     843             : 
     844             :         default:
     845             :                 break;
     846             :         }
     847           0 : }
     848             : 
     849           0 : void optc1_set_early_control(
     850             :         struct timing_generator *optc,
     851             :         uint32_t early_cntl)
     852             : {
     853             :         /* asic design change, do not need this control
     854             :          * empty for share caller logic
     855             :          */
     856           0 : }
     857             : 
     858             : 
     859           0 : void optc1_set_static_screen_control(
     860             :         struct timing_generator *optc,
     861             :         uint32_t event_triggers,
     862             :         uint32_t num_frames)
     863             : {
     864           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     865             : 
     866             :         // By register spec, it only takes 8 bit value
     867           0 :         if (num_frames > 0xFF)
     868           0 :                 num_frames = 0xFF;
     869             : 
     870             :         /* Bit 8 is no longer applicable in RV for PSR case,
     871             :          * set bit 8 to 0 if given
     872             :          */
     873           0 :         if ((event_triggers & STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN)
     874             :                         != 0)
     875           0 :                 event_triggers = event_triggers &
     876             :                 ~STATIC_SCREEN_EVENT_MASK_RANGETIMING_DOUBLE_BUFFER_UPDATE_EN;
     877             : 
     878           0 :         REG_SET_2(OTG_STATIC_SCREEN_CONTROL, 0,
     879             :                         OTG_STATIC_SCREEN_EVENT_MASK, event_triggers,
     880             :                         OTG_STATIC_SCREEN_FRAME_COUNT, num_frames);
     881           0 : }
     882             : 
     883           0 : static void optc1_setup_manual_trigger(struct timing_generator *optc)
     884             : {
     885           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     886             : 
     887           0 :         REG_SET(OTG_GLOBAL_CONTROL2, 0,
     888             :                         MANUAL_FLOW_CONTROL_SEL, optc->inst);
     889             : 
     890           0 :         REG_SET_8(OTG_TRIGA_CNTL, 0,
     891             :                         OTG_TRIGA_SOURCE_SELECT, 22,
     892             :                         OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
     893             :                         OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
     894             :                         OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
     895             :                         OTG_TRIGA_POLARITY_SELECT, 0,
     896             :                         OTG_TRIGA_FREQUENCY_SELECT, 0,
     897             :                         OTG_TRIGA_DELAY, 0,
     898             :                         OTG_TRIGA_CLEAR, 1);
     899           0 : }
     900             : 
     901           0 : static void optc1_program_manual_trigger(struct timing_generator *optc)
     902             : {
     903           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     904             : 
     905           0 :         REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
     906             :                         MANUAL_FLOW_CONTROL, 1);
     907             : 
     908           0 :         REG_SET(OTG_MANUAL_FLOW_CONTROL, 0,
     909             :                         MANUAL_FLOW_CONTROL, 0);
     910           0 : }
     911             : 
     912             : 
     913             : /**
     914             :  *****************************************************************************
     915             :  *  Function: set_drr
     916             :  *
     917             :  *  @brief
     918             :  *     Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
     919             :  *
     920             :  *****************************************************************************
     921             :  */
     922           0 : void optc1_set_drr(
     923             :         struct timing_generator *optc,
     924             :         const struct drr_params *params)
     925             : {
     926           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     927             : 
     928           0 :         if (params != NULL &&
     929           0 :                 params->vertical_total_max > 0 &&
     930           0 :                 params->vertical_total_min > 0) {
     931             : 
     932           0 :                 if (params->vertical_total_mid != 0) {
     933             : 
     934           0 :                         REG_SET(OTG_V_TOTAL_MID, 0,
     935             :                                 OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
     936             : 
     937           0 :                         REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
     938             :                                         OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
     939             :                                         OTG_VTOTAL_MID_FRAME_NUM,
     940             :                                         (uint8_t)params->vertical_total_mid_frame_num);
     941             : 
     942             :                 }
     943             : 
     944           0 :                 REG_SET(OTG_V_TOTAL_MAX, 0,
     945             :                         OTG_V_TOTAL_MAX, params->vertical_total_max - 1);
     946             : 
     947           0 :                 REG_SET(OTG_V_TOTAL_MIN, 0,
     948             :                         OTG_V_TOTAL_MIN, params->vertical_total_min - 1);
     949             : 
     950           0 :                 REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
     951             :                                 OTG_V_TOTAL_MIN_SEL, 1,
     952             :                                 OTG_V_TOTAL_MAX_SEL, 1,
     953             :                                 OTG_FORCE_LOCK_ON_EVENT, 0,
     954             :                                 OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
     955             :                                 OTG_SET_V_TOTAL_MIN_MASK, 0);
     956             : 
     957             :                 // Setup manual flow control for EOF via TRIG_A
     958           0 :                 optc->funcs->setup_manual_trigger(optc);
     959             : 
     960             :         } else {
     961           0 :                 REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
     962             :                                 OTG_SET_V_TOTAL_MIN_MASK, 0,
     963             :                                 OTG_V_TOTAL_MIN_SEL, 0,
     964             :                                 OTG_V_TOTAL_MAX_SEL, 0,
     965             :                                 OTG_FORCE_LOCK_ON_EVENT, 0);
     966             : 
     967           0 :                 REG_SET(OTG_V_TOTAL_MIN, 0,
     968             :                         OTG_V_TOTAL_MIN, 0);
     969             : 
     970           0 :                 REG_SET(OTG_V_TOTAL_MAX, 0,
     971             :                         OTG_V_TOTAL_MAX, 0);
     972             :         }
     973           0 : }
     974             : 
     975           0 : void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max)
     976             : {
     977           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     978             : 
     979           0 :         REG_SET(OTG_V_TOTAL_MAX, 0,
     980             :                 OTG_V_TOTAL_MAX, vtotal_max);
     981             : 
     982           0 :         REG_SET(OTG_V_TOTAL_MIN, 0,
     983             :                 OTG_V_TOTAL_MIN, vtotal_min);
     984           0 : }
     985             : 
     986           0 : static void optc1_set_test_pattern(
     987             :         struct timing_generator *optc,
     988             :         /* TODO: replace 'controller_dp_test_pattern' by 'test_pattern_mode'
     989             :          * because this is not DP-specific (which is probably somewhere in DP
     990             :          * encoder) */
     991             :         enum controller_dp_test_pattern test_pattern,
     992             :         enum dc_color_depth color_depth)
     993             : {
     994           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
     995             :         enum test_pattern_color_format bit_depth;
     996             :         enum test_pattern_dyn_range dyn_range;
     997             :         enum test_pattern_mode mode;
     998             :         uint32_t pattern_mask;
     999             :         uint32_t pattern_data;
    1000             :         /* color ramp generator mixes 16-bits color */
    1001           0 :         uint32_t src_bpc = 16;
    1002             :         /* requested bpc */
    1003             :         uint32_t dst_bpc;
    1004             :         uint32_t index;
    1005             :         /* RGB values of the color bars.
    1006             :          * Produce two RGB colors: RGB0 - white (all Fs)
    1007             :          * and RGB1 - black (all 0s)
    1008             :          * (three RGB components for two colors)
    1009             :          */
    1010           0 :         uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
    1011             :                                                 0x0000, 0x0000};
    1012             :         /* dest color (converted to the specified color format) */
    1013             :         uint16_t dst_color[6];
    1014             :         uint32_t inc_base;
    1015             : 
    1016             :         /* translate to bit depth */
    1017             :         switch (color_depth) {
    1018             :         case COLOR_DEPTH_666:
    1019             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
    1020             :         break;
    1021             :         case COLOR_DEPTH_888:
    1022             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
    1023             :         break;
    1024             :         case COLOR_DEPTH_101010:
    1025             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
    1026             :         break;
    1027             :         case COLOR_DEPTH_121212:
    1028             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
    1029             :         break;
    1030             :         default:
    1031             :                 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
    1032             :         break;
    1033             :         }
    1034             : 
    1035           0 :         switch (test_pattern) {
    1036             :         case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
    1037             :         case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
    1038             :         {
    1039           0 :                 dyn_range = (test_pattern ==
    1040             :                                 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
    1041           0 :                                 TEST_PATTERN_DYN_RANGE_CEA :
    1042             :                                 TEST_PATTERN_DYN_RANGE_VESA);
    1043           0 :                 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
    1044             : 
    1045           0 :                 REG_UPDATE_2(OTG_TEST_PATTERN_PARAMETERS,
    1046             :                                 OTG_TEST_PATTERN_VRES, 6,
    1047             :                                 OTG_TEST_PATTERN_HRES, 6);
    1048             : 
    1049           0 :                 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
    1050             :                                 OTG_TEST_PATTERN_EN, 1,
    1051             :                                 OTG_TEST_PATTERN_MODE, mode,
    1052             :                                 OTG_TEST_PATTERN_DYNAMIC_RANGE, dyn_range,
    1053             :                                 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
    1054             :         }
    1055           0 :         break;
    1056             : 
    1057             :         case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
    1058             :         case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
    1059             :         {
    1060           0 :                 mode = (test_pattern ==
    1061             :                         CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
    1062           0 :                         TEST_PATTERN_MODE_VERTICALBARS :
    1063             :                         TEST_PATTERN_MODE_HORIZONTALBARS);
    1064             : 
    1065             :                 switch (bit_depth) {
    1066             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
    1067             :                         dst_bpc = 6;
    1068             :                 break;
    1069             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
    1070             :                         dst_bpc = 8;
    1071             :                 break;
    1072             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
    1073             :                         dst_bpc = 10;
    1074             :                 break;
    1075             :                 default:
    1076             :                         dst_bpc = 8;
    1077             :                 break;
    1078             :                 }
    1079             : 
    1080             :                 /* adjust color to the required colorFormat */
    1081           0 :                 for (index = 0; index < 6; index++) {
    1082             :                         /* dst = 2^dstBpc * src / 2^srcBpc = src >>
    1083             :                          * (srcBpc - dstBpc);
    1084             :                          */
    1085           0 :                         dst_color[index] =
    1086           0 :                                 src_color[index] >> (src_bpc - dst_bpc);
    1087             :                 /* CRTC_TEST_PATTERN_DATA has 16 bits,
    1088             :                  * lowest 6 are hardwired to ZERO
    1089             :                  * color bits should be left aligned to MSB
    1090             :                  * XXXXXXXXXX000000 for 10 bit,
    1091             :                  * XXXXXXXX00000000 for 8 bit and XXXXXX0000000000 for 6
    1092             :                  */
    1093           0 :                         dst_color[index] <<= (16 - dst_bpc);
    1094             :                 }
    1095             : 
    1096           0 :                 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
    1097             : 
    1098             :                 /* We have to write the mask before data, similar to pipeline.
    1099             :                  * For example, for 8 bpc, if we want RGB0 to be magenta,
    1100             :                  * and RGB1 to be cyan,
    1101             :                  * we need to make 7 writes:
    1102             :                  * MASK   DATA
    1103             :                  * 000001 00000000 00000000                     set mask to R0
    1104             :                  * 000010 11111111 00000000     R0 255, 0xFF00, set mask to G0
    1105             :                  * 000100 00000000 00000000     G0 0,   0x0000, set mask to B0
    1106             :                  * 001000 11111111 00000000     B0 255, 0xFF00, set mask to R1
    1107             :                  * 010000 00000000 00000000     R1 0,   0x0000, set mask to G1
    1108             :                  * 100000 11111111 00000000     G1 255, 0xFF00, set mask to B1
    1109             :                  * 100000 11111111 00000000     B1 255, 0xFF00
    1110             :                  *
    1111             :                  * we will make a loop of 6 in which we prepare the mask,
    1112             :                  * then write, then prepare the color for next write.
    1113             :                  * first iteration will write mask only,
    1114             :                  * but each next iteration color prepared in
    1115             :                  * previous iteration will be written within new mask,
    1116             :                  * the last component will written separately,
    1117             :                  * mask is not changing between 6th and 7th write
    1118             :                  * and color will be prepared by last iteration
    1119             :                  */
    1120             : 
    1121             :                 /* write color, color values mask in CRTC_TEST_PATTERN_MASK
    1122             :                  * is B1, G1, R1, B0, G0, R0
    1123             :                  */
    1124           0 :                 pattern_data = 0;
    1125           0 :                 for (index = 0; index < 6; index++) {
    1126             :                         /* prepare color mask, first write PATTERN_DATA
    1127             :                          * will have all zeros
    1128             :                          */
    1129           0 :                         pattern_mask = (1 << index);
    1130             : 
    1131             :                         /* write color component */
    1132           0 :                         REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
    1133             :                                         OTG_TEST_PATTERN_MASK, pattern_mask,
    1134             :                                         OTG_TEST_PATTERN_DATA, pattern_data);
    1135             : 
    1136             :                         /* prepare next color component,
    1137             :                          * will be written in the next iteration
    1138             :                          */
    1139           0 :                         pattern_data = dst_color[index];
    1140             :                 }
    1141             :                 /* write last color component,
    1142             :                  * it's been already prepared in the loop
    1143             :                  */
    1144           0 :                 REG_SET_2(OTG_TEST_PATTERN_COLOR, 0,
    1145             :                                 OTG_TEST_PATTERN_MASK, pattern_mask,
    1146             :                                 OTG_TEST_PATTERN_DATA, pattern_data);
    1147             : 
    1148             :                 /* enable test pattern */
    1149           0 :                 REG_UPDATE_4(OTG_TEST_PATTERN_CONTROL,
    1150             :                                 OTG_TEST_PATTERN_EN, 1,
    1151             :                                 OTG_TEST_PATTERN_MODE, mode,
    1152             :                                 OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
    1153             :                                 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
    1154             :         }
    1155           0 :         break;
    1156             : 
    1157             :         case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
    1158             :         {
    1159           0 :                 mode = (bit_depth ==
    1160             :                         TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
    1161           0 :                         TEST_PATTERN_MODE_DUALRAMP_RGB :
    1162             :                         TEST_PATTERN_MODE_SINGLERAMP_RGB);
    1163             : 
    1164             :                 switch (bit_depth) {
    1165             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
    1166             :                         dst_bpc = 6;
    1167             :                 break;
    1168             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
    1169             :                         dst_bpc = 8;
    1170             :                 break;
    1171             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
    1172             :                         dst_bpc = 10;
    1173             :                 break;
    1174             :                 default:
    1175             :                         dst_bpc = 8;
    1176             :                 break;
    1177             :                 }
    1178             : 
    1179             :                 /* increment for the first ramp for one color gradation
    1180             :                  * 1 gradation for 6-bit color is 2^10
    1181             :                  * gradations in 16-bit color
    1182             :                  */
    1183           0 :                 inc_base = (src_bpc - dst_bpc);
    1184             : 
    1185           0 :                 switch (bit_depth) {
    1186             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
    1187             :                 {
    1188           0 :                         REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
    1189             :                                         OTG_TEST_PATTERN_INC0, inc_base,
    1190             :                                         OTG_TEST_PATTERN_INC1, 0,
    1191             :                                         OTG_TEST_PATTERN_HRES, 6,
    1192             :                                         OTG_TEST_PATTERN_VRES, 6,
    1193             :                                         OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
    1194             :                 }
    1195           0 :                 break;
    1196             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
    1197             :                 {
    1198           0 :                         REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
    1199             :                                         OTG_TEST_PATTERN_INC0, inc_base,
    1200             :                                         OTG_TEST_PATTERN_INC1, 0,
    1201             :                                         OTG_TEST_PATTERN_HRES, 8,
    1202             :                                         OTG_TEST_PATTERN_VRES, 6,
    1203             :                                         OTG_TEST_PATTERN_RAMP0_OFFSET, 0);
    1204             :                 }
    1205           0 :                 break;
    1206             :                 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
    1207             :                 {
    1208           0 :                         REG_UPDATE_5(OTG_TEST_PATTERN_PARAMETERS,
    1209             :                                         OTG_TEST_PATTERN_INC0, inc_base,
    1210             :                                         OTG_TEST_PATTERN_INC1, inc_base + 2,
    1211             :                                         OTG_TEST_PATTERN_HRES, 8,
    1212             :                                         OTG_TEST_PATTERN_VRES, 5,
    1213             :                                         OTG_TEST_PATTERN_RAMP0_OFFSET, 384 << 6);
    1214             :                 }
    1215           0 :                 break;
    1216             :                 default:
    1217             :                 break;
    1218             :                 }
    1219             : 
    1220           0 :                 REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
    1221             : 
    1222             :                 /* enable test pattern */
    1223           0 :                 REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
    1224             : 
    1225           0 :                 REG_SET_4(OTG_TEST_PATTERN_CONTROL, 0,
    1226             :                                 OTG_TEST_PATTERN_EN, 1,
    1227             :                                 OTG_TEST_PATTERN_MODE, mode,
    1228             :                                 OTG_TEST_PATTERN_DYNAMIC_RANGE, 0,
    1229             :                                 OTG_TEST_PATTERN_COLOR_FORMAT, bit_depth);
    1230             :         }
    1231           0 :         break;
    1232             :         case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
    1233             :         {
    1234           0 :                 REG_WRITE(OTG_TEST_PATTERN_CONTROL, 0);
    1235           0 :                 REG_WRITE(OTG_TEST_PATTERN_COLOR, 0);
    1236           0 :                 REG_WRITE(OTG_TEST_PATTERN_PARAMETERS, 0);
    1237             :         }
    1238           0 :         break;
    1239             :         default:
    1240             :                 break;
    1241             : 
    1242             :         }
    1243           0 : }
    1244             : 
    1245           0 : void optc1_get_crtc_scanoutpos(
    1246             :         struct timing_generator *optc,
    1247             :         uint32_t *v_blank_start,
    1248             :         uint32_t *v_blank_end,
    1249             :         uint32_t *h_position,
    1250             :         uint32_t *v_position)
    1251             : {
    1252           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1253             :         struct crtc_position position;
    1254             : 
    1255           0 :         REG_GET_2(OTG_V_BLANK_START_END,
    1256             :                         OTG_V_BLANK_START, v_blank_start,
    1257             :                         OTG_V_BLANK_END, v_blank_end);
    1258             : 
    1259           0 :         optc1_get_position(optc, &position);
    1260             : 
    1261           0 :         *h_position = position.horizontal_count;
    1262           0 :         *v_position = position.vertical_count;
    1263           0 : }
    1264             : 
    1265           0 : static void optc1_enable_stereo(struct timing_generator *optc,
    1266             :         const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
    1267             : {
    1268           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1269             : 
    1270           0 :         if (flags) {
    1271             :                 uint32_t stereo_en;
    1272           0 :                 stereo_en = flags->FRAME_PACKED == 0 ? 1 : 0;
    1273             : 
    1274           0 :                 if (flags->PROGRAM_STEREO)
    1275           0 :                         REG_UPDATE_3(OTG_STEREO_CONTROL,
    1276             :                                 OTG_STEREO_EN, stereo_en,
    1277             :                                 OTG_STEREO_SYNC_OUTPUT_LINE_NUM, 0,
    1278             :                                 OTG_STEREO_SYNC_OUTPUT_POLARITY, flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
    1279             : 
    1280           0 :                 if (flags->PROGRAM_POLARITY)
    1281           0 :                         REG_UPDATE(OTG_STEREO_CONTROL,
    1282             :                                 OTG_STEREO_EYE_FLAG_POLARITY,
    1283             :                                 flags->RIGHT_EYE_POLARITY == 0 ? 0 : 1);
    1284             : 
    1285           0 :                 if (flags->DISABLE_STEREO_DP_SYNC)
    1286           0 :                         REG_UPDATE(OTG_STEREO_CONTROL,
    1287             :                                 OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, 1);
    1288             : 
    1289           0 :                 if (flags->PROGRAM_STEREO)
    1290           0 :                         REG_UPDATE_2(OTG_3D_STRUCTURE_CONTROL,
    1291             :                                 OTG_3D_STRUCTURE_EN, flags->FRAME_PACKED,
    1292             :                                 OTG_3D_STRUCTURE_STEREO_SEL_OVR, flags->FRAME_PACKED);
    1293             : 
    1294             :         }
    1295           0 : }
    1296             : 
    1297           0 : void optc1_program_stereo(struct timing_generator *optc,
    1298             :         const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
    1299             : {
    1300           0 :         if (flags->PROGRAM_STEREO)
    1301           0 :                 optc1_enable_stereo(optc, timing, flags);
    1302             :         else
    1303           0 :                 optc1_disable_stereo(optc);
    1304           0 : }
    1305             : 
    1306             : 
    1307           0 : bool optc1_is_stereo_left_eye(struct timing_generator *optc)
    1308             : {
    1309           0 :         bool ret = false;
    1310           0 :         uint32_t left_eye = 0;
    1311           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1312             : 
    1313           0 :         REG_GET(OTG_STEREO_STATUS,
    1314             :                 OTG_STEREO_CURRENT_EYE, &left_eye);
    1315           0 :         if (left_eye == 1)
    1316             :                 ret = true;
    1317             :         else
    1318           0 :                 ret = false;
    1319             : 
    1320           0 :         return ret;
    1321             : }
    1322             : 
    1323           0 : bool optc1_get_hw_timing(struct timing_generator *tg,
    1324             :                 struct dc_crtc_timing *hw_crtc_timing)
    1325             : {
    1326           0 :         struct dcn_otg_state s = {0};
    1327             : 
    1328           0 :         if (tg == NULL || hw_crtc_timing == NULL)
    1329             :                 return false;
    1330             : 
    1331           0 :         optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
    1332             : 
    1333           0 :         hw_crtc_timing->h_total = s.h_total + 1;
    1334           0 :         hw_crtc_timing->h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end);
    1335           0 :         hw_crtc_timing->h_front_porch = s.h_total + 1 - s.h_blank_start;
    1336           0 :         hw_crtc_timing->h_sync_width = s.h_sync_a_end - s.h_sync_a_start;
    1337             : 
    1338           0 :         hw_crtc_timing->v_total = s.v_total + 1;
    1339           0 :         hw_crtc_timing->v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end);
    1340           0 :         hw_crtc_timing->v_front_porch = s.v_total + 1 - s.v_blank_start;
    1341           0 :         hw_crtc_timing->v_sync_width = s.v_sync_a_end - s.v_sync_a_start;
    1342             : 
    1343           0 :         return true;
    1344             : }
    1345             : 
    1346             : 
    1347           0 : void optc1_read_otg_state(struct optc *optc1,
    1348             :                 struct dcn_otg_state *s)
    1349             : {
    1350           0 :         REG_GET(OTG_CONTROL,
    1351             :                         OTG_MASTER_EN, &s->otg_enabled);
    1352             : 
    1353           0 :         REG_GET_2(OTG_V_BLANK_START_END,
    1354             :                         OTG_V_BLANK_START, &s->v_blank_start,
    1355             :                         OTG_V_BLANK_END, &s->v_blank_end);
    1356             : 
    1357           0 :         REG_GET(OTG_V_SYNC_A_CNTL,
    1358             :                         OTG_V_SYNC_A_POL, &s->v_sync_a_pol);
    1359             : 
    1360           0 :         REG_GET(OTG_V_TOTAL,
    1361             :                         OTG_V_TOTAL, &s->v_total);
    1362             : 
    1363           0 :         REG_GET(OTG_V_TOTAL_MAX,
    1364             :                         OTG_V_TOTAL_MAX, &s->v_total_max);
    1365             : 
    1366           0 :         REG_GET(OTG_V_TOTAL_MIN,
    1367             :                         OTG_V_TOTAL_MIN, &s->v_total_min);
    1368             : 
    1369           0 :         REG_GET(OTG_V_TOTAL_CONTROL,
    1370             :                         OTG_V_TOTAL_MAX_SEL, &s->v_total_max_sel);
    1371             : 
    1372           0 :         REG_GET(OTG_V_TOTAL_CONTROL,
    1373             :                         OTG_V_TOTAL_MIN_SEL, &s->v_total_min_sel);
    1374             : 
    1375           0 :         REG_GET_2(OTG_V_SYNC_A,
    1376             :                         OTG_V_SYNC_A_START, &s->v_sync_a_start,
    1377             :                         OTG_V_SYNC_A_END, &s->v_sync_a_end);
    1378             : 
    1379           0 :         REG_GET_2(OTG_H_BLANK_START_END,
    1380             :                         OTG_H_BLANK_START, &s->h_blank_start,
    1381             :                         OTG_H_BLANK_END, &s->h_blank_end);
    1382             : 
    1383           0 :         REG_GET_2(OTG_H_SYNC_A,
    1384             :                         OTG_H_SYNC_A_START, &s->h_sync_a_start,
    1385             :                         OTG_H_SYNC_A_END, &s->h_sync_a_end);
    1386             : 
    1387           0 :         REG_GET(OTG_H_SYNC_A_CNTL,
    1388             :                         OTG_H_SYNC_A_POL, &s->h_sync_a_pol);
    1389             : 
    1390           0 :         REG_GET(OTG_H_TOTAL,
    1391             :                         OTG_H_TOTAL, &s->h_total);
    1392             : 
    1393           0 :         REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
    1394             :                         OPTC_UNDERFLOW_OCCURRED_STATUS, &s->underflow_occurred_status);
    1395             : 
    1396           0 :         REG_GET(OTG_VERTICAL_INTERRUPT2_CONTROL,
    1397             :                         OTG_VERTICAL_INTERRUPT2_INT_ENABLE, &s->vertical_interrupt2_en);
    1398             : 
    1399           0 :         REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION,
    1400             :                         OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line);
    1401           0 : }
    1402             : 
    1403           0 : bool optc1_get_otg_active_size(struct timing_generator *optc,
    1404             :                 uint32_t *otg_active_width,
    1405             :                 uint32_t *otg_active_height)
    1406             : {
    1407             :         uint32_t otg_enabled;
    1408             :         uint32_t v_blank_start;
    1409             :         uint32_t v_blank_end;
    1410             :         uint32_t h_blank_start;
    1411             :         uint32_t h_blank_end;
    1412           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1413             : 
    1414             : 
    1415           0 :         REG_GET(OTG_CONTROL,
    1416             :                         OTG_MASTER_EN, &otg_enabled);
    1417             : 
    1418           0 :         if (otg_enabled == 0)
    1419             :                 return false;
    1420             : 
    1421           0 :         REG_GET_2(OTG_V_BLANK_START_END,
    1422             :                         OTG_V_BLANK_START, &v_blank_start,
    1423             :                         OTG_V_BLANK_END, &v_blank_end);
    1424             : 
    1425           0 :         REG_GET_2(OTG_H_BLANK_START_END,
    1426             :                         OTG_H_BLANK_START, &h_blank_start,
    1427             :                         OTG_H_BLANK_END, &h_blank_end);
    1428             : 
    1429           0 :         *otg_active_width = v_blank_start - v_blank_end;
    1430           0 :         *otg_active_height = h_blank_start - h_blank_end;
    1431           0 :         return true;
    1432             : }
    1433             : 
    1434           0 : void optc1_clear_optc_underflow(struct timing_generator *optc)
    1435             : {
    1436           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1437             : 
    1438           0 :         REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1);
    1439           0 : }
    1440             : 
    1441           0 : void optc1_tg_init(struct timing_generator *optc)
    1442             : {
    1443           0 :         optc1_set_blank_data_double_buffer(optc, true);
    1444           0 :         optc1_set_timing_double_buffer(optc, true);
    1445           0 :         optc1_clear_optc_underflow(optc);
    1446           0 : }
    1447             : 
    1448           0 : bool optc1_is_tg_enabled(struct timing_generator *optc)
    1449             : {
    1450           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1451           0 :         uint32_t otg_enabled = 0;
    1452             : 
    1453           0 :         REG_GET(OTG_CONTROL, OTG_MASTER_EN, &otg_enabled);
    1454             : 
    1455           0 :         return (otg_enabled != 0);
    1456             : 
    1457             : }
    1458             : 
    1459           0 : bool optc1_is_optc_underflow_occurred(struct timing_generator *optc)
    1460             : {
    1461           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1462           0 :         uint32_t underflow_occurred = 0;
    1463             : 
    1464           0 :         REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
    1465             :                         OPTC_UNDERFLOW_OCCURRED_STATUS,
    1466             :                         &underflow_occurred);
    1467             : 
    1468           0 :         return (underflow_occurred == 1);
    1469             : }
    1470             : 
    1471           0 : bool optc1_configure_crc(struct timing_generator *optc,
    1472             :                           const struct crc_params *params)
    1473             : {
    1474           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1475             : 
    1476             :         /* Cannot configure crc on a CRTC that is disabled */
    1477           0 :         if (!optc1_is_tg_enabled(optc))
    1478             :                 return false;
    1479             : 
    1480           0 :         REG_WRITE(OTG_CRC_CNTL, 0);
    1481             : 
    1482           0 :         if (!params->enable)
    1483             :                 return true;
    1484             : 
    1485             :         /* Program frame boundaries */
    1486             :         /* Window A x axis start and end. */
    1487           0 :         REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL,
    1488             :                         OTG_CRC0_WINDOWA_X_START, params->windowa_x_start,
    1489             :                         OTG_CRC0_WINDOWA_X_END, params->windowa_x_end);
    1490             : 
    1491             :         /* Window A y axis start and end. */
    1492           0 :         REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL,
    1493             :                         OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start,
    1494             :                         OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end);
    1495             : 
    1496             :         /* Window B x axis start and end. */
    1497           0 :         REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL,
    1498             :                         OTG_CRC0_WINDOWB_X_START, params->windowb_x_start,
    1499             :                         OTG_CRC0_WINDOWB_X_END, params->windowb_x_end);
    1500             : 
    1501             :         /* Window B y axis start and end. */
    1502           0 :         REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL,
    1503             :                         OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start,
    1504             :                         OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end);
    1505             : 
    1506             :         /* Set crc mode and selection, and enable. Only using CRC0*/
    1507           0 :         REG_UPDATE_3(OTG_CRC_CNTL,
    1508             :                         OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
    1509             :                         OTG_CRC0_SELECT, params->selection,
    1510             :                         OTG_CRC_EN, 1);
    1511             : 
    1512           0 :         return true;
    1513             : }
    1514             : 
    1515             : /**
    1516             :  * optc1_get_crc - Capture CRC result per component
    1517             :  *
    1518             :  * @optc: timing_generator instance.
    1519             :  * @r_cr: 16-bit primary CRC signature for red data.
    1520             :  * @g_y: 16-bit primary CRC signature for green data.
    1521             :  * @b_cb: 16-bit primary CRC signature for blue data.
    1522             :  *
    1523             :  * This function reads the CRC signature from the OPTC registers. Notice that
    1524             :  * we have three registers to keep the CRC result per color component (RGB).
    1525             :  *
    1526             :  * Returns:
    1527             :  * If CRC is disabled, return false; otherwise, return true, and the CRC
    1528             :  * results in the parameters.
    1529             :  */
    1530           0 : bool optc1_get_crc(struct timing_generator *optc,
    1531             :                    uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
    1532             : {
    1533           0 :         uint32_t field = 0;
    1534           0 :         struct optc *optc1 = DCN10TG_FROM_TG(optc);
    1535             : 
    1536           0 :         REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
    1537             : 
    1538             :         /* Early return if CRC is not enabled for this CRTC */
    1539           0 :         if (!field)
    1540             :                 return false;
    1541             : 
    1542             :         /* OTG_CRC0_DATA_RG has the CRC16 results for the red and green component */
    1543           0 :         REG_GET_2(OTG_CRC0_DATA_RG,
    1544             :                   CRC0_R_CR, r_cr,
    1545             :                   CRC0_G_Y, g_y);
    1546             : 
    1547             :         /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */
    1548           0 :         REG_GET(OTG_CRC0_DATA_B,
    1549             :                 CRC0_B_CB, b_cb);
    1550             : 
    1551           0 :         return true;
    1552             : }
    1553             : 
    1554             : static const struct timing_generator_funcs dcn10_tg_funcs = {
    1555             :                 .validate_timing = optc1_validate_timing,
    1556             :                 .program_timing = optc1_program_timing,
    1557             :                 .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
    1558             :                 .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
    1559             :                 .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
    1560             :                 .program_global_sync = optc1_program_global_sync,
    1561             :                 .enable_crtc = optc1_enable_crtc,
    1562             :                 .disable_crtc = optc1_disable_crtc,
    1563             :                 /* used by enable_timing_synchronization. Not need for FPGA */
    1564             :                 .is_counter_moving = optc1_is_counter_moving,
    1565             :                 .get_position = optc1_get_position,
    1566             :                 .get_frame_count = optc1_get_vblank_counter,
    1567             :                 .get_scanoutpos = optc1_get_crtc_scanoutpos,
    1568             :                 .get_otg_active_size = optc1_get_otg_active_size,
    1569             :                 .set_early_control = optc1_set_early_control,
    1570             :                 /* used by enable_timing_synchronization. Not need for FPGA */
    1571             :                 .wait_for_state = optc1_wait_for_state,
    1572             :                 .set_blank = optc1_set_blank,
    1573             :                 .is_blanked = optc1_is_blanked,
    1574             :                 .set_blank_color = optc1_program_blank_color,
    1575             :                 .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
    1576             :                 .enable_reset_trigger = optc1_enable_reset_trigger,
    1577             :                 .enable_crtc_reset = optc1_enable_crtc_reset,
    1578             :                 .disable_reset_trigger = optc1_disable_reset_trigger,
    1579             :                 .lock = optc1_lock,
    1580             :                 .is_locked = optc1_is_locked,
    1581             :                 .unlock = optc1_unlock,
    1582             :                 .enable_optc_clock = optc1_enable_optc_clock,
    1583             :                 .set_drr = optc1_set_drr,
    1584             :                 .get_last_used_drr_vtotal = NULL,
    1585             :                 .set_static_screen_control = optc1_set_static_screen_control,
    1586             :                 .set_test_pattern = optc1_set_test_pattern,
    1587             :                 .program_stereo = optc1_program_stereo,
    1588             :                 .is_stereo_left_eye = optc1_is_stereo_left_eye,
    1589             :                 .set_blank_data_double_buffer = optc1_set_blank_data_double_buffer,
    1590             :                 .tg_init = optc1_tg_init,
    1591             :                 .is_tg_enabled = optc1_is_tg_enabled,
    1592             :                 .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
    1593             :                 .clear_optc_underflow = optc1_clear_optc_underflow,
    1594             :                 .get_crc = optc1_get_crc,
    1595             :                 .configure_crc = optc1_configure_crc,
    1596             :                 .set_vtg_params = optc1_set_vtg_params,
    1597             :                 .program_manual_trigger = optc1_program_manual_trigger,
    1598             :                 .setup_manual_trigger = optc1_setup_manual_trigger,
    1599             :                 .get_hw_timing = optc1_get_hw_timing,
    1600             : };
    1601             : 
    1602           0 : void dcn10_timing_generator_init(struct optc *optc1)
    1603             : {
    1604           0 :         optc1->base.funcs = &dcn10_tg_funcs;
    1605             : 
    1606           0 :         optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
    1607           0 :         optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
    1608             : 
    1609           0 :         optc1->min_h_blank = 32;
    1610           0 :         optc1->min_v_blank = 3;
    1611           0 :         optc1->min_v_blank_interlace = 5;
    1612           0 :         optc1->min_h_sync_width = 4;
    1613           0 :         optc1->min_v_sync_width = 1;
    1614           0 : }
    1615             : 
    1616             : /* "Containter" vs. "pixel" is a concept within HW blocks, mostly those closer to the back-end. It works like this:
    1617             :  *
    1618             :  * - In most of the formats (RGB or YCbCr 4:4:4, 4:2:2 uncompressed and DSC 4:2:2 Simple) pixel rate is the same as
    1619             :  *   containter rate.
    1620             :  *
    1621             :  * - In 4:2:0 (DSC or uncompressed) there are two pixels per container, hence the target container rate has to be
    1622             :  *   halved to maintain the correct pixel rate.
    1623             :  *
    1624             :  * - Unlike 4:2:2 uncompressed, DSC 4:2:2 Native also has two pixels per container (this happens when DSC is applied
    1625             :  *   to it) and has to be treated the same as 4:2:0, i.e. target containter rate has to be halved in this case as well.
    1626             :  *
    1627             :  */
    1628           0 : bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing)
    1629             : {
    1630           0 :         bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420;
    1631             : 
    1632           0 :         two_pix = two_pix || (timing->flags.DSC && timing->pixel_encoding == PIXEL_ENCODING_YCBCR422
    1633           0 :                         && !timing->dsc_cfg.ycbcr422_simple);
    1634           0 :         return two_pix;
    1635             : }
    1636             : 

Generated by: LCOV version 1.14