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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors: AMD
      23             :  *
      24             :  */
      25             : 
      26             : #include "dm_services.h"
      27             : #include "dc.h"
      28             : #include "dc_bios_types.h"
      29             : #include "core_types.h"
      30             : #include "core_status.h"
      31             : #include "resource.h"
      32             : #include "dm_helpers.h"
      33             : #include "dce110_timing_generator.h"
      34             : #include "dce/dce_hwseq.h"
      35             : #include "gpio_service_interface.h"
      36             : 
      37             : #include "dce110_compressor.h"
      38             : 
      39             : #include "bios/bios_parser_helper.h"
      40             : #include "timing_generator.h"
      41             : #include "mem_input.h"
      42             : #include "opp.h"
      43             : #include "ipp.h"
      44             : #include "transform.h"
      45             : #include "stream_encoder.h"
      46             : #include "link_encoder.h"
      47             : #include "link_enc_cfg.h"
      48             : #include "link_hwss.h"
      49             : #include "dc_link_dp.h"
      50             : #include "dccg.h"
      51             : #include "clock_source.h"
      52             : #include "clk_mgr.h"
      53             : #include "abm.h"
      54             : #include "audio.h"
      55             : #include "reg_helper.h"
      56             : #include "panel_cntl.h"
      57             : #include "inc/link_dpcd.h"
      58             : #include "dpcd_defs.h"
      59             : /* include DCE11 register header files */
      60             : #include "dce/dce_11_0_d.h"
      61             : #include "dce/dce_11_0_sh_mask.h"
      62             : #include "custom_float.h"
      63             : 
      64             : #include "atomfirmware.h"
      65             : 
      66             : #include "dcn10/dcn10_hw_sequencer.h"
      67             : 
      68             : #include "link/link_dp_trace.h"
      69             : #include "dce110_hw_sequencer.h"
      70             : 
      71             : #define GAMMA_HW_POINTS_NUM 256
      72             : 
      73             : /*
      74             :  * All values are in milliseconds;
      75             :  * For eDP, after power-up/power/down,
      76             :  * 300/500 msec max. delay from LCDVCC to black video generation
      77             :  */
      78             : #define PANEL_POWER_UP_TIMEOUT 300
      79             : #define PANEL_POWER_DOWN_TIMEOUT 500
      80             : #define HPD_CHECK_INTERVAL 10
      81             : #define OLED_POST_T7_DELAY 100
      82             : #define OLED_PRE_T11_DELAY 150
      83             : 
      84             : #define CTX \
      85             :         hws->ctx
      86             : 
      87             : #define DC_LOGGER_INIT()
      88             : 
      89             : #define REG(reg)\
      90             :         hws->regs->reg
      91             : 
      92             : #undef FN
      93             : #define FN(reg_name, field_name) \
      94             :         hws->shifts->field_name, hws->masks->field_name
      95             : 
      96             : struct dce110_hw_seq_reg_offsets {
      97             :         uint32_t crtc;
      98             : };
      99             : 
     100             : static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
     101             : {
     102             :         .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
     103             : },
     104             : {
     105             :         .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
     106             : },
     107             : {
     108             :         .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
     109             : },
     110             : {
     111             :         .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
     112             : }
     113             : };
     114             : 
     115             : #define HW_REG_BLND(reg, id)\
     116             :         (reg + reg_offsets[id].blnd)
     117             : 
     118             : #define HW_REG_CRTC(reg, id)\
     119             :         (reg + reg_offsets[id].crtc)
     120             : 
     121             : #define MAX_WATERMARK 0xFFFF
     122             : #define SAFE_NBP_MARK 0x7FFF
     123             : 
     124             : /*******************************************************************************
     125             :  * Private definitions
     126             :  ******************************************************************************/
     127             : /***************************PIPE_CONTROL***********************************/
     128           0 : static void dce110_init_pte(struct dc_context *ctx)
     129             : {
     130             :         uint32_t addr;
     131           0 :         uint32_t value = 0;
     132           0 :         uint32_t chunk_int = 0;
     133           0 :         uint32_t chunk_mul = 0;
     134             : 
     135           0 :         addr = mmUNP_DVMM_PTE_CONTROL;
     136           0 :         value = dm_read_reg(ctx, addr);
     137             : 
     138           0 :         set_reg_field_value(
     139             :                 value,
     140             :                 0,
     141             :                 DVMM_PTE_CONTROL,
     142             :                 DVMM_USE_SINGLE_PTE);
     143             : 
     144           0 :         set_reg_field_value(
     145             :                 value,
     146             :                 1,
     147             :                 DVMM_PTE_CONTROL,
     148             :                 DVMM_PTE_BUFFER_MODE0);
     149             : 
     150           0 :         set_reg_field_value(
     151             :                 value,
     152             :                 1,
     153             :                 DVMM_PTE_CONTROL,
     154             :                 DVMM_PTE_BUFFER_MODE1);
     155             : 
     156           0 :         dm_write_reg(ctx, addr, value);
     157             : 
     158           0 :         addr = mmDVMM_PTE_REQ;
     159           0 :         value = dm_read_reg(ctx, addr);
     160             : 
     161           0 :         chunk_int = get_reg_field_value(
     162             :                 value,
     163             :                 DVMM_PTE_REQ,
     164             :                 HFLIP_PTEREQ_PER_CHUNK_INT);
     165             : 
     166           0 :         chunk_mul = get_reg_field_value(
     167             :                 value,
     168             :                 DVMM_PTE_REQ,
     169             :                 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
     170             : 
     171           0 :         if (chunk_int != 0x4 || chunk_mul != 0x4) {
     172             : 
     173           0 :                 set_reg_field_value(
     174             :                         value,
     175             :                         255,
     176             :                         DVMM_PTE_REQ,
     177             :                         MAX_PTEREQ_TO_ISSUE);
     178             : 
     179           0 :                 set_reg_field_value(
     180             :                         value,
     181             :                         4,
     182             :                         DVMM_PTE_REQ,
     183             :                         HFLIP_PTEREQ_PER_CHUNK_INT);
     184             : 
     185           0 :                 set_reg_field_value(
     186             :                         value,
     187             :                         4,
     188             :                         DVMM_PTE_REQ,
     189             :                         HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
     190             : 
     191           0 :                 dm_write_reg(ctx, addr, value);
     192             :         }
     193           0 : }
     194             : /**************************************************************************/
     195             : 
     196           0 : static void enable_display_pipe_clock_gating(
     197             :         struct dc_context *ctx,
     198             :         bool clock_gating)
     199             : {
     200             :         /*TODO*/
     201           0 : }
     202             : 
     203           0 : static bool dce110_enable_display_power_gating(
     204             :         struct dc *dc,
     205             :         uint8_t controller_id,
     206             :         struct dc_bios *dcb,
     207             :         enum pipe_gating_control power_gating)
     208             : {
     209           0 :         enum bp_result bp_result = BP_RESULT_OK;
     210             :         enum bp_pipe_control_action cntl;
     211           0 :         struct dc_context *ctx = dc->ctx;
     212           0 :         unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
     213             : 
     214           0 :         if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
     215             :                 return true;
     216             : 
     217           0 :         if (power_gating == PIPE_GATING_CONTROL_INIT)
     218             :                 cntl = ASIC_PIPE_INIT;
     219           0 :         else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
     220             :                 cntl = ASIC_PIPE_ENABLE;
     221             :         else
     222           0 :                 cntl = ASIC_PIPE_DISABLE;
     223             : 
     224           0 :         if (controller_id == underlay_idx)
     225           0 :                 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
     226             : 
     227           0 :         if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
     228             : 
     229           0 :                 bp_result = dcb->funcs->enable_disp_power_gating(
     230           0 :                                                 dcb, controller_id + 1, cntl);
     231             : 
     232             :                 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
     233             :                  * by default when command table is called
     234             :                  *
     235             :                  * Bios parser accepts controller_id = 6 as indicative of
     236             :                  * underlay pipe in dce110. But we do not support more
     237             :                  * than 3.
     238             :                  */
     239           0 :                 if (controller_id < CONTROLLER_ID_MAX - 1)
     240           0 :                         dm_write_reg(ctx,
     241             :                                 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
     242             :                                 0);
     243             :         }
     244             : 
     245           0 :         if (power_gating != PIPE_GATING_CONTROL_ENABLE)
     246           0 :                 dce110_init_pte(ctx);
     247             : 
     248           0 :         if (bp_result == BP_RESULT_OK)
     249             :                 return true;
     250             :         else
     251           0 :                 return false;
     252             : }
     253             : 
     254           0 : static void build_prescale_params(struct ipp_prescale_params *prescale_params,
     255             :                 const struct dc_plane_state *plane_state)
     256             : {
     257           0 :         prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
     258             : 
     259           0 :         switch (plane_state->format) {
     260             :         case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
     261           0 :                 prescale_params->scale = 0x2082;
     262             :                 break;
     263             :         case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
     264             :         case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
     265           0 :                 prescale_params->scale = 0x2020;
     266             :                 break;
     267             :         case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
     268             :         case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
     269           0 :                 prescale_params->scale = 0x2008;
     270             :                 break;
     271             :         case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
     272             :         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
     273             :         case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
     274           0 :                 prescale_params->scale = 0x2000;
     275             :                 break;
     276             :         default:
     277           0 :                 ASSERT(false);
     278             :                 break;
     279             :         }
     280           0 : }
     281             : 
     282             : static bool
     283           0 : dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
     284             :                                const struct dc_plane_state *plane_state)
     285             : {
     286           0 :         struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
     287           0 :         const struct dc_transfer_func *tf = NULL;
     288           0 :         struct ipp_prescale_params prescale_params = { 0 };
     289           0 :         bool result = true;
     290             : 
     291           0 :         if (ipp == NULL)
     292             :                 return false;
     293             : 
     294           0 :         if (plane_state->in_transfer_func)
     295           0 :                 tf = plane_state->in_transfer_func;
     296             : 
     297           0 :         build_prescale_params(&prescale_params, plane_state);
     298           0 :         ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
     299             : 
     300           0 :         if (plane_state->gamma_correction &&
     301           0 :                         !plane_state->gamma_correction->is_identity &&
     302           0 :                         dce_use_lut(plane_state->format))
     303           0 :                 ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction);
     304             : 
     305           0 :         if (tf == NULL) {
     306             :                 /* Default case if no input transfer function specified */
     307           0 :                 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
     308           0 :         } else if (tf->type == TF_TYPE_PREDEFINED) {
     309           0 :                 switch (tf->tf) {
     310             :                 case TRANSFER_FUNCTION_SRGB:
     311           0 :                         ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
     312           0 :                         break;
     313             :                 case TRANSFER_FUNCTION_BT709:
     314           0 :                         ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC);
     315           0 :                         break;
     316             :                 case TRANSFER_FUNCTION_LINEAR:
     317           0 :                         ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
     318           0 :                         break;
     319             :                 case TRANSFER_FUNCTION_PQ:
     320             :                 default:
     321             :                         result = false;
     322             :                         break;
     323             :                 }
     324           0 :         } else if (tf->type == TF_TYPE_BYPASS) {
     325           0 :                 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
     326             :         } else {
     327             :                 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
     328             :                 result = false;
     329             :         }
     330             : 
     331             :         return result;
     332             : }
     333             : 
     334           0 : static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted,
     335             :                                     struct curve_points *arr_points,
     336             :                                     uint32_t hw_points_num)
     337             : {
     338             :         struct custom_float_format fmt;
     339             : 
     340           0 :         struct pwl_result_data *rgb = rgb_resulted;
     341             : 
     342           0 :         uint32_t i = 0;
     343             : 
     344           0 :         fmt.exponenta_bits = 6;
     345           0 :         fmt.mantissa_bits = 12;
     346           0 :         fmt.sign = true;
     347             : 
     348           0 :         if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
     349             :                                             &arr_points[0].custom_float_x)) {
     350           0 :                 BREAK_TO_DEBUGGER();
     351           0 :                 return false;
     352             :         }
     353             : 
     354           0 :         if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
     355             :                                             &arr_points[0].custom_float_offset)) {
     356           0 :                 BREAK_TO_DEBUGGER();
     357           0 :                 return false;
     358             :         }
     359             : 
     360           0 :         if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
     361             :                                             &arr_points[0].custom_float_slope)) {
     362           0 :                 BREAK_TO_DEBUGGER();
     363           0 :                 return false;
     364             :         }
     365             : 
     366           0 :         fmt.mantissa_bits = 10;
     367           0 :         fmt.sign = false;
     368             : 
     369           0 :         if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
     370             :                                             &arr_points[1].custom_float_x)) {
     371           0 :                 BREAK_TO_DEBUGGER();
     372           0 :                 return false;
     373             :         }
     374             : 
     375           0 :         if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
     376             :                                             &arr_points[1].custom_float_y)) {
     377           0 :                 BREAK_TO_DEBUGGER();
     378           0 :                 return false;
     379             :         }
     380             : 
     381           0 :         if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
     382             :                                             &arr_points[1].custom_float_slope)) {
     383           0 :                 BREAK_TO_DEBUGGER();
     384           0 :                 return false;
     385             :         }
     386             : 
     387           0 :         fmt.mantissa_bits = 12;
     388           0 :         fmt.sign = true;
     389             : 
     390           0 :         while (i != hw_points_num) {
     391           0 :                 if (!convert_to_custom_float_format(rgb->red, &fmt,
     392             :                                                     &rgb->red_reg)) {
     393           0 :                         BREAK_TO_DEBUGGER();
     394           0 :                         return false;
     395             :                 }
     396             : 
     397           0 :                 if (!convert_to_custom_float_format(rgb->green, &fmt,
     398             :                                                     &rgb->green_reg)) {
     399           0 :                         BREAK_TO_DEBUGGER();
     400           0 :                         return false;
     401             :                 }
     402             : 
     403           0 :                 if (!convert_to_custom_float_format(rgb->blue, &fmt,
     404             :                                                     &rgb->blue_reg)) {
     405           0 :                         BREAK_TO_DEBUGGER();
     406           0 :                         return false;
     407             :                 }
     408             : 
     409           0 :                 if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
     410             :                                                     &rgb->delta_red_reg)) {
     411           0 :                         BREAK_TO_DEBUGGER();
     412           0 :                         return false;
     413             :                 }
     414             : 
     415           0 :                 if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
     416             :                                                     &rgb->delta_green_reg)) {
     417           0 :                         BREAK_TO_DEBUGGER();
     418           0 :                         return false;
     419             :                 }
     420             : 
     421           0 :                 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
     422             :                                                     &rgb->delta_blue_reg)) {
     423           0 :                         BREAK_TO_DEBUGGER();
     424           0 :                         return false;
     425             :                 }
     426             : 
     427           0 :                 ++rgb;
     428           0 :                 ++i;
     429             :         }
     430             : 
     431             :         return true;
     432             : }
     433             : 
     434             : #define MAX_LOW_POINT      25
     435             : #define NUMBER_REGIONS     16
     436             : #define NUMBER_SW_SEGMENTS 16
     437             : 
     438             : static bool
     439           0 : dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
     440             :                                       struct pwl_params *regamma_params)
     441             : {
     442             :         struct curve_points *arr_points;
     443             :         struct pwl_result_data *rgb_resulted;
     444             :         struct pwl_result_data *rgb;
     445             :         struct pwl_result_data *rgb_plus_1;
     446             :         struct fixed31_32 y_r;
     447             :         struct fixed31_32 y_g;
     448             :         struct fixed31_32 y_b;
     449             :         struct fixed31_32 y1_min;
     450             :         struct fixed31_32 y3_max;
     451             : 
     452             :         int32_t region_start, region_end;
     453             :         uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points;
     454             : 
     455           0 :         if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
     456             :                 return false;
     457             : 
     458           0 :         arr_points = regamma_params->arr_points;
     459           0 :         rgb_resulted = regamma_params->rgb_resulted;
     460           0 :         hw_points = 0;
     461             : 
     462           0 :         memset(regamma_params, 0, sizeof(struct pwl_params));
     463             : 
     464           0 :         if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
     465             :                 /* 16 segments
     466             :                  * segments are from 2^-11 to 2^5
     467             :                  */
     468             :                 region_start = -11;
     469             :                 region_end = region_start + NUMBER_REGIONS;
     470             : 
     471           0 :                 for (i = 0; i < NUMBER_REGIONS; i++)
     472           0 :                         seg_distr[i] = 4;
     473             : 
     474             :         } else {
     475             :                 /* 10 segments
     476             :                  * segment is from 2^-10 to 2^1
     477             :                  * We include an extra segment for range [2^0, 2^1). This is to
     478             :                  * ensure that colors with normalized values of 1 don't miss the
     479             :                  * LUT.
     480             :                  */
     481           0 :                 region_start = -10;
     482           0 :                 region_end = 1;
     483             : 
     484           0 :                 seg_distr[0] = 4;
     485           0 :                 seg_distr[1] = 4;
     486           0 :                 seg_distr[2] = 4;
     487           0 :                 seg_distr[3] = 4;
     488           0 :                 seg_distr[4] = 4;
     489           0 :                 seg_distr[5] = 4;
     490           0 :                 seg_distr[6] = 4;
     491           0 :                 seg_distr[7] = 4;
     492           0 :                 seg_distr[8] = 4;
     493           0 :                 seg_distr[9] = 4;
     494           0 :                 seg_distr[10] = 0;
     495           0 :                 seg_distr[11] = -1;
     496           0 :                 seg_distr[12] = -1;
     497           0 :                 seg_distr[13] = -1;
     498           0 :                 seg_distr[14] = -1;
     499           0 :                 seg_distr[15] = -1;
     500             :         }
     501             : 
     502           0 :         for (k = 0; k < 16; k++) {
     503           0 :                 if (seg_distr[k] != -1)
     504           0 :                         hw_points += (1 << seg_distr[k]);
     505             :         }
     506             : 
     507             :         j = 0;
     508           0 :         for (k = 0; k < (region_end - region_start); k++) {
     509           0 :                 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
     510           0 :                 start_index = (region_start + k + MAX_LOW_POINT) *
     511             :                                 NUMBER_SW_SEGMENTS;
     512           0 :                 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
     513           0 :                                 i += increment) {
     514           0 :                         if (j == hw_points - 1)
     515             :                                 break;
     516           0 :                         rgb_resulted[j].red = output_tf->tf_pts.red[i];
     517           0 :                         rgb_resulted[j].green = output_tf->tf_pts.green[i];
     518           0 :                         rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
     519           0 :                         j++;
     520             :                 }
     521             :         }
     522             : 
     523             :         /* last point */
     524           0 :         start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
     525           0 :         rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
     526           0 :         rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
     527           0 :         rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
     528             : 
     529           0 :         arr_points[0].x = dc_fixpt_pow(dc_fixpt_from_int(2),
     530             :                                              dc_fixpt_from_int(region_start));
     531           0 :         arr_points[1].x = dc_fixpt_pow(dc_fixpt_from_int(2),
     532             :                                              dc_fixpt_from_int(region_end));
     533             : 
     534           0 :         y_r = rgb_resulted[0].red;
     535           0 :         y_g = rgb_resulted[0].green;
     536           0 :         y_b = rgb_resulted[0].blue;
     537             : 
     538             :         y1_min = dc_fixpt_min(y_r, dc_fixpt_min(y_g, y_b));
     539             : 
     540           0 :         arr_points[0].y = y1_min;
     541           0 :         arr_points[0].slope = dc_fixpt_div(arr_points[0].y,
     542             :                                                  arr_points[0].x);
     543             : 
     544           0 :         y_r = rgb_resulted[hw_points - 1].red;
     545           0 :         y_g = rgb_resulted[hw_points - 1].green;
     546           0 :         y_b = rgb_resulted[hw_points - 1].blue;
     547             : 
     548             :         /* see comment above, m_arrPoints[1].y should be the Y value for the
     549             :          * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
     550             :          */
     551             :         y3_max = dc_fixpt_max(y_r, dc_fixpt_max(y_g, y_b));
     552             : 
     553           0 :         arr_points[1].y = y3_max;
     554             : 
     555           0 :         arr_points[1].slope = dc_fixpt_zero;
     556             : 
     557           0 :         if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
     558             :                 /* for PQ, we want to have a straight line from last HW X point,
     559             :                  * and the slope to be such that we hit 1.0 at 10000 nits.
     560             :                  */
     561           0 :                 const struct fixed31_32 end_value = dc_fixpt_from_int(125);
     562             : 
     563           0 :                 arr_points[1].slope = dc_fixpt_div(
     564             :                                 dc_fixpt_sub(dc_fixpt_one, arr_points[1].y),
     565             :                                 dc_fixpt_sub(end_value, arr_points[1].x));
     566             :         }
     567             : 
     568           0 :         regamma_params->hw_points_num = hw_points;
     569             : 
     570           0 :         k = 0;
     571           0 :         for (i = 1; i < 16; i++) {
     572           0 :                 if (seg_distr[k] != -1) {
     573           0 :                         regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
     574           0 :                         regamma_params->arr_curve_points[i].offset =
     575           0 :                                         regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
     576             :                 }
     577           0 :                 k++;
     578             :         }
     579             : 
     580           0 :         if (seg_distr[k] != -1)
     581           0 :                 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
     582             : 
     583           0 :         rgb = rgb_resulted;
     584           0 :         rgb_plus_1 = rgb_resulted + 1;
     585             : 
     586           0 :         i = 1;
     587             : 
     588           0 :         while (i != hw_points + 1) {
     589           0 :                 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
     590           0 :                         rgb_plus_1->red = rgb->red;
     591           0 :                 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
     592           0 :                         rgb_plus_1->green = rgb->green;
     593           0 :                 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
     594           0 :                         rgb_plus_1->blue = rgb->blue;
     595             : 
     596           0 :                 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
     597           0 :                 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
     598           0 :                 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
     599             : 
     600           0 :                 ++rgb_plus_1;
     601           0 :                 ++rgb;
     602           0 :                 ++i;
     603             :         }
     604             : 
     605           0 :         convert_to_custom_float(rgb_resulted, arr_points, hw_points);
     606             : 
     607           0 :         return true;
     608             : }
     609             : 
     610             : static bool
     611           0 : dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
     612             :                                 const struct dc_stream_state *stream)
     613             : {
     614           0 :         struct transform *xfm = pipe_ctx->plane_res.xfm;
     615             : 
     616           0 :         xfm->funcs->opp_power_on_regamma_lut(xfm, true);
     617           0 :         xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
     618             : 
     619           0 :         if (stream->out_transfer_func &&
     620           0 :             stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
     621           0 :             stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
     622           0 :                 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
     623           0 :         } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func,
     624             :                                                          &xfm->regamma_params)) {
     625           0 :                 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
     626           0 :                 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
     627             :         } else {
     628           0 :                 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
     629             :         }
     630             : 
     631           0 :         xfm->funcs->opp_power_on_regamma_lut(xfm, false);
     632             : 
     633           0 :         return true;
     634             : }
     635             : 
     636           0 : void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
     637             : {
     638             :         bool is_hdmi_tmds;
     639             :         bool is_dp;
     640             : 
     641           0 :         ASSERT(pipe_ctx->stream);
     642             : 
     643           0 :         if (pipe_ctx->stream_res.stream_enc == NULL)
     644             :                 return;  /* this is not root pipe */
     645             : 
     646           0 :         is_hdmi_tmds = dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal);
     647           0 :         is_dp = dc_is_dp_signal(pipe_ctx->stream->signal);
     648             : 
     649           0 :         if (!is_hdmi_tmds && !is_dp)
     650             :                 return;
     651             : 
     652           0 :         if (is_hdmi_tmds)
     653           0 :                 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
     654             :                         pipe_ctx->stream_res.stream_enc,
     655           0 :                         &pipe_ctx->stream_res.encoder_info_frame);
     656             :         else
     657           0 :                 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
     658             :                         pipe_ctx->stream_res.stream_enc,
     659           0 :                         &pipe_ctx->stream_res.encoder_info_frame);
     660             : }
     661             : 
     662           0 : void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
     663             : {
     664           0 :         enum dc_lane_count lane_count =
     665           0 :                 pipe_ctx->stream->link->cur_link_settings.lane_count;
     666           0 :         struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
     667           0 :         struct dc_link *link = pipe_ctx->stream->link;
     668           0 :         const struct dc *dc = link->dc;
     669           0 :         const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
     670             :         uint32_t active_total_with_borders;
     671           0 :         uint32_t early_control = 0;
     672           0 :         struct timing_generator *tg = pipe_ctx->stream_res.tg;
     673             : 
     674           0 :         link_hwss->setup_stream_encoder(pipe_ctx);
     675             : 
     676           0 :         dc->hwss.update_info_frame(pipe_ctx);
     677             : 
     678             :         /* enable early control to avoid corruption on DP monitor*/
     679           0 :         active_total_with_borders =
     680           0 :                         timing->h_addressable
     681           0 :                                 + timing->h_border_left
     682           0 :                                 + timing->h_border_right;
     683             : 
     684           0 :         if (lane_count != 0)
     685           0 :                 early_control = active_total_with_borders % lane_count;
     686             : 
     687           0 :         if (early_control == 0)
     688           0 :                 early_control = lane_count;
     689             : 
     690           0 :         tg->funcs->set_early_control(tg, early_control);
     691             : 
     692             :         /* enable audio only within mode set */
     693           0 :         if (pipe_ctx->stream_res.audio != NULL) {
     694           0 :                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
     695           0 :                         pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
     696             :         }
     697             : 
     698             : 
     699             : 
     700             : 
     701           0 : }
     702             : 
     703             : static enum bp_result link_transmitter_control(
     704             :                 struct dc_bios *bios,
     705             :         struct bp_transmitter_control *cntl)
     706             : {
     707             :         enum bp_result result;
     708             : 
     709           0 :         result = bios->funcs->transmitter_control(bios, cntl);
     710             : 
     711             :         return result;
     712             : }
     713             : 
     714             : /*
     715             :  * @brief
     716             :  * eDP only.
     717             :  */
     718           0 : void dce110_edp_wait_for_hpd_ready(
     719             :                 struct dc_link *link,
     720             :                 bool power_up)
     721             : {
     722           0 :         struct dc_context *ctx = link->ctx;
     723           0 :         struct graphics_object_id connector = link->link_enc->connector;
     724             :         struct gpio *hpd;
     725           0 :         struct dc_sink *sink = link->local_sink;
     726           0 :         bool edp_hpd_high = false;
     727           0 :         uint32_t time_elapsed = 0;
     728           0 :         uint32_t timeout = power_up ?
     729           0 :                 PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
     730             : 
     731           0 :         if (dal_graphics_object_id_get_connector_id(connector)
     732             :                         != CONNECTOR_ID_EDP) {
     733           0 :                 BREAK_TO_DEBUGGER();
     734           0 :                 return;
     735             :         }
     736             : 
     737           0 :         if (!power_up)
     738             :                 /*
     739             :                  * From KV, we will not HPD low after turning off VCC -
     740             :                  * instead, we will check the SW timer in power_up().
     741             :                  */
     742             :                 return;
     743             : 
     744             :         /*
     745             :          * When we power on/off the eDP panel,
     746             :          * we need to wait until SENSE bit is high/low.
     747             :          */
     748             : 
     749             :         /* obtain HPD */
     750             :         /* TODO what to do with this? */
     751           0 :         hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
     752             : 
     753           0 :         if (!hpd) {
     754           0 :                 BREAK_TO_DEBUGGER();
     755           0 :                 return;
     756             :         }
     757             : 
     758           0 :         if (sink != NULL) {
     759           0 :                 if (sink->edid_caps.panel_patch.extra_t3_ms > 0) {
     760           0 :                         int extra_t3_in_ms = sink->edid_caps.panel_patch.extra_t3_ms;
     761             : 
     762           0 :                         msleep(extra_t3_in_ms);
     763             :                 }
     764             :         }
     765             : 
     766           0 :         dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
     767             : 
     768             :         /* wait until timeout or panel detected */
     769             : 
     770             :         do {
     771           0 :                 uint32_t detected = 0;
     772             : 
     773           0 :                 dal_gpio_get_value(hpd, &detected);
     774             : 
     775           0 :                 if (!(detected ^ power_up)) {
     776           0 :                         edp_hpd_high = true;
     777           0 :                         break;
     778             :                 }
     779             : 
     780           0 :                 msleep(HPD_CHECK_INTERVAL);
     781             : 
     782           0 :                 time_elapsed += HPD_CHECK_INTERVAL;
     783           0 :         } while (time_elapsed < timeout);
     784             : 
     785           0 :         dal_gpio_close(hpd);
     786             : 
     787           0 :         dal_gpio_destroy_irq(&hpd);
     788             : 
     789           0 :         if (false == edp_hpd_high) {
     790           0 :                 DC_LOG_WARNING(
     791             :                                 "%s: wait timed out!\n", __func__);
     792             :         }
     793             : }
     794             : 
     795           0 : void dce110_edp_power_control(
     796             :                 struct dc_link *link,
     797             :                 bool power_up)
     798             : {
     799           0 :         struct dc_context *ctx = link->ctx;
     800           0 :         struct bp_transmitter_control cntl = { 0 };
     801             :         enum bp_result bp_result;
     802             :         uint8_t panel_instance;
     803             : 
     804             : 
     805           0 :         if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
     806             :                         != CONNECTOR_ID_EDP) {
     807           0 :                 BREAK_TO_DEBUGGER();
     808           0 :                 return;
     809             :         }
     810             : 
     811           0 :         if (!link->panel_cntl)
     812             :                 return;
     813           0 :         if (power_up !=
     814           0 :                 link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl)) {
     815             : 
     816           0 :                 unsigned long long current_ts = dm_get_timestamp(ctx);
     817           0 :                 unsigned long long time_since_edp_poweroff_ms =
     818           0 :                                 div64_u64(dm_get_elapse_time_in_ns(
     819             :                                                 ctx,
     820             :                                                 current_ts,
     821             :                                                 dp_trace_get_edp_poweroff_timestamp(link)), 1000000);
     822           0 :                 unsigned long long time_since_edp_poweron_ms =
     823           0 :                                 div64_u64(dm_get_elapse_time_in_ns(
     824             :                                                 ctx,
     825             :                                                 current_ts,
     826             :                                                 dp_trace_get_edp_poweron_timestamp(link)), 1000000);
     827           0 :                 DC_LOG_HW_RESUME_S3(
     828             :                                 "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu",
     829             :                                 __func__,
     830             :                                 power_up,
     831             :                                 current_ts,
     832             :                                 dp_trace_get_edp_poweroff_timestamp(link),
     833             :                                 dp_trace_get_edp_poweron_timestamp(link),
     834             :                                 time_since_edp_poweroff_ms,
     835             :                                 time_since_edp_poweron_ms);
     836             : 
     837             :                 /* Send VBIOS command to prompt eDP panel power */
     838           0 :                 if (power_up) {
     839             :                         /* edp requires a min of 500ms from LCDVDD off to on */
     840           0 :                         unsigned long long remaining_min_edp_poweroff_time_ms = 500;
     841             : 
     842             :                         /* add time defined by a patch, if any (usually patch extra_t12_ms is 0) */
     843           0 :                         if (link->local_sink != NULL)
     844           0 :                                 remaining_min_edp_poweroff_time_ms +=
     845           0 :                                         link->local_sink->edid_caps.panel_patch.extra_t12_ms;
     846             : 
     847             :                         /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */
     848           0 :                         if (dp_trace_get_edp_poweroff_timestamp(link) != 0) {
     849           0 :                                 if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms)
     850           0 :                                         remaining_min_edp_poweroff_time_ms =
     851             :                                                 remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms;
     852             :                                 else
     853             :                                         remaining_min_edp_poweroff_time_ms = 0;
     854             :                         }
     855             : 
     856           0 :                         if (remaining_min_edp_poweroff_time_ms) {
     857           0 :                                 DC_LOG_HW_RESUME_S3(
     858             :                                                 "%s: remaining_min_edp_poweroff_time_ms=%llu: begin wait.\n",
     859             :                                                 __func__, remaining_min_edp_poweroff_time_ms);
     860           0 :                                 msleep(remaining_min_edp_poweroff_time_ms);
     861           0 :                                 DC_LOG_HW_RESUME_S3(
     862             :                                                 "%s: remaining_min_edp_poweroff_time_ms=%llu: end wait.\n",
     863             :                                                 __func__, remaining_min_edp_poweroff_time_ms);
     864           0 :                                 dm_output_to_console("%s: wait %lld ms to power on eDP.\n",
     865             :                                                 __func__, remaining_min_edp_poweroff_time_ms);
     866             :                         } else {
     867           0 :                                 DC_LOG_HW_RESUME_S3(
     868             :                                                 "%s: remaining_min_edp_poweroff_time_ms=%llu: no wait required.\n",
     869             :                                                 __func__, remaining_min_edp_poweroff_time_ms);
     870             :                         }
     871             :                 }
     872             : 
     873           0 :                 DC_LOG_HW_RESUME_S3(
     874             :                                 "%s: BEGIN: Panel Power action: %s\n",
     875             :                                 __func__, (power_up ? "On":"Off"));
     876             : 
     877           0 :                 cntl.action = power_up ?
     878           0 :                         TRANSMITTER_CONTROL_POWER_ON :
     879             :                         TRANSMITTER_CONTROL_POWER_OFF;
     880           0 :                 cntl.transmitter = link->link_enc->transmitter;
     881           0 :                 cntl.connector_obj_id = link->link_enc->connector;
     882           0 :                 cntl.coherent = false;
     883           0 :                 cntl.lanes_number = LANE_COUNT_FOUR;
     884           0 :                 cntl.hpd_sel = link->link_enc->hpd_source;
     885           0 :                 panel_instance = link->panel_cntl->inst;
     886             : 
     887           0 :                 if (ctx->dc->ctx->dmub_srv &&
     888           0 :                                 ctx->dc->debug.dmub_command_table) {
     889           0 :                         if (cntl.action == TRANSMITTER_CONTROL_POWER_ON)
     890           0 :                                 bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
     891             :                                                 LVTMA_CONTROL_POWER_ON,
     892             :                                                 panel_instance);
     893             :                         else
     894           0 :                                 bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
     895             :                                                 LVTMA_CONTROL_POWER_OFF,
     896             :                                                 panel_instance);
     897             :                 }
     898             : 
     899           0 :                 bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
     900             : 
     901           0 :                 DC_LOG_HW_RESUME_S3(
     902             :                                 "%s: END: Panel Power action: %s bp_result=%u\n",
     903             :                                 __func__, (power_up ? "On":"Off"),
     904             :                                 bp_result);
     905             : 
     906           0 :                 dp_trace_set_edp_power_timestamp(link, power_up);
     907             : 
     908           0 :                 DC_LOG_HW_RESUME_S3(
     909             :                                 "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n",
     910             :                                 __func__,
     911             :                                 dp_trace_get_edp_poweroff_timestamp(link),
     912             :                                 dp_trace_get_edp_poweron_timestamp(link));
     913             : 
     914           0 :                 if (bp_result != BP_RESULT_OK)
     915           0 :                         DC_LOG_ERROR(
     916             :                                         "%s: Panel Power bp_result: %d\n",
     917             :                                         __func__, bp_result);
     918             :         } else {
     919           0 :                 DC_LOG_HW_RESUME_S3(
     920             :                                 "%s: Skipping Panel Power action: %s\n",
     921             :                                 __func__, (power_up ? "On":"Off"));
     922             :         }
     923             : }
     924             : 
     925           0 : void dce110_edp_wait_for_T12(
     926             :                 struct dc_link *link)
     927             : {
     928           0 :         struct dc_context *ctx = link->ctx;
     929             : 
     930           0 :         if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
     931             :                         != CONNECTOR_ID_EDP) {
     932           0 :                 BREAK_TO_DEBUGGER();
     933           0 :                 return;
     934             :         }
     935             : 
     936           0 :         if (!link->panel_cntl)
     937             :                 return;
     938             : 
     939           0 :         if (!link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl) &&
     940           0 :                         dp_trace_get_edp_poweroff_timestamp(link) != 0) {
     941           0 :                 unsigned int t12_duration = 500; // Default T12 as per spec
     942           0 :                 unsigned long long current_ts = dm_get_timestamp(ctx);
     943           0 :                 unsigned long long time_since_edp_poweroff_ms =
     944           0 :                                 div64_u64(dm_get_elapse_time_in_ns(
     945             :                                                 ctx,
     946             :                                                 current_ts,
     947             :                                                 dp_trace_get_edp_poweroff_timestamp(link)), 1000000);
     948             : 
     949           0 :                 t12_duration += link->local_sink->edid_caps.panel_patch.extra_t12_ms; // Add extra T12
     950             : 
     951           0 :                 if (time_since_edp_poweroff_ms < t12_duration)
     952           0 :                         msleep(t12_duration - time_since_edp_poweroff_ms);
     953             :         }
     954             : }
     955             : 
     956             : /*todo: cloned in stream enc, fix*/
     957             : /*
     958             :  * @brief
     959             :  * eDP only. Control the backlight of the eDP panel
     960             :  */
     961           0 : void dce110_edp_backlight_control(
     962             :                 struct dc_link *link,
     963             :                 bool enable)
     964             : {
     965           0 :         struct dc_context *ctx = link->ctx;
     966           0 :         struct bp_transmitter_control cntl = { 0 };
     967             :         uint8_t panel_instance;
     968             : 
     969           0 :         if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
     970             :                 != CONNECTOR_ID_EDP) {
     971           0 :                 BREAK_TO_DEBUGGER();
     972           0 :                 return;
     973             :         }
     974             : 
     975           0 :         if (link->panel_cntl) {
     976           0 :                 bool is_backlight_on = link->panel_cntl->funcs->is_panel_backlight_on(link->panel_cntl);
     977             : 
     978           0 :                 if ((enable && is_backlight_on) || (!enable && !is_backlight_on)) {
     979           0 :                         DC_LOG_HW_RESUME_S3(
     980             :                                 "%s: panel already powered up/off. Do nothing.\n",
     981             :                                 __func__);
     982           0 :                         return;
     983             :                 }
     984             :         }
     985             : 
     986             :         /* Send VBIOS command to control eDP panel backlight */
     987             : 
     988           0 :         DC_LOG_HW_RESUME_S3(
     989             :                         "%s: backlight action: %s\n",
     990             :                         __func__, (enable ? "On":"Off"));
     991             : 
     992           0 :         cntl.action = enable ?
     993           0 :                 TRANSMITTER_CONTROL_BACKLIGHT_ON :
     994             :                 TRANSMITTER_CONTROL_BACKLIGHT_OFF;
     995             : 
     996             :         /*cntl.engine_id = ctx->engine;*/
     997           0 :         cntl.transmitter = link->link_enc->transmitter;
     998           0 :         cntl.connector_obj_id = link->link_enc->connector;
     999             :         /*todo: unhardcode*/
    1000           0 :         cntl.lanes_number = LANE_COUNT_FOUR;
    1001           0 :         cntl.hpd_sel = link->link_enc->hpd_source;
    1002           0 :         cntl.signal = SIGNAL_TYPE_EDP;
    1003             : 
    1004             :         /* For eDP, the following delays might need to be considered
    1005             :          * after link training completed:
    1006             :          * idle period - min. accounts for required BS-Idle pattern,
    1007             :          * max. allows for source frame synchronization);
    1008             :          * 50 msec max. delay from valid video data from source
    1009             :          * to video on dislpay or backlight enable.
    1010             :          *
    1011             :          * Disable the delay for now.
    1012             :          * Enable it in the future if necessary.
    1013             :          */
    1014             :         /* dc_service_sleep_in_milliseconds(50); */
    1015             :                 /*edp 1.2*/
    1016           0 :         panel_instance = link->panel_cntl->inst;
    1017             : 
    1018           0 :         if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) {
    1019           0 :                 if (!link->dc->config.edp_no_power_sequencing)
    1020             :                 /*
    1021             :                  * Sometimes, DP receiver chip power-controlled externally by an
    1022             :                  * Embedded Controller could be treated and used as eDP,
    1023             :                  * if it drives mobile display. In this case,
    1024             :                  * we shouldn't be doing power-sequencing, hence we can skip
    1025             :                  * waiting for T7-ready.
    1026             :                  */
    1027           0 :                         edp_receiver_ready_T7(link);
    1028             :                 else
    1029           0 :                         DC_LOG_DC("edp_receiver_ready_T7 skipped\n");
    1030             :         }
    1031             : 
    1032           0 :         if (ctx->dc->ctx->dmub_srv &&
    1033           0 :                         ctx->dc->debug.dmub_command_table) {
    1034           0 :                 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
    1035           0 :                         ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
    1036             :                                         LVTMA_CONTROL_LCD_BLON,
    1037             :                                         panel_instance);
    1038             :                 else
    1039           0 :                         ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios,
    1040             :                                         LVTMA_CONTROL_LCD_BLOFF,
    1041             :                                         panel_instance);
    1042             :         }
    1043             : 
    1044           0 :         link_transmitter_control(ctx->dc_bios, &cntl);
    1045             : 
    1046           0 :         if (enable && link->dpcd_sink_ext_caps.bits.oled)
    1047           0 :                 msleep(OLED_POST_T7_DELAY);
    1048             : 
    1049           0 :         if (link->dpcd_sink_ext_caps.bits.oled ||
    1050           0 :                 link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
    1051             :                 link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1)
    1052           0 :                 dc_link_backlight_enable_aux(link, enable);
    1053             : 
    1054             :         /*edp 1.2*/
    1055           0 :         if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) {
    1056           0 :                 if (!link->dc->config.edp_no_power_sequencing)
    1057             :                 /*
    1058             :                  * Sometimes, DP receiver chip power-controlled externally by an
    1059             :                  * Embedded Controller could be treated and used as eDP,
    1060             :                  * if it drives mobile display. In this case,
    1061             :                  * we shouldn't be doing power-sequencing, hence we can skip
    1062             :                  * waiting for T9-ready.
    1063             :                  */
    1064           0 :                         edp_add_delay_for_T9(link);
    1065             :                 else
    1066           0 :                         DC_LOG_DC("edp_receiver_ready_T9 skipped\n");
    1067             :         }
    1068             : 
    1069           0 :         if (!enable && link->dpcd_sink_ext_caps.bits.oled)
    1070           0 :                 msleep(OLED_PRE_T11_DELAY);
    1071             : }
    1072             : 
    1073           0 : void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
    1074             : {
    1075             :         /* notify audio driver for audio modes of monitor */
    1076             :         struct dc *dc;
    1077             :         struct clk_mgr *clk_mgr;
    1078           0 :         unsigned int i, num_audio = 1;
    1079             : 
    1080           0 :         if (!pipe_ctx->stream)
    1081             :                 return;
    1082             : 
    1083           0 :         dc = pipe_ctx->stream->ctx->dc;
    1084           0 :         clk_mgr = dc->clk_mgr;
    1085             : 
    1086           0 :         if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
    1087             :                 return;
    1088             : 
    1089           0 :         if (pipe_ctx->stream_res.audio) {
    1090           0 :                 for (i = 0; i < MAX_PIPES; i++) {
    1091             :                         /*current_state not updated yet*/
    1092           0 :                         if (dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL)
    1093           0 :                                 num_audio++;
    1094             :                 }
    1095             : 
    1096           0 :                 pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
    1097             : 
    1098           0 :                 if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa)
    1099             :                         /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
    1100           0 :                         clk_mgr->funcs->enable_pme_wa(clk_mgr);
    1101             :                 /* un-mute audio */
    1102             :                 /* TODO: audio should be per stream rather than per link */
    1103           0 :                 if (is_dp_128b_132b_signal(pipe_ctx))
    1104           0 :                         pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
    1105             :                                         pipe_ctx->stream_res.hpo_dp_stream_enc, false);
    1106             :                 else
    1107           0 :                         pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
    1108             :                                         pipe_ctx->stream_res.stream_enc, false);
    1109           0 :                 if (pipe_ctx->stream_res.audio)
    1110           0 :                         pipe_ctx->stream_res.audio->enabled = true;
    1111             :         }
    1112             : 
    1113           0 :         if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1114           0 :                 dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM);
    1115             : }
    1116             : 
    1117           0 : void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
    1118             : {
    1119             :         struct dc *dc;
    1120             :         struct clk_mgr *clk_mgr;
    1121             : 
    1122           0 :         if (!pipe_ctx || !pipe_ctx->stream)
    1123             :                 return;
    1124             : 
    1125           0 :         dc = pipe_ctx->stream->ctx->dc;
    1126           0 :         clk_mgr = dc->clk_mgr;
    1127             : 
    1128           0 :         if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
    1129             :                 return;
    1130             : 
    1131           0 :         if (is_dp_128b_132b_signal(pipe_ctx))
    1132           0 :                 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
    1133             :                                 pipe_ctx->stream_res.hpo_dp_stream_enc, true);
    1134             :         else
    1135           0 :                 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
    1136             :                                 pipe_ctx->stream_res.stream_enc, true);
    1137           0 :         if (pipe_ctx->stream_res.audio) {
    1138           0 :                 pipe_ctx->stream_res.audio->enabled = false;
    1139             : 
    1140           0 :                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1141           0 :                         if (is_dp_128b_132b_signal(pipe_ctx))
    1142           0 :                                 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable(
    1143             :                                                 pipe_ctx->stream_res.hpo_dp_stream_enc);
    1144             :                         else
    1145           0 :                                 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
    1146             :                                                 pipe_ctx->stream_res.stream_enc);
    1147             :                 else
    1148           0 :                         pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
    1149             :                                         pipe_ctx->stream_res.stream_enc);
    1150             : 
    1151           0 :                 if (clk_mgr->funcs->enable_pme_wa)
    1152             :                         /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
    1153           0 :                         clk_mgr->funcs->enable_pme_wa(clk_mgr);
    1154             : 
    1155             :                 /* TODO: notify audio driver for if audio modes list changed
    1156             :                  * add audio mode list change flag */
    1157             :                 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
    1158             :                  * stream->stream_engine_id);
    1159             :                  */
    1160             :         }
    1161             : 
    1162           0 :         if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1163           0 :                 dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM);
    1164             : }
    1165             : 
    1166           0 : void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
    1167             : {
    1168           0 :         struct dc_stream_state *stream = pipe_ctx->stream;
    1169           0 :         struct dc_link *link = stream->link;
    1170           0 :         struct dc *dc = pipe_ctx->stream->ctx->dc;
    1171           0 :         const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
    1172             : 
    1173           0 :         if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) {
    1174           0 :                 pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
    1175             :                         pipe_ctx->stream_res.stream_enc);
    1176           0 :                 pipe_ctx->stream_res.stream_enc->funcs->hdmi_reset_stream_attribute(
    1177             :                         pipe_ctx->stream_res.stream_enc);
    1178             :         }
    1179             : 
    1180           0 :         if (is_dp_128b_132b_signal(pipe_ctx)) {
    1181           0 :                 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets(
    1182             :                                         pipe_ctx->stream_res.hpo_dp_stream_enc);
    1183           0 :         } else if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1184           0 :                 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
    1185             :                         pipe_ctx->stream_res.stream_enc);
    1186             : 
    1187           0 :         dc->hwss.disable_audio_stream(pipe_ctx);
    1188             : 
    1189           0 :         link_hwss->reset_stream_encoder(pipe_ctx);
    1190             : 
    1191           0 :         if (is_dp_128b_132b_signal(pipe_ctx)) {
    1192             :                 /* TODO: This looks like a bug to me as we are disabling HPO IO when
    1193             :                  * we are just disabling a single HPO stream. Shouldn't we disable HPO
    1194             :                  * HW control only when HPOs for all streams are disabled?
    1195             :                  */
    1196           0 :                 if (pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control)
    1197           0 :                         pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control(
    1198             :                                         pipe_ctx->stream->ctx->dc->hwseq, false);
    1199             :         }
    1200           0 : }
    1201             : 
    1202           0 : void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
    1203             :                 struct dc_link_settings *link_settings)
    1204             : {
    1205           0 :         struct encoder_unblank_param params = { { 0 } };
    1206           0 :         struct dc_stream_state *stream = pipe_ctx->stream;
    1207           0 :         struct dc_link *link = stream->link;
    1208           0 :         struct dce_hwseq *hws = link->dc->hwseq;
    1209             : 
    1210             :         /* only 3 items below are used by unblank */
    1211           0 :         params.timing = pipe_ctx->stream->timing;
    1212           0 :         params.link_settings.link_rate = link_settings->link_rate;
    1213             : 
    1214           0 :         if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1215           0 :                 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, &params);
    1216             : 
    1217           0 :         if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
    1218           0 :                 hws->funcs.edp_backlight_control(link, true);
    1219             :         }
    1220           0 : }
    1221             : 
    1222           0 : void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
    1223             : {
    1224           0 :         struct dc_stream_state *stream = pipe_ctx->stream;
    1225           0 :         struct dc_link *link = stream->link;
    1226           0 :         struct dce_hwseq *hws = link->dc->hwseq;
    1227             : 
    1228           0 :         if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
    1229           0 :                 hws->funcs.edp_backlight_control(link, false);
    1230           0 :                 link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
    1231             :         }
    1232             : 
    1233           0 :         if (is_dp_128b_132b_signal(pipe_ctx)) {
    1234             :                 /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */
    1235           0 :                 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_blank(
    1236             :                                 pipe_ctx->stream_res.hpo_dp_stream_enc);
    1237           0 :         } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
    1238           0 :                 pipe_ctx->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
    1239             : 
    1240           0 :                 if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) {
    1241             :                         /*
    1242             :                          * After output is idle pattern some sinks need time to recognize the stream
    1243             :                          * has changed or they enter protection state and hang.
    1244             :                          */
    1245           0 :                         msleep(60);
    1246           0 :                 } else if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
    1247           0 :                         if (!link->dc->config.edp_no_power_sequencing) {
    1248             :                                 /*
    1249             :                                  * Sometimes, DP receiver chip power-controlled externally by an
    1250             :                                  * Embedded Controller could be treated and used as eDP,
    1251             :                                  * if it drives mobile display. In this case,
    1252             :                                  * we shouldn't be doing power-sequencing, hence we can skip
    1253             :                                  * waiting for T9-ready.
    1254             :                                  */
    1255           0 :                                 edp_receiver_ready_T9(link);
    1256             :                         }
    1257             :                 }
    1258             :         }
    1259             : 
    1260           0 : }
    1261             : 
    1262             : 
    1263           0 : void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
    1264             : {
    1265           0 :         if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL)
    1266           0 :                 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable);
    1267           0 : }
    1268             : 
    1269             : static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
    1270             : {
    1271             :         switch (crtc_id) {
    1272             :         case CONTROLLER_ID_D0:
    1273             :                 return DTO_SOURCE_ID0;
    1274             :         case CONTROLLER_ID_D1:
    1275             :                 return DTO_SOURCE_ID1;
    1276             :         case CONTROLLER_ID_D2:
    1277             :                 return DTO_SOURCE_ID2;
    1278             :         case CONTROLLER_ID_D3:
    1279             :                 return DTO_SOURCE_ID3;
    1280             :         case CONTROLLER_ID_D4:
    1281             :                 return DTO_SOURCE_ID4;
    1282             :         case CONTROLLER_ID_D5:
    1283             :                 return DTO_SOURCE_ID5;
    1284             :         default:
    1285             :                 return DTO_SOURCE_UNKNOWN;
    1286             :         }
    1287             : }
    1288             : 
    1289           0 : static void build_audio_output(
    1290             :         struct dc_state *state,
    1291             :         const struct pipe_ctx *pipe_ctx,
    1292             :         struct audio_output *audio_output)
    1293             : {
    1294           0 :         const struct dc_stream_state *stream = pipe_ctx->stream;
    1295           0 :         audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id;
    1296             : 
    1297           0 :         audio_output->signal = pipe_ctx->stream->signal;
    1298             : 
    1299             :         /* audio_crtc_info  */
    1300             : 
    1301           0 :         audio_output->crtc_info.h_total =
    1302           0 :                 stream->timing.h_total;
    1303             : 
    1304             :         /*
    1305             :          * Audio packets are sent during actual CRTC blank physical signal, we
    1306             :          * need to specify actual active signal portion
    1307             :          */
    1308           0 :         audio_output->crtc_info.h_active =
    1309           0 :                         stream->timing.h_addressable
    1310           0 :                         + stream->timing.h_border_left
    1311           0 :                         + stream->timing.h_border_right;
    1312             : 
    1313           0 :         audio_output->crtc_info.v_active =
    1314           0 :                         stream->timing.v_addressable
    1315           0 :                         + stream->timing.v_border_top
    1316           0 :                         + stream->timing.v_border_bottom;
    1317             : 
    1318           0 :         audio_output->crtc_info.pixel_repetition = 1;
    1319             : 
    1320           0 :         audio_output->crtc_info.interlaced =
    1321           0 :                         stream->timing.flags.INTERLACE;
    1322             : 
    1323           0 :         audio_output->crtc_info.refresh_rate =
    1324           0 :                 (stream->timing.pix_clk_100hz*100)/
    1325           0 :                 (stream->timing.h_total*stream->timing.v_total);
    1326             : 
    1327           0 :         audio_output->crtc_info.color_depth =
    1328           0 :                 stream->timing.display_color_depth;
    1329             : 
    1330           0 :         audio_output->crtc_info.requested_pixel_clock_100Hz =
    1331           0 :                         pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
    1332             : 
    1333           0 :         audio_output->crtc_info.calculated_pixel_clock_100Hz =
    1334           0 :                         pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz;
    1335             : 
    1336             : /*for HDMI, audio ACR is with deep color ratio factor*/
    1337           0 :         if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) &&
    1338             :                 audio_output->crtc_info.requested_pixel_clock_100Hz ==
    1339           0 :                                 (stream->timing.pix_clk_100hz)) {
    1340           0 :                 if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
    1341           0 :                         audio_output->crtc_info.requested_pixel_clock_100Hz =
    1342           0 :                                         audio_output->crtc_info.requested_pixel_clock_100Hz/2;
    1343           0 :                         audio_output->crtc_info.calculated_pixel_clock_100Hz =
    1344           0 :                                         pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz/2;
    1345             : 
    1346             :                 }
    1347             :         }
    1348             : 
    1349           0 :         if (state->clk_mgr &&
    1350           0 :                 (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
    1351             :                         pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)) {
    1352           0 :                 audio_output->pll_info.dp_dto_source_clock_in_khz =
    1353           0 :                                 state->clk_mgr->funcs->get_dp_ref_clk_frequency(
    1354             :                                                 state->clk_mgr);
    1355             :         }
    1356             : 
    1357           0 :         audio_output->pll_info.feed_back_divider =
    1358           0 :                         pipe_ctx->pll_settings.feedback_divider;
    1359             : 
    1360           0 :         audio_output->pll_info.dto_source =
    1361           0 :                 translate_to_dto_source(
    1362           0 :                         pipe_ctx->stream_res.tg->inst + 1);
    1363             : 
    1364             :         /* TODO hard code to enable for now. Need get from stream */
    1365           0 :         audio_output->pll_info.ss_enabled = true;
    1366             : 
    1367           0 :         audio_output->pll_info.ss_percentage =
    1368           0 :                         pipe_ctx->pll_settings.ss_percentage;
    1369           0 : }
    1370             : 
    1371           0 : static void program_scaler(const struct dc *dc,
    1372             :                 const struct pipe_ctx *pipe_ctx)
    1373             : {
    1374           0 :         struct tg_color color = {0};
    1375             : 
    1376             :         /* TOFPGA */
    1377           0 :         if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
    1378           0 :                 return;
    1379             : 
    1380           0 :         if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
    1381           0 :                 get_surface_visual_confirm_color(pipe_ctx, &color);
    1382             :         else
    1383           0 :                 color_space_to_black_color(dc,
    1384           0 :                                 pipe_ctx->stream->output_color_space,
    1385             :                                 &color);
    1386             : 
    1387           0 :         pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
    1388             :                 pipe_ctx->plane_res.xfm,
    1389             :                 pipe_ctx->plane_res.scl_data.lb_params.depth,
    1390           0 :                 &pipe_ctx->stream->bit_depth_params);
    1391             : 
    1392           0 :         if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
    1393             :                 /*
    1394             :                  * The way 420 is packed, 2 channels carry Y component, 1 channel
    1395             :                  * alternate between Cb and Cr, so both channels need the pixel
    1396             :                  * value for Y
    1397             :                  */
    1398           0 :                 if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
    1399           0 :                         color.color_r_cr = color.color_g_y;
    1400             : 
    1401           0 :                 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
    1402             :                                 pipe_ctx->stream_res.tg,
    1403             :                                 &color);
    1404             :         }
    1405             : 
    1406           0 :         pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
    1407             :                 &pipe_ctx->plane_res.scl_data);
    1408             : }
    1409             : 
    1410           0 : static enum dc_status dce110_enable_stream_timing(
    1411             :                 struct pipe_ctx *pipe_ctx,
    1412             :                 struct dc_state *context,
    1413             :                 struct dc *dc)
    1414             : {
    1415           0 :         struct dc_stream_state *stream = pipe_ctx->stream;
    1416           0 :         struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
    1417           0 :                         pipe_ctx[pipe_ctx->pipe_idx];
    1418           0 :         struct tg_color black_color = {0};
    1419             : 
    1420           0 :         if (!pipe_ctx_old->stream) {
    1421             : 
    1422             :                 /* program blank color */
    1423           0 :                 color_space_to_black_color(dc,
    1424             :                                 stream->output_color_space, &black_color);
    1425           0 :                 pipe_ctx->stream_res.tg->funcs->set_blank_color(
    1426             :                                 pipe_ctx->stream_res.tg,
    1427             :                                 &black_color);
    1428             : 
    1429             :                 /*
    1430             :                  * Must blank CRTC after disabling power gating and before any
    1431             :                  * programming, otherwise CRTC will be hung in bad state
    1432             :                  */
    1433           0 :                 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
    1434             : 
    1435           0 :                 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
    1436             :                                 pipe_ctx->clock_source,
    1437             :                                 &pipe_ctx->stream_res.pix_clk_params,
    1438           0 :                                 dp_get_link_encoding_format(&pipe_ctx->link_config.dp_link_settings),
    1439             :                                 &pipe_ctx->pll_settings)) {
    1440           0 :                         BREAK_TO_DEBUGGER();
    1441           0 :                         return DC_ERROR_UNEXPECTED;
    1442             :                 }
    1443             : 
    1444           0 :                 pipe_ctx->stream_res.tg->funcs->program_timing(
    1445             :                                 pipe_ctx->stream_res.tg,
    1446           0 :                                 &stream->timing,
    1447             :                                 0,
    1448             :                                 0,
    1449             :                                 0,
    1450             :                                 0,
    1451           0 :                                 pipe_ctx->stream->signal,
    1452             :                                 true);
    1453             :         }
    1454             : 
    1455           0 :         if (!pipe_ctx_old->stream) {
    1456           0 :                 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(
    1457             :                                 pipe_ctx->stream_res.tg)) {
    1458           0 :                         BREAK_TO_DEBUGGER();
    1459           0 :                         return DC_ERROR_UNEXPECTED;
    1460             :                 }
    1461             :         }
    1462             : 
    1463             :         return DC_OK;
    1464             : }
    1465             : 
    1466           0 : static enum dc_status apply_single_controller_ctx_to_hw(
    1467             :                 struct pipe_ctx *pipe_ctx,
    1468             :                 struct dc_state *context,
    1469             :                 struct dc *dc)
    1470             : {
    1471           0 :         struct dc_stream_state *stream = pipe_ctx->stream;
    1472           0 :         struct dc_link *link = stream->link;
    1473           0 :         struct drr_params params = {0};
    1474           0 :         unsigned int event_triggers = 0;
    1475           0 :         struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
    1476           0 :         struct dce_hwseq *hws = dc->hwseq;
    1477             : 
    1478           0 :         if (hws->funcs.disable_stream_gating) {
    1479           0 :                 hws->funcs.disable_stream_gating(dc, pipe_ctx);
    1480             :         }
    1481             : 
    1482           0 :         if (pipe_ctx->stream_res.audio != NULL) {
    1483             :                 struct audio_output audio_output;
    1484             : 
    1485           0 :                 build_audio_output(context, pipe_ctx, &audio_output);
    1486             : 
    1487           0 :                 if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1488           0 :                         if (is_dp_128b_132b_signal(pipe_ctx))
    1489           0 :                                 pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
    1490             :                                                 pipe_ctx->stream_res.hpo_dp_stream_enc,
    1491           0 :                                                 pipe_ctx->stream_res.audio->inst,
    1492           0 :                                                 &pipe_ctx->stream->audio_info);
    1493             :                         else
    1494           0 :                                 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
    1495             :                                                 pipe_ctx->stream_res.stream_enc,
    1496           0 :                                                 pipe_ctx->stream_res.audio->inst,
    1497           0 :                                                 &pipe_ctx->stream->audio_info);
    1498             :                 else
    1499           0 :                         pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
    1500             :                                         pipe_ctx->stream_res.stream_enc,
    1501           0 :                                         pipe_ctx->stream_res.audio->inst,
    1502             :                                         &pipe_ctx->stream->audio_info,
    1503             :                                         &audio_output.crtc_info);
    1504             : 
    1505           0 :                 pipe_ctx->stream_res.audio->funcs->az_configure(
    1506             :                                 pipe_ctx->stream_res.audio,
    1507             :                                 pipe_ctx->stream->signal,
    1508             :                                 &audio_output.crtc_info,
    1509           0 :                                 &pipe_ctx->stream->audio_info);
    1510             :         }
    1511             : 
    1512             :         /* make sure no pipes syncd to the pipe being enabled */
    1513           0 :         if (!pipe_ctx->stream->apply_seamless_boot_optimization && dc->config.use_pipe_ctx_sync_logic)
    1514           0 :                 check_syncd_pipes_for_disabled_master_pipe(dc, context, pipe_ctx->pipe_idx);
    1515             : 
    1516           0 :         pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
    1517             :                 pipe_ctx->stream_res.opp,
    1518             :                 &stream->bit_depth_params,
    1519             :                 &stream->clamping);
    1520             : 
    1521           0 :         pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
    1522             :                         pipe_ctx->stream_res.opp,
    1523             :                         COLOR_SPACE_YCBCR601,
    1524             :                         stream->timing.display_color_depth,
    1525             :                         stream->signal);
    1526             : 
    1527           0 :         while (odm_pipe) {
    1528           0 :                 odm_pipe->stream_res.opp->funcs->opp_set_dyn_expansion(
    1529             :                                 odm_pipe->stream_res.opp,
    1530             :                                 COLOR_SPACE_YCBCR601,
    1531             :                                 stream->timing.display_color_depth,
    1532             :                                 stream->signal);
    1533             : 
    1534           0 :                 odm_pipe->stream_res.opp->funcs->opp_program_fmt(
    1535             :                                 odm_pipe->stream_res.opp,
    1536             :                                 &stream->bit_depth_params,
    1537             :                                 &stream->clamping);
    1538           0 :                 odm_pipe = odm_pipe->next_odm_pipe;
    1539             :         }
    1540             : 
    1541             :         /* DCN3.1 FPGA Workaround
    1542             :          * Need to enable HPO DP Stream Encoder before setting OTG master enable.
    1543             :          * To do so, move calling function enable_stream_timing to only be done AFTER calling
    1544             :          * function core_link_enable_stream
    1545             :          */
    1546           0 :         if (!(hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx)))
    1547             :                 /*  */
    1548             :                 /* Do not touch stream timing on seamless boot optimization. */
    1549           0 :                 if (!pipe_ctx->stream->apply_seamless_boot_optimization)
    1550           0 :                         hws->funcs.enable_stream_timing(pipe_ctx, context, dc);
    1551             : 
    1552           0 :         if (hws->funcs.setup_vupdate_interrupt)
    1553           0 :                 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
    1554             : 
    1555           0 :         params.vertical_total_min = stream->adjust.v_total_min;
    1556           0 :         params.vertical_total_max = stream->adjust.v_total_max;
    1557           0 :         if (pipe_ctx->stream_res.tg->funcs->set_drr)
    1558           0 :                 pipe_ctx->stream_res.tg->funcs->set_drr(
    1559             :                         pipe_ctx->stream_res.tg, &params);
    1560             : 
    1561             :         // DRR should set trigger event to monitor surface update event
    1562           0 :         if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
    1563           0 :                 event_triggers = 0x80;
    1564             :         /* Event triggers and num frames initialized for DRR, but can be
    1565             :          * later updated for PSR use. Note DRR trigger events are generated
    1566             :          * regardless of whether num frames met.
    1567             :          */
    1568           0 :         if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
    1569           0 :                 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
    1570             :                                 pipe_ctx->stream_res.tg, event_triggers, 2);
    1571             : 
    1572           0 :         if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
    1573           0 :                 pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
    1574             :                         pipe_ctx->stream_res.stream_enc,
    1575           0 :                         pipe_ctx->stream_res.tg->inst);
    1576             : 
    1577           0 :         if (dc_is_dp_signal(pipe_ctx->stream->signal))
    1578           0 :                 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG);
    1579             : 
    1580             :         /* Have to setup DSC before DIG FE and BE are connected (which happens before the
    1581             :          * link training). This is to make sure the bandwidth sent to DIG BE won't be
    1582             :          * bigger than what the link and/or DIG BE can handle. VBID[6]/CompressedStream_flag
    1583             :          * will be automatically set at a later time when the video is enabled
    1584             :          * (DP_VID_STREAM_EN = 1).
    1585             :          */
    1586           0 :         if (pipe_ctx->stream->timing.flags.DSC) {
    1587           0 :                 if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
    1588           0 :                         dc_is_virtual_signal(pipe_ctx->stream->signal))
    1589           0 :                         dp_set_dsc_enable(pipe_ctx, true);
    1590             : 
    1591             :         }
    1592             : 
    1593           0 :         if (!stream->dpms_off) {
    1594           0 :                 if (dc->hwss.update_phy_state)
    1595           0 :                         dc->hwss.update_phy_state(context, pipe_ctx, TX_ON_SYMCLK_ON);
    1596             :                 else
    1597           0 :                         core_link_enable_stream(context, pipe_ctx);
    1598             :         }
    1599             : 
    1600             :         /* DCN3.1 FPGA Workaround
    1601             :          * Need to enable HPO DP Stream Encoder before setting OTG master enable.
    1602             :          * To do so, move calling function enable_stream_timing to only be done AFTER calling
    1603             :          * function core_link_enable_stream
    1604             :          */
    1605           0 :         if (hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx)) {
    1606           0 :                 if (!pipe_ctx->stream->apply_seamless_boot_optimization)
    1607           0 :                         hws->funcs.enable_stream_timing(pipe_ctx, context, dc);
    1608             :         }
    1609             : 
    1610           0 :         pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != NULL;
    1611             : 
    1612           0 :         pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false;
    1613             : 
    1614           0 :         return DC_OK;
    1615             : }
    1616             : 
    1617             : /******************************************************************************/
    1618             : 
    1619           0 : static void power_down_encoders(struct dc *dc)
    1620             : {
    1621             :         int i;
    1622             : 
    1623           0 :         for (i = 0; i < dc->link_count; i++) {
    1624           0 :                 enum signal_type signal = dc->links[i]->connector_signal;
    1625             : 
    1626           0 :                 dc_link_blank_dp_stream(dc->links[i], false);
    1627             : 
    1628           0 :                 if (signal != SIGNAL_TYPE_EDP)
    1629           0 :                         signal = SIGNAL_TYPE_NONE;
    1630             : 
    1631           0 :                 if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY)
    1632           0 :                         dc->links[i]->link_enc->funcs->disable_output(
    1633             :                                         dc->links[i]->link_enc, signal);
    1634             : 
    1635           0 :                 dc->links[i]->link_status.link_active = false;
    1636           0 :                 memset(&dc->links[i]->cur_link_settings, 0,
    1637             :                                 sizeof(dc->links[i]->cur_link_settings));
    1638             :         }
    1639           0 : }
    1640             : 
    1641             : static void power_down_controllers(struct dc *dc)
    1642             : {
    1643             :         int i;
    1644             : 
    1645           0 :         for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
    1646           0 :                 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
    1647             :                                 dc->res_pool->timing_generators[i]);
    1648             :         }
    1649             : }
    1650             : 
    1651           0 : static void power_down_clock_sources(struct dc *dc)
    1652             : {
    1653             :         int i;
    1654             : 
    1655           0 :         if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
    1656             :                 dc->res_pool->dp_clock_source) == false)
    1657           0 :                 dm_error("Failed to power down pll! (dp clk src)\n");
    1658             : 
    1659           0 :         for (i = 0; i < dc->res_pool->clk_src_count; i++) {
    1660           0 :                 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
    1661             :                                 dc->res_pool->clock_sources[i]) == false)
    1662           0 :                         dm_error("Failed to power down pll! (clk src index=%d)\n", i);
    1663             :         }
    1664           0 : }
    1665             : 
    1666           0 : static void power_down_all_hw_blocks(struct dc *dc)
    1667             : {
    1668           0 :         power_down_encoders(dc);
    1669             : 
    1670           0 :         power_down_controllers(dc);
    1671             : 
    1672           0 :         power_down_clock_sources(dc);
    1673             : 
    1674           0 :         if (dc->fbc_compressor)
    1675           0 :                 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
    1676           0 : }
    1677             : 
    1678           0 : static void disable_vga_and_power_gate_all_controllers(
    1679             :                 struct dc *dc)
    1680             : {
    1681             :         int i;
    1682             :         struct timing_generator *tg;
    1683           0 :         struct dc_context *ctx = dc->ctx;
    1684             : 
    1685           0 :         for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
    1686           0 :                 tg = dc->res_pool->timing_generators[i];
    1687             : 
    1688           0 :                 if (tg->funcs->disable_vga)
    1689           0 :                         tg->funcs->disable_vga(tg);
    1690             :         }
    1691           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    1692             :                 /* Enable CLOCK gating for each pipe BEFORE controller
    1693             :                  * powergating. */
    1694           0 :                 enable_display_pipe_clock_gating(ctx,
    1695             :                                 true);
    1696             : 
    1697           0 :                 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
    1698           0 :                 dc->hwss.disable_plane(dc,
    1699           0 :                         &dc->current_state->res_ctx.pipe_ctx[i]);
    1700             :         }
    1701           0 : }
    1702             : 
    1703             : 
    1704             : static void get_edp_streams(struct dc_state *context,
    1705             :                 struct dc_stream_state **edp_streams,
    1706             :                 int *edp_stream_num)
    1707             : {
    1708             :         int i;
    1709             : 
    1710             :         *edp_stream_num = 0;
    1711           0 :         for (i = 0; i < context->stream_count; i++) {
    1712           0 :                 if (context->streams[i]->signal == SIGNAL_TYPE_EDP) {
    1713           0 :                         edp_streams[*edp_stream_num] = context->streams[i];
    1714           0 :                         if (++(*edp_stream_num) == MAX_NUM_EDP)
    1715             :                                 return;
    1716             :                 }
    1717             :         }
    1718             : }
    1719             : 
    1720             : static void get_edp_links_with_sink(
    1721             :                 struct dc *dc,
    1722             :                 struct dc_link **edp_links_with_sink,
    1723             :                 int *edp_with_sink_num)
    1724             : {
    1725             :         int i;
    1726             : 
    1727             :         /* check if there is an eDP panel not in use */
    1728           0 :         *edp_with_sink_num = 0;
    1729           0 :         for (i = 0; i < dc->link_count; i++) {
    1730           0 :                 if (dc->links[i]->local_sink &&
    1731           0 :                         dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
    1732           0 :                         edp_links_with_sink[*edp_with_sink_num] = dc->links[i];
    1733           0 :                         if (++(*edp_with_sink_num) == MAX_NUM_EDP)
    1734             :                                 return;
    1735             :                 }
    1736             :         }
    1737             : }
    1738             : 
    1739             : /*
    1740             :  * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
    1741             :  *  1. Power down all DC HW blocks
    1742             :  *  2. Disable VGA engine on all controllers
    1743             :  *  3. Enable power gating for controller
    1744             :  *  4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
    1745             :  */
    1746           0 : void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
    1747             : {
    1748             :         struct dc_link *edp_links_with_sink[MAX_NUM_EDP];
    1749             :         struct dc_link *edp_links[MAX_NUM_EDP];
    1750             :         struct dc_stream_state *edp_streams[MAX_NUM_EDP];
    1751           0 :         struct dc_link *edp_link_with_sink = NULL;
    1752           0 :         struct dc_link *edp_link = NULL;
    1753           0 :         struct dce_hwseq *hws = dc->hwseq;
    1754             :         int edp_with_sink_num;
    1755             :         int edp_num;
    1756             :         int edp_stream_num;
    1757             :         int i;
    1758           0 :         bool can_apply_edp_fast_boot = false;
    1759           0 :         bool can_apply_seamless_boot = false;
    1760           0 :         bool keep_edp_vdd_on = false;
    1761             :         DC_LOGGER_INIT();
    1762             : 
    1763             : 
    1764           0 :         get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num);
    1765           0 :         get_edp_links(dc, edp_links, &edp_num);
    1766             : 
    1767           0 :         if (hws->funcs.init_pipes)
    1768           0 :                 hws->funcs.init_pipes(dc, context);
    1769             : 
    1770           0 :         get_edp_streams(context, edp_streams, &edp_stream_num);
    1771             : 
    1772             :         // Check fastboot support, disable on DCE8 because of blank screens
    1773           0 :         if (edp_num && edp_stream_num && dc->ctx->dce_version != DCE_VERSION_8_0 &&
    1774           0 :                     dc->ctx->dce_version != DCE_VERSION_8_1 &&
    1775             :                     dc->ctx->dce_version != DCE_VERSION_8_3) {
    1776           0 :                 for (i = 0; i < edp_num; i++) {
    1777           0 :                         edp_link = edp_links[i];
    1778           0 :                         if (edp_link != edp_streams[0]->link)
    1779           0 :                                 continue;
    1780             :                         // enable fastboot if backend is enabled on eDP
    1781           0 :                         if (edp_link->link_enc->funcs->is_dig_enabled &&
    1782           0 :                             edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
    1783           0 :                             edp_link->link_status.link_active) {
    1784           0 :                                 struct dc_stream_state *edp_stream = edp_streams[0];
    1785             : 
    1786           0 :                                 can_apply_edp_fast_boot = dc_validate_boot_timing(dc,
    1787           0 :                                         edp_stream->sink, &edp_stream->timing);
    1788           0 :                                 edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot;
    1789           0 :                                 if (can_apply_edp_fast_boot)
    1790           0 :                                         DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n");
    1791             : 
    1792             :                                 break;
    1793             :                         }
    1794             :                 }
    1795             :                 // We are trying to enable eDP, don't power down VDD
    1796           0 :                 if (can_apply_edp_fast_boot)
    1797           0 :                         keep_edp_vdd_on = true;
    1798             :         }
    1799             : 
    1800             :         // Check seamless boot support
    1801           0 :         for (i = 0; i < context->stream_count; i++) {
    1802           0 :                 if (context->streams[i]->apply_seamless_boot_optimization) {
    1803             :                         can_apply_seamless_boot = true;
    1804             :                         break;
    1805             :                 }
    1806             :         }
    1807             : 
    1808             :         /* eDP should not have stream in resume from S4 and so even with VBios post
    1809             :          * it should get turned off
    1810             :          */
    1811           0 :         if (edp_with_sink_num)
    1812           0 :                 edp_link_with_sink = edp_links_with_sink[0];
    1813             : 
    1814           0 :         if (!can_apply_edp_fast_boot && !can_apply_seamless_boot) {
    1815           0 :                 if (edp_link_with_sink && !keep_edp_vdd_on) {
    1816             :                         /*turn off backlight before DP_blank and encoder powered down*/
    1817           0 :                         hws->funcs.edp_backlight_control(edp_link_with_sink, false);
    1818             :                 }
    1819             :                 /*resume from S3, no vbios posting, no need to power down again*/
    1820           0 :                 power_down_all_hw_blocks(dc);
    1821           0 :                 disable_vga_and_power_gate_all_controllers(dc);
    1822           0 :                 if (edp_link_with_sink && !keep_edp_vdd_on)
    1823           0 :                         dc->hwss.edp_power_control(edp_link_with_sink, false);
    1824             :         }
    1825           0 :         bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1);
    1826           0 : }
    1827             : 
    1828             : static uint32_t compute_pstate_blackout_duration(
    1829             :         struct bw_fixed blackout_duration,
    1830             :         const struct dc_stream_state *stream)
    1831             : {
    1832             :         uint32_t total_dest_line_time_ns;
    1833             :         uint32_t pstate_blackout_duration_ns;
    1834             : 
    1835           0 :         pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
    1836             : 
    1837           0 :         total_dest_line_time_ns = 1000000UL *
    1838           0 :                 (stream->timing.h_total * 10) /
    1839           0 :                 stream->timing.pix_clk_100hz +
    1840             :                 pstate_blackout_duration_ns;
    1841             : 
    1842             :         return total_dest_line_time_ns;
    1843             : }
    1844             : 
    1845           0 : static void dce110_set_displaymarks(
    1846             :         const struct dc *dc,
    1847             :         struct dc_state *context)
    1848             : {
    1849             :         uint8_t i, num_pipes;
    1850           0 :         unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
    1851             : 
    1852           0 :         for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
    1853           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    1854             :                 uint32_t total_dest_line_time_ns;
    1855             : 
    1856           0 :                 if (pipe_ctx->stream == NULL)
    1857           0 :                         continue;
    1858             : 
    1859           0 :                 total_dest_line_time_ns = compute_pstate_blackout_duration(
    1860           0 :                         dc->bw_vbios->blackout_duration, pipe_ctx->stream);
    1861           0 :                 pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks(
    1862             :                         pipe_ctx->plane_res.mi,
    1863             :                         context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes],
    1864             :                         context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes],
    1865             :                         context->bw_ctx.bw.dce.stutter_entry_wm_ns[num_pipes],
    1866             :                         context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes],
    1867             :                         total_dest_line_time_ns);
    1868           0 :                 if (i == underlay_idx) {
    1869           0 :                         num_pipes++;
    1870           0 :                         pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks(
    1871             :                                 pipe_ctx->plane_res.mi,
    1872             :                                 context->bw_ctx.bw.dce.nbp_state_change_wm_ns[num_pipes],
    1873             :                                 context->bw_ctx.bw.dce.stutter_exit_wm_ns[num_pipes],
    1874             :                                 context->bw_ctx.bw.dce.urgent_wm_ns[num_pipes],
    1875             :                                 total_dest_line_time_ns);
    1876             :                 }
    1877           0 :                 num_pipes++;
    1878             :         }
    1879           0 : }
    1880             : 
    1881           0 : void dce110_set_safe_displaymarks(
    1882             :                 struct resource_context *res_ctx,
    1883             :                 const struct resource_pool *pool)
    1884             : {
    1885             :         int i;
    1886           0 :         int underlay_idx = pool->underlay_pipe_index;
    1887           0 :         struct dce_watermarks max_marks = {
    1888             :                 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
    1889           0 :         struct dce_watermarks nbp_marks = {
    1890             :                 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
    1891           0 :         struct dce_watermarks min_marks = { 0, 0, 0, 0};
    1892             : 
    1893           0 :         for (i = 0; i < MAX_PIPES; i++) {
    1894           0 :                 if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
    1895           0 :                         continue;
    1896             : 
    1897           0 :                 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
    1898             :                                 res_ctx->pipe_ctx[i].plane_res.mi,
    1899             :                                 nbp_marks,
    1900             :                                 max_marks,
    1901             :                                 min_marks,
    1902             :                                 max_marks,
    1903             :                                 MAX_WATERMARK);
    1904             : 
    1905           0 :                 if (i == underlay_idx)
    1906           0 :                         res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
    1907             :                                 res_ctx->pipe_ctx[i].plane_res.mi,
    1908             :                                 nbp_marks,
    1909             :                                 max_marks,
    1910             :                                 max_marks,
    1911             :                                 MAX_WATERMARK);
    1912             : 
    1913             :         }
    1914           0 : }
    1915             : 
    1916             : /*******************************************************************************
    1917             :  * Public functions
    1918             :  ******************************************************************************/
    1919             : 
    1920           0 : static void set_drr(struct pipe_ctx **pipe_ctx,
    1921             :                 int num_pipes, struct dc_crtc_timing_adjust adjust)
    1922             : {
    1923           0 :         int i = 0;
    1924           0 :         struct drr_params params = {0};
    1925             :         // DRR should set trigger event to monitor surface update event
    1926           0 :         unsigned int event_triggers = 0x80;
    1927             :         // Note DRR trigger events are generated regardless of whether num frames met.
    1928           0 :         unsigned int num_frames = 2;
    1929             : 
    1930           0 :         params.vertical_total_max = adjust.v_total_max;
    1931           0 :         params.vertical_total_min = adjust.v_total_min;
    1932             : 
    1933             :         /* TODO: If multiple pipes are to be supported, you need
    1934             :          * some GSL stuff. Static screen triggers may be programmed differently
    1935             :          * as well.
    1936             :          */
    1937           0 :         for (i = 0; i < num_pipes; i++) {
    1938           0 :                 pipe_ctx[i]->stream_res.tg->funcs->set_drr(
    1939             :                         pipe_ctx[i]->stream_res.tg, &params);
    1940             : 
    1941           0 :                 if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
    1942           0 :                         pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
    1943             :                                         pipe_ctx[i]->stream_res.tg,
    1944             :                                         event_triggers, num_frames);
    1945             :         }
    1946           0 : }
    1947             : 
    1948           0 : static void get_position(struct pipe_ctx **pipe_ctx,
    1949             :                 int num_pipes,
    1950             :                 struct crtc_position *position)
    1951             : {
    1952           0 :         int i = 0;
    1953             : 
    1954             :         /* TODO: handle pipes > 1
    1955             :          */
    1956           0 :         for (i = 0; i < num_pipes; i++)
    1957           0 :                 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
    1958           0 : }
    1959             : 
    1960           0 : static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
    1961             :                 int num_pipes, const struct dc_static_screen_params *params)
    1962             : {
    1963             :         unsigned int i;
    1964           0 :         unsigned int triggers = 0;
    1965             : 
    1966           0 :         if (params->triggers.overlay_update)
    1967           0 :                 triggers |= 0x100;
    1968           0 :         if (params->triggers.surface_update)
    1969           0 :                 triggers |= 0x80;
    1970           0 :         if (params->triggers.cursor_update)
    1971           0 :                 triggers |= 0x2;
    1972           0 :         if (params->triggers.force_trigger)
    1973           0 :                 triggers |= 0x1;
    1974             : 
    1975           0 :         if (num_pipes) {
    1976           0 :                 struct dc *dc = pipe_ctx[0]->stream->ctx->dc;
    1977             : 
    1978           0 :                 if (dc->fbc_compressor)
    1979           0 :                         triggers |= 0x84;
    1980             :         }
    1981             : 
    1982           0 :         for (i = 0; i < num_pipes; i++)
    1983           0 :                 pipe_ctx[i]->stream_res.tg->funcs->
    1984             :                         set_static_screen_control(pipe_ctx[i]->stream_res.tg,
    1985             :                                         triggers, params->num_frames);
    1986           0 : }
    1987             : 
    1988             : /*
    1989             :  *  Check if FBC can be enabled
    1990             :  */
    1991           0 : static bool should_enable_fbc(struct dc *dc,
    1992             :                 struct dc_state *context,
    1993             :                 uint32_t *pipe_idx)
    1994             : {
    1995             :         uint32_t i;
    1996           0 :         struct pipe_ctx *pipe_ctx = NULL;
    1997           0 :         struct resource_context *res_ctx = &context->res_ctx;
    1998           0 :         unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
    1999             : 
    2000             : 
    2001           0 :         ASSERT(dc->fbc_compressor);
    2002             : 
    2003             :         /* FBC memory should be allocated */
    2004           0 :         if (!dc->ctx->fbc_gpu_addr)
    2005             :                 return false;
    2006             : 
    2007             :         /* Only supports single display */
    2008           0 :         if (context->stream_count != 1)
    2009             :                 return false;
    2010             : 
    2011           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2012           0 :                 if (res_ctx->pipe_ctx[i].stream) {
    2013             : 
    2014           0 :                         pipe_ctx = &res_ctx->pipe_ctx[i];
    2015             : 
    2016           0 :                         if (!pipe_ctx)
    2017           0 :                                 continue;
    2018             : 
    2019             :                         /* fbc not applicable on underlay pipe */
    2020           0 :                         if (pipe_ctx->pipe_idx != underlay_idx) {
    2021           0 :                                 *pipe_idx = i;
    2022           0 :                                 break;
    2023             :                         }
    2024             :                 }
    2025             :         }
    2026             : 
    2027           0 :         if (i == dc->res_pool->pipe_count)
    2028             :                 return false;
    2029             : 
    2030           0 :         if (!pipe_ctx->stream->link)
    2031             :                 return false;
    2032             : 
    2033             :         /* Only supports eDP */
    2034           0 :         if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
    2035             :                 return false;
    2036             : 
    2037             :         /* PSR should not be enabled */
    2038           0 :         if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled)
    2039             :                 return false;
    2040             : 
    2041             :         /* Nothing to compress */
    2042           0 :         if (!pipe_ctx->plane_state)
    2043             :                 return false;
    2044             : 
    2045             :         /* Only for non-linear tiling */
    2046           0 :         if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
    2047             :                 return false;
    2048             : 
    2049           0 :         return true;
    2050             : }
    2051             : 
    2052             : /*
    2053             :  *  Enable FBC
    2054             :  */
    2055           0 : static void enable_fbc(
    2056             :                 struct dc *dc,
    2057             :                 struct dc_state *context)
    2058             : {
    2059           0 :         uint32_t pipe_idx = 0;
    2060             : 
    2061           0 :         if (should_enable_fbc(dc, context, &pipe_idx)) {
    2062             :                 /* Program GRPH COMPRESSED ADDRESS and PITCH */
    2063             :                 struct compr_addr_and_pitch_params params = {0, 0, 0};
    2064           0 :                 struct compressor *compr = dc->fbc_compressor;
    2065           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
    2066             : 
    2067           0 :                 params.source_view_width = pipe_ctx->stream->timing.h_addressable;
    2068           0 :                 params.source_view_height = pipe_ctx->stream->timing.v_addressable;
    2069           0 :                 params.inst = pipe_ctx->stream_res.tg->inst;
    2070           0 :                 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
    2071             : 
    2072           0 :                 compr->funcs->surface_address_and_pitch(compr, &params);
    2073           0 :                 compr->funcs->set_fbc_invalidation_triggers(compr, 1);
    2074             : 
    2075           0 :                 compr->funcs->enable_fbc(compr, &params);
    2076             :         }
    2077           0 : }
    2078             : 
    2079           0 : static void dce110_reset_hw_ctx_wrap(
    2080             :                 struct dc *dc,
    2081             :                 struct dc_state *context)
    2082             : {
    2083             :         int i;
    2084             : 
    2085             :         /* Reset old context */
    2086             :         /* look up the targets that have been removed since last commit */
    2087           0 :         for (i = 0; i < MAX_PIPES; i++) {
    2088           0 :                 struct pipe_ctx *pipe_ctx_old =
    2089           0 :                         &dc->current_state->res_ctx.pipe_ctx[i];
    2090           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    2091             : 
    2092             :                 /* Note: We need to disable output if clock sources change,
    2093             :                  * since bios does optimization and doesn't apply if changing
    2094             :                  * PHY when not already disabled.
    2095             :                  */
    2096             : 
    2097             :                 /* Skip underlay pipe since it will be handled in commit surface*/
    2098           0 :                 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
    2099           0 :                         continue;
    2100             : 
    2101           0 :                 if (!pipe_ctx->stream ||
    2102           0 :                                 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
    2103           0 :                         struct clock_source *old_clk = pipe_ctx_old->clock_source;
    2104             : 
    2105             :                         /* Disable if new stream is null. O/w, if stream is
    2106             :                          * disabled already, no need to disable again.
    2107             :                          */
    2108           0 :                         if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) {
    2109           0 :                                 core_link_disable_stream(pipe_ctx_old);
    2110             : 
    2111             :                                 /* free acquired resources*/
    2112           0 :                                 if (pipe_ctx_old->stream_res.audio) {
    2113             :                                         /*disable az_endpoint*/
    2114           0 :                                         pipe_ctx_old->stream_res.audio->funcs->
    2115             :                                                         az_disable(pipe_ctx_old->stream_res.audio);
    2116             : 
    2117             :                                         /*free audio*/
    2118           0 :                                         if (dc->caps.dynamic_audio == true) {
    2119             :                                                 /*we have to dynamic arbitrate the audio endpoints*/
    2120             :                                                 /*we free the resource, need reset is_audio_acquired*/
    2121           0 :                                                 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
    2122             :                                                                 pipe_ctx_old->stream_res.audio, false);
    2123           0 :                                                 pipe_ctx_old->stream_res.audio = NULL;
    2124             :                                         }
    2125             :                                 }
    2126             :                         }
    2127             : 
    2128           0 :                         pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
    2129           0 :                         if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
    2130           0 :                                 dm_error("DC: failed to blank crtc!\n");
    2131           0 :                                 BREAK_TO_DEBUGGER();
    2132             :                         }
    2133           0 :                         pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
    2134           0 :                         pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
    2135           0 :                                         pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
    2136             : 
    2137           0 :                         if (old_clk && 0 == resource_get_clock_source_reference(&context->res_ctx,
    2138           0 :                                                                                 dc->res_pool,
    2139             :                                                                                 old_clk))
    2140           0 :                                 old_clk->funcs->cs_power_down(old_clk);
    2141             : 
    2142           0 :                         dc->hwss.disable_plane(dc, pipe_ctx_old);
    2143             : 
    2144           0 :                         pipe_ctx_old->stream = NULL;
    2145             :                 }
    2146             :         }
    2147           0 : }
    2148             : 
    2149           0 : static void dce110_setup_audio_dto(
    2150             :                 struct dc *dc,
    2151             :                 struct dc_state *context)
    2152             : {
    2153             :         int i;
    2154             : 
    2155             :         /* program audio wall clock. use HDMI as clock source if HDMI
    2156             :          * audio active. Otherwise, use DP as clock source
    2157             :          * first, loop to find any HDMI audio, if not, loop find DP audio
    2158             :          */
    2159             :         /* Setup audio rate clock source */
    2160             :         /* Issue:
    2161             :         * Audio lag happened on DP monitor when unplug a HDMI monitor
    2162             :         *
    2163             :         * Cause:
    2164             :         * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
    2165             :         * is set to either dto0 or dto1, audio should work fine.
    2166             :         * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
    2167             :         * set to dto0 will cause audio lag.
    2168             :         *
    2169             :         * Solution:
    2170             :         * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
    2171             :         * find first available pipe with audio, setup audio wall DTO per topology
    2172             :         * instead of per pipe.
    2173             :         */
    2174           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2175           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    2176             : 
    2177           0 :                 if (pipe_ctx->stream == NULL)
    2178           0 :                         continue;
    2179             : 
    2180           0 :                 if (pipe_ctx->top_pipe)
    2181           0 :                         continue;
    2182           0 :                 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
    2183           0 :                         continue;
    2184           0 :                 if (pipe_ctx->stream_res.audio != NULL) {
    2185             :                         struct audio_output audio_output;
    2186             : 
    2187           0 :                         build_audio_output(context, pipe_ctx, &audio_output);
    2188             : 
    2189           0 :                         if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) {
    2190           0 :                                 struct dtbclk_dto_params dto_params = {0};
    2191             : 
    2192           0 :                                 dc->res_pool->dccg->funcs->set_audio_dtbclk_dto(
    2193             :                                         dc->res_pool->dccg, &dto_params);
    2194             : 
    2195           0 :                                 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
    2196             :                                                 pipe_ctx->stream_res.audio,
    2197           0 :                                                 pipe_ctx->stream->signal,
    2198             :                                                 &audio_output.crtc_info,
    2199             :                                                 &audio_output.pll_info);
    2200             :                         } else
    2201           0 :                                 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
    2202             :                                         pipe_ctx->stream_res.audio,
    2203           0 :                                         pipe_ctx->stream->signal,
    2204             :                                         &audio_output.crtc_info,
    2205             :                                         &audio_output.pll_info);
    2206             :                         break;
    2207             :                 }
    2208             :         }
    2209             : 
    2210             :         /* no HDMI audio is found, try DP audio */
    2211           0 :         if (i == dc->res_pool->pipe_count) {
    2212           0 :                 for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2213           0 :                         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    2214             : 
    2215           0 :                         if (pipe_ctx->stream == NULL)
    2216           0 :                                 continue;
    2217             : 
    2218           0 :                         if (pipe_ctx->top_pipe)
    2219           0 :                                 continue;
    2220             : 
    2221           0 :                         if (!dc_is_dp_signal(pipe_ctx->stream->signal))
    2222           0 :                                 continue;
    2223             : 
    2224           0 :                         if (pipe_ctx->stream_res.audio != NULL) {
    2225             :                                 struct audio_output audio_output;
    2226             : 
    2227           0 :                                 build_audio_output(context, pipe_ctx, &audio_output);
    2228             : 
    2229           0 :                                 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
    2230             :                                         pipe_ctx->stream_res.audio,
    2231           0 :                                         pipe_ctx->stream->signal,
    2232             :                                         &audio_output.crtc_info,
    2233             :                                         &audio_output.pll_info);
    2234             :                                 break;
    2235             :                         }
    2236             :                 }
    2237             :         }
    2238           0 : }
    2239             : 
    2240           0 : enum dc_status dce110_apply_ctx_to_hw(
    2241             :                 struct dc *dc,
    2242             :                 struct dc_state *context)
    2243             : {
    2244           0 :         struct dce_hwseq *hws = dc->hwseq;
    2245           0 :         struct dc_bios *dcb = dc->ctx->dc_bios;
    2246             :         enum dc_status status;
    2247             :         int i;
    2248             : 
    2249             :         /* reset syncd pipes from disabled pipes */
    2250           0 :         if (dc->config.use_pipe_ctx_sync_logic)
    2251           0 :                 reset_syncd_pipes_from_disabled_pipes(dc, context);
    2252             : 
    2253             :         /* Reset old context */
    2254             :         /* look up the targets that have been removed since last commit */
    2255           0 :         hws->funcs.reset_hw_ctx_wrap(dc, context);
    2256             : 
    2257             :         /* Skip applying if no targets */
    2258           0 :         if (context->stream_count <= 0)
    2259             :                 return DC_OK;
    2260             : 
    2261             :         /* Apply new context */
    2262           0 :         dcb->funcs->set_scratch_critical_state(dcb, true);
    2263             : 
    2264             :         /* below is for real asic only */
    2265           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2266           0 :                 struct pipe_ctx *pipe_ctx_old =
    2267           0 :                                         &dc->current_state->res_ctx.pipe_ctx[i];
    2268           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    2269             : 
    2270           0 :                 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
    2271           0 :                         continue;
    2272             : 
    2273           0 :                 if (pipe_ctx->stream == pipe_ctx_old->stream) {
    2274           0 :                         if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
    2275           0 :                                 dce_crtc_switch_to_clk_src(dc->hwseq,
    2276             :                                                 pipe_ctx->clock_source, i);
    2277           0 :                         continue;
    2278             :                 }
    2279             : 
    2280           0 :                 hws->funcs.enable_display_power_gating(
    2281           0 :                                 dc, i, dc->ctx->dc_bios,
    2282             :                                 PIPE_GATING_CONTROL_DISABLE);
    2283             :         }
    2284             : 
    2285           0 :         if (dc->fbc_compressor)
    2286           0 :                 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
    2287             : 
    2288           0 :         dce110_setup_audio_dto(dc, context);
    2289             : 
    2290           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2291           0 :                 struct pipe_ctx *pipe_ctx_old =
    2292           0 :                                         &dc->current_state->res_ctx.pipe_ctx[i];
    2293           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    2294             : 
    2295           0 :                 if (pipe_ctx->stream == NULL)
    2296           0 :                         continue;
    2297             : 
    2298           0 :                 if (pipe_ctx->stream == pipe_ctx_old->stream &&
    2299           0 :                         pipe_ctx->stream->link->link_state_valid) {
    2300           0 :                         continue;
    2301             :                 }
    2302             : 
    2303           0 :                 if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
    2304           0 :                         continue;
    2305             : 
    2306           0 :                 if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe)
    2307           0 :                         continue;
    2308             : 
    2309           0 :                 status = apply_single_controller_ctx_to_hw(
    2310             :                                 pipe_ctx,
    2311             :                                 context,
    2312             :                                 dc);
    2313             : 
    2314           0 :                 if (DC_OK != status)
    2315             :                         return status;
    2316             :         }
    2317             : 
    2318           0 :         if (dc->fbc_compressor)
    2319           0 :                 enable_fbc(dc, dc->current_state);
    2320             : 
    2321           0 :         dcb->funcs->set_scratch_critical_state(dcb, false);
    2322             : 
    2323           0 :         return DC_OK;
    2324             : }
    2325             : 
    2326             : /*******************************************************************************
    2327             :  * Front End programming
    2328             :  ******************************************************************************/
    2329           0 : static void set_default_colors(struct pipe_ctx *pipe_ctx)
    2330             : {
    2331           0 :         struct default_adjustment default_adjust = { 0 };
    2332             : 
    2333             :         default_adjust.force_hw_default = false;
    2334           0 :         default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
    2335           0 :         default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
    2336           0 :         default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
    2337           0 :         default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
    2338             : 
    2339             :         /* display color depth */
    2340           0 :         default_adjust.color_depth =
    2341           0 :                 pipe_ctx->stream->timing.display_color_depth;
    2342             : 
    2343             :         /* Lb color depth */
    2344           0 :         default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
    2345             : 
    2346           0 :         pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
    2347             :                                         pipe_ctx->plane_res.xfm, &default_adjust);
    2348           0 : }
    2349             : 
    2350             : 
    2351             : /*******************************************************************************
    2352             :  * In order to turn on/off specific surface we will program
    2353             :  * Blender + CRTC
    2354             :  *
    2355             :  * In case that we have two surfaces and they have a different visibility
    2356             :  * we can't turn off the CRTC since it will turn off the entire display
    2357             :  *
    2358             :  * |----------------------------------------------- |
    2359             :  * |bottom pipe|curr pipe  |              |         |
    2360             :  * |Surface    |Surface    | Blender      |  CRCT   |
    2361             :  * |visibility |visibility | Configuration|         |
    2362             :  * |------------------------------------------------|
    2363             :  * |   off     |    off    | CURRENT_PIPE | blank   |
    2364             :  * |   off     |    on     | CURRENT_PIPE | unblank |
    2365             :  * |   on      |    off    | OTHER_PIPE   | unblank |
    2366             :  * |   on      |    on     | BLENDING     | unblank |
    2367             :  * -------------------------------------------------|
    2368             :  *
    2369             :  ******************************************************************************/
    2370           0 : static void program_surface_visibility(const struct dc *dc,
    2371             :                 struct pipe_ctx *pipe_ctx)
    2372             : {
    2373           0 :         enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
    2374           0 :         bool blank_target = false;
    2375             : 
    2376           0 :         if (pipe_ctx->bottom_pipe) {
    2377             : 
    2378             :                 /* For now we are supporting only two pipes */
    2379           0 :                 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
    2380             : 
    2381           0 :                 if (pipe_ctx->bottom_pipe->plane_state->visible) {
    2382           0 :                         if (pipe_ctx->plane_state->visible)
    2383             :                                 blender_mode = BLND_MODE_BLENDING;
    2384             :                         else
    2385           0 :                                 blender_mode = BLND_MODE_OTHER_PIPE;
    2386             : 
    2387           0 :                 } else if (!pipe_ctx->plane_state->visible)
    2388           0 :                         blank_target = true;
    2389             : 
    2390           0 :         } else if (!pipe_ctx->plane_state->visible)
    2391           0 :                 blank_target = true;
    2392             : 
    2393           0 :         dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode);
    2394           0 :         pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
    2395             : 
    2396           0 : }
    2397             : 
    2398           0 : static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
    2399             : {
    2400           0 :         int i = 0;
    2401             :         struct xfm_grph_csc_adjustment adjust;
    2402           0 :         memset(&adjust, 0, sizeof(adjust));
    2403           0 :         adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
    2404             : 
    2405             : 
    2406           0 :         if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
    2407           0 :                 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
    2408             : 
    2409           0 :                 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
    2410           0 :                         adjust.temperature_matrix[i] =
    2411             :                                 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
    2412             :         }
    2413             : 
    2414           0 :         pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
    2415           0 : }
    2416           0 : static void update_plane_addr(const struct dc *dc,
    2417             :                 struct pipe_ctx *pipe_ctx)
    2418             : {
    2419           0 :         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
    2420             : 
    2421           0 :         if (plane_state == NULL)
    2422             :                 return;
    2423             : 
    2424           0 :         pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr(
    2425             :                         pipe_ctx->plane_res.mi,
    2426           0 :                         &plane_state->address,
    2427           0 :                         plane_state->flip_immediate);
    2428             : 
    2429           0 :         plane_state->status.requested_address = plane_state->address;
    2430             : }
    2431             : 
    2432           0 : static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
    2433             : {
    2434           0 :         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
    2435             : 
    2436           0 :         if (plane_state == NULL)
    2437             :                 return;
    2438             : 
    2439           0 :         plane_state->status.is_flip_pending =
    2440           0 :                         pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending(
    2441             :                                         pipe_ctx->plane_res.mi);
    2442             : 
    2443           0 :         if (plane_state->status.is_flip_pending && !plane_state->visible)
    2444           0 :                 pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address;
    2445             : 
    2446           0 :         plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address;
    2447           0 :         if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
    2448           0 :                         pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) {
    2449           0 :                 plane_state->status.is_right_eye =\
    2450           0 :                                 !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
    2451             :         }
    2452             : }
    2453             : 
    2454           0 : void dce110_power_down(struct dc *dc)
    2455             : {
    2456           0 :         power_down_all_hw_blocks(dc);
    2457           0 :         disable_vga_and_power_gate_all_controllers(dc);
    2458           0 : }
    2459             : 
    2460           0 : static bool wait_for_reset_trigger_to_occur(
    2461             :         struct dc_context *dc_ctx,
    2462             :         struct timing_generator *tg)
    2463             : {
    2464           0 :         bool rc = false;
    2465             : 
    2466             :         /* To avoid endless loop we wait at most
    2467             :          * frames_to_wait_on_triggered_reset frames for the reset to occur. */
    2468           0 :         const uint32_t frames_to_wait_on_triggered_reset = 10;
    2469             :         uint32_t i;
    2470             : 
    2471           0 :         for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
    2472             : 
    2473           0 :                 if (!tg->funcs->is_counter_moving(tg)) {
    2474           0 :                         DC_ERROR("TG counter is not moving!\n");
    2475             :                         break;
    2476             :                 }
    2477             : 
    2478           0 :                 if (tg->funcs->did_triggered_reset_occur(tg)) {
    2479           0 :                         rc = true;
    2480             :                         /* usually occurs at i=1 */
    2481           0 :                         DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
    2482             :                                         i);
    2483             :                         break;
    2484             :                 }
    2485             : 
    2486             :                 /* Wait for one frame. */
    2487           0 :                 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
    2488           0 :                 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
    2489             :         }
    2490             : 
    2491           0 :         if (false == rc)
    2492           0 :                 DC_ERROR("GSL: Timeout on reset trigger!\n");
    2493             : 
    2494           0 :         return rc;
    2495             : }
    2496             : 
    2497             : /* Enable timing synchronization for a group of Timing Generators. */
    2498           0 : static void dce110_enable_timing_synchronization(
    2499             :                 struct dc *dc,
    2500             :                 int group_index,
    2501             :                 int group_size,
    2502             :                 struct pipe_ctx *grouped_pipes[])
    2503             : {
    2504           0 :         struct dc_context *dc_ctx = dc->ctx;
    2505           0 :         struct dcp_gsl_params gsl_params = { 0 };
    2506             :         int i;
    2507             : 
    2508           0 :         DC_SYNC_INFO("GSL: Setting-up...\n");
    2509             : 
    2510             :         /* Designate a single TG in the group as a master.
    2511             :          * Since HW doesn't care which one, we always assign
    2512             :          * the 1st one in the group. */
    2513           0 :         gsl_params.gsl_group = 0;
    2514           0 :         gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst;
    2515             : 
    2516           0 :         for (i = 0; i < group_size; i++)
    2517           0 :                 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
    2518             :                                         grouped_pipes[i]->stream_res.tg, &gsl_params);
    2519             : 
    2520             :         /* Reset slave controllers on master VSync */
    2521           0 :         DC_SYNC_INFO("GSL: enabling trigger-reset\n");
    2522             : 
    2523           0 :         for (i = 1 /* skip the master */; i < group_size; i++)
    2524           0 :                 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
    2525             :                                 grouped_pipes[i]->stream_res.tg,
    2526             :                                 gsl_params.gsl_group);
    2527             : 
    2528           0 :         for (i = 1 /* skip the master */; i < group_size; i++) {
    2529           0 :                 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
    2530           0 :                 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
    2531           0 :                 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
    2532             :                                 grouped_pipes[i]->stream_res.tg);
    2533             :         }
    2534             : 
    2535             :         /* GSL Vblank synchronization is a one time sync mechanism, assumption
    2536             :          * is that the sync'ed displays will not drift out of sync over time*/
    2537           0 :         DC_SYNC_INFO("GSL: Restoring register states.\n");
    2538           0 :         for (i = 0; i < group_size; i++)
    2539           0 :                 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
    2540             : 
    2541           0 :         DC_SYNC_INFO("GSL: Set-up complete.\n");
    2542           0 : }
    2543             : 
    2544           0 : static void dce110_enable_per_frame_crtc_position_reset(
    2545             :                 struct dc *dc,
    2546             :                 int group_size,
    2547             :                 struct pipe_ctx *grouped_pipes[])
    2548             : {
    2549           0 :         struct dc_context *dc_ctx = dc->ctx;
    2550           0 :         struct dcp_gsl_params gsl_params = { 0 };
    2551             :         int i;
    2552             : 
    2553             :         gsl_params.gsl_group = 0;
    2554             :         gsl_params.gsl_master = 0;
    2555             : 
    2556           0 :         for (i = 0; i < group_size; i++)
    2557           0 :                 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
    2558             :                                         grouped_pipes[i]->stream_res.tg, &gsl_params);
    2559             : 
    2560           0 :         DC_SYNC_INFO("GSL: enabling trigger-reset\n");
    2561             : 
    2562           0 :         for (i = 1; i < group_size; i++)
    2563           0 :                 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
    2564             :                                 grouped_pipes[i]->stream_res.tg,
    2565             :                                 gsl_params.gsl_master,
    2566           0 :                                 &grouped_pipes[i]->stream->triggered_crtc_reset);
    2567             : 
    2568           0 :         DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
    2569           0 :         for (i = 1; i < group_size; i++)
    2570           0 :                 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
    2571             : 
    2572           0 :         for (i = 0; i < group_size; i++)
    2573           0 :                 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
    2574             : 
    2575           0 : }
    2576             : 
    2577           0 : static void init_pipes(struct dc *dc, struct dc_state *context)
    2578             : {
    2579             :         // Do nothing
    2580           0 : }
    2581             : 
    2582           0 : static void init_hw(struct dc *dc)
    2583             : {
    2584             :         int i;
    2585             :         struct dc_bios *bp;
    2586             :         struct transform *xfm;
    2587             :         struct abm *abm;
    2588             :         struct dmcu *dmcu;
    2589           0 :         struct dce_hwseq *hws = dc->hwseq;
    2590           0 :         uint32_t backlight = MAX_BACKLIGHT_LEVEL;
    2591             : 
    2592           0 :         bp = dc->ctx->dc_bios;
    2593           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2594           0 :                 xfm = dc->res_pool->transforms[i];
    2595           0 :                 xfm->funcs->transform_reset(xfm);
    2596             : 
    2597           0 :                 hws->funcs.enable_display_power_gating(
    2598             :                                 dc, i, bp,
    2599             :                                 PIPE_GATING_CONTROL_INIT);
    2600           0 :                 hws->funcs.enable_display_power_gating(
    2601             :                                 dc, i, bp,
    2602             :                                 PIPE_GATING_CONTROL_DISABLE);
    2603           0 :                 hws->funcs.enable_display_pipe_clock_gating(
    2604             :                         dc->ctx,
    2605             :                         true);
    2606             :         }
    2607             : 
    2608           0 :         dce_clock_gating_power_up(dc->hwseq, false);
    2609             :         /***************************************/
    2610             : 
    2611           0 :         for (i = 0; i < dc->link_count; i++) {
    2612             :                 /****************************************/
    2613             :                 /* Power up AND update implementation according to the
    2614             :                  * required signal (which may be different from the
    2615             :                  * default signal on connector). */
    2616           0 :                 struct dc_link *link = dc->links[i];
    2617             : 
    2618           0 :                 link->link_enc->funcs->hw_init(link->link_enc);
    2619             :         }
    2620             : 
    2621           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2622           0 :                 struct timing_generator *tg = dc->res_pool->timing_generators[i];
    2623             : 
    2624           0 :                 tg->funcs->disable_vga(tg);
    2625             : 
    2626             :                 /* Blank controller using driver code instead of
    2627             :                  * command table. */
    2628           0 :                 tg->funcs->set_blank(tg, true);
    2629           0 :                 hwss_wait_for_blank_complete(tg);
    2630             :         }
    2631             : 
    2632           0 :         for (i = 0; i < dc->res_pool->audio_count; i++) {
    2633           0 :                 struct audio *audio = dc->res_pool->audios[i];
    2634           0 :                 audio->funcs->hw_init(audio);
    2635             :         }
    2636             : 
    2637           0 :         for (i = 0; i < dc->link_count; i++) {
    2638           0 :                 struct dc_link *link = dc->links[i];
    2639             : 
    2640           0 :                 if (link->panel_cntl)
    2641           0 :                         backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
    2642             :         }
    2643             : 
    2644           0 :         abm = dc->res_pool->abm;
    2645           0 :         if (abm != NULL)
    2646           0 :                 abm->funcs->abm_init(abm, backlight);
    2647             : 
    2648           0 :         dmcu = dc->res_pool->dmcu;
    2649           0 :         if (dmcu != NULL && abm != NULL)
    2650           0 :                 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
    2651             : 
    2652           0 :         if (dc->fbc_compressor)
    2653           0 :                 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
    2654             : 
    2655           0 : }
    2656             : 
    2657             : 
    2658           0 : void dce110_prepare_bandwidth(
    2659             :                 struct dc *dc,
    2660             :                 struct dc_state *context)
    2661             : {
    2662           0 :         struct clk_mgr *dccg = dc->clk_mgr;
    2663             : 
    2664           0 :         dce110_set_safe_displaymarks(&context->res_ctx, dc->res_pool);
    2665             : 
    2666           0 :         dccg->funcs->update_clocks(
    2667             :                         dccg,
    2668             :                         context,
    2669             :                         false);
    2670           0 : }
    2671             : 
    2672           0 : void dce110_optimize_bandwidth(
    2673             :                 struct dc *dc,
    2674             :                 struct dc_state *context)
    2675             : {
    2676           0 :         struct clk_mgr *dccg = dc->clk_mgr;
    2677             : 
    2678           0 :         dce110_set_displaymarks(dc, context);
    2679             : 
    2680           0 :         dccg->funcs->update_clocks(
    2681             :                         dccg,
    2682             :                         context,
    2683             :                         true);
    2684           0 : }
    2685             : 
    2686           0 : static void dce110_program_front_end_for_pipe(
    2687             :                 struct dc *dc, struct pipe_ctx *pipe_ctx)
    2688             : {
    2689           0 :         struct mem_input *mi = pipe_ctx->plane_res.mi;
    2690           0 :         struct dc_plane_state *plane_state = pipe_ctx->plane_state;
    2691             :         struct xfm_grph_csc_adjustment adjust;
    2692             :         struct out_csc_color_matrix tbl_entry;
    2693             :         unsigned int i;
    2694           0 :         struct dce_hwseq *hws = dc->hwseq;
    2695             : 
    2696             :         DC_LOGGER_INIT();
    2697           0 :         memset(&tbl_entry, 0, sizeof(tbl_entry));
    2698             : 
    2699           0 :         memset(&adjust, 0, sizeof(adjust));
    2700           0 :         adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
    2701             : 
    2702           0 :         dce_enable_fe_clock(dc->hwseq, mi->inst, true);
    2703             : 
    2704           0 :         set_default_colors(pipe_ctx);
    2705           0 :         if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
    2706             :                         == true) {
    2707           0 :                 tbl_entry.color_space =
    2708           0 :                         pipe_ctx->stream->output_color_space;
    2709             : 
    2710           0 :                 for (i = 0; i < 12; i++)
    2711           0 :                         tbl_entry.regval[i] =
    2712           0 :                         pipe_ctx->stream->csc_color_matrix.matrix[i];
    2713             : 
    2714           0 :                 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
    2715             :                                 (pipe_ctx->plane_res.xfm, &tbl_entry);
    2716             :         }
    2717             : 
    2718           0 :         if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
    2719           0 :                 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
    2720             : 
    2721           0 :                 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
    2722           0 :                         adjust.temperature_matrix[i] =
    2723             :                                 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
    2724             :         }
    2725             : 
    2726           0 :         pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
    2727             : 
    2728           0 :         pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != NULL;
    2729             : 
    2730           0 :         program_scaler(dc, pipe_ctx);
    2731             : 
    2732           0 :         mi->funcs->mem_input_program_surface_config(
    2733             :                         mi,
    2734             :                         plane_state->format,
    2735             :                         &plane_state->tiling_info,
    2736             :                         &plane_state->plane_size,
    2737             :                         plane_state->rotation,
    2738             :                         NULL,
    2739             :                         false);
    2740           0 :         if (mi->funcs->set_blank)
    2741           0 :                 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
    2742             : 
    2743           0 :         if (dc->config.gpu_vm_support)
    2744           0 :                 mi->funcs->mem_input_program_pte_vm(
    2745             :                                 pipe_ctx->plane_res.mi,
    2746             :                                 plane_state->format,
    2747             :                                 &plane_state->tiling_info,
    2748             :                                 plane_state->rotation);
    2749             : 
    2750             :         /* Moved programming gamma from dc to hwss */
    2751           0 :         if (pipe_ctx->plane_state->update_flags.bits.full_update ||
    2752           0 :                         pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
    2753             :                         pipe_ctx->plane_state->update_flags.bits.gamma_change)
    2754           0 :                 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
    2755             : 
    2756           0 :         if (pipe_ctx->plane_state->update_flags.bits.full_update)
    2757           0 :                 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
    2758             : 
    2759             :         DC_LOG_SURFACE(
    2760             :                         "Pipe:%d %p: addr hi:0x%x, "
    2761             :                         "addr low:0x%x, "
    2762             :                         "src: %d, %d, %d,"
    2763             :                         " %d; dst: %d, %d, %d, %d;"
    2764             :                         "clip: %d, %d, %d, %d\n",
    2765             :                         pipe_ctx->pipe_idx,
    2766             :                         (void *) pipe_ctx->plane_state,
    2767             :                         pipe_ctx->plane_state->address.grph.addr.high_part,
    2768             :                         pipe_ctx->plane_state->address.grph.addr.low_part,
    2769             :                         pipe_ctx->plane_state->src_rect.x,
    2770             :                         pipe_ctx->plane_state->src_rect.y,
    2771             :                         pipe_ctx->plane_state->src_rect.width,
    2772             :                         pipe_ctx->plane_state->src_rect.height,
    2773             :                         pipe_ctx->plane_state->dst_rect.x,
    2774             :                         pipe_ctx->plane_state->dst_rect.y,
    2775             :                         pipe_ctx->plane_state->dst_rect.width,
    2776             :                         pipe_ctx->plane_state->dst_rect.height,
    2777             :                         pipe_ctx->plane_state->clip_rect.x,
    2778             :                         pipe_ctx->plane_state->clip_rect.y,
    2779             :                         pipe_ctx->plane_state->clip_rect.width,
    2780             :                         pipe_ctx->plane_state->clip_rect.height);
    2781             : 
    2782             :         DC_LOG_SURFACE(
    2783             :                         "Pipe %d: width, height, x, y\n"
    2784             :                         "viewport:%d, %d, %d, %d\n"
    2785             :                         "recout:  %d, %d, %d, %d\n",
    2786             :                         pipe_ctx->pipe_idx,
    2787             :                         pipe_ctx->plane_res.scl_data.viewport.width,
    2788             :                         pipe_ctx->plane_res.scl_data.viewport.height,
    2789             :                         pipe_ctx->plane_res.scl_data.viewport.x,
    2790             :                         pipe_ctx->plane_res.scl_data.viewport.y,
    2791             :                         pipe_ctx->plane_res.scl_data.recout.width,
    2792             :                         pipe_ctx->plane_res.scl_data.recout.height,
    2793             :                         pipe_ctx->plane_res.scl_data.recout.x,
    2794             :                         pipe_ctx->plane_res.scl_data.recout.y);
    2795           0 : }
    2796             : 
    2797           0 : static void dce110_apply_ctx_for_surface(
    2798             :                 struct dc *dc,
    2799             :                 const struct dc_stream_state *stream,
    2800             :                 int num_planes,
    2801             :                 struct dc_state *context)
    2802             : {
    2803             :         int i;
    2804             : 
    2805           0 :         if (num_planes == 0)
    2806             :                 return;
    2807             : 
    2808           0 :         if (dc->fbc_compressor)
    2809           0 :                 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
    2810             : 
    2811           0 :         for (i = 0; i < dc->res_pool->pipe_count; i++) {
    2812           0 :                 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
    2813             : 
    2814           0 :                 if (pipe_ctx->stream != stream)
    2815           0 :                         continue;
    2816             : 
    2817             :                 /* Need to allocate mem before program front end for Fiji */
    2818           0 :                 pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
    2819             :                                 pipe_ctx->plane_res.mi,
    2820             :                                 pipe_ctx->stream->timing.h_total,
    2821             :                                 pipe_ctx->stream->timing.v_total,
    2822           0 :                                 pipe_ctx->stream->timing.pix_clk_100hz / 10,
    2823           0 :                                 context->stream_count);
    2824             : 
    2825           0 :                 dce110_program_front_end_for_pipe(dc, pipe_ctx);
    2826             : 
    2827           0 :                 dc->hwss.update_plane_addr(dc, pipe_ctx);
    2828             : 
    2829           0 :                 program_surface_visibility(dc, pipe_ctx);
    2830             : 
    2831             :         }
    2832             : 
    2833           0 :         if (dc->fbc_compressor)
    2834           0 :                 enable_fbc(dc, context);
    2835             : }
    2836             : 
    2837           0 : static void dce110_post_unlock_program_front_end(
    2838             :                 struct dc *dc,
    2839             :                 struct dc_state *context)
    2840             : {
    2841           0 : }
    2842             : 
    2843           0 : static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
    2844             : {
    2845           0 :         struct dce_hwseq *hws = dc->hwseq;
    2846           0 :         int fe_idx = pipe_ctx->plane_res.mi ?
    2847           0 :                 pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
    2848             : 
    2849             :         /* Do not power down fe when stream is active on dce*/
    2850           0 :         if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream)
    2851             :                 return;
    2852             : 
    2853           0 :         hws->funcs.enable_display_power_gating(
    2854           0 :                 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
    2855             : 
    2856           0 :         dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
    2857             :                                 dc->res_pool->transforms[fe_idx]);
    2858             : }
    2859             : 
    2860           0 : static void dce110_wait_for_mpcc_disconnect(
    2861             :                 struct dc *dc,
    2862             :                 struct resource_pool *res_pool,
    2863             :                 struct pipe_ctx *pipe_ctx)
    2864             : {
    2865             :         /* do nothing*/
    2866           0 : }
    2867             : 
    2868           0 : static void program_output_csc(struct dc *dc,
    2869             :                 struct pipe_ctx *pipe_ctx,
    2870             :                 enum dc_color_space colorspace,
    2871             :                 uint16_t *matrix,
    2872             :                 int opp_id)
    2873             : {
    2874             :         int i;
    2875             :         struct out_csc_color_matrix tbl_entry;
    2876             : 
    2877           0 :         if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
    2878           0 :                 enum dc_color_space color_space = pipe_ctx->stream->output_color_space;
    2879             : 
    2880           0 :                 for (i = 0; i < 12; i++)
    2881           0 :                         tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
    2882             : 
    2883           0 :                 tbl_entry.color_space = color_space;
    2884             : 
    2885           0 :                 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(
    2886             :                                 pipe_ctx->plane_res.xfm, &tbl_entry);
    2887             :         }
    2888           0 : }
    2889             : 
    2890           0 : static void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
    2891             : {
    2892           0 :         struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
    2893           0 :         struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
    2894           0 :         struct mem_input *mi = pipe_ctx->plane_res.mi;
    2895           0 :         struct dc_cursor_mi_param param = {
    2896           0 :                 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
    2897           0 :                 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.xtalin_clock_inKhz,
    2898             :                 .viewport = pipe_ctx->plane_res.scl_data.viewport,
    2899             :                 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
    2900             :                 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
    2901           0 :                 .rotation = pipe_ctx->plane_state->rotation,
    2902           0 :                 .mirror = pipe_ctx->plane_state->horizontal_mirror
    2903             :         };
    2904             : 
    2905             :         /**
    2906             :          * If the cursor's source viewport is clipped then we need to
    2907             :          * translate the cursor to appear in the correct position on
    2908             :          * the screen.
    2909             :          *
    2910             :          * This translation isn't affected by scaling so it needs to be
    2911             :          * done *after* we adjust the position for the scale factor.
    2912             :          *
    2913             :          * This is only done by opt-in for now since there are still
    2914             :          * some usecases like tiled display that might enable the
    2915             :          * cursor on both streams while expecting dc to clip it.
    2916             :          */
    2917           0 :         if (pos_cpy.translate_by_source) {
    2918           0 :                 pos_cpy.x += pipe_ctx->plane_state->src_rect.x;
    2919           0 :                 pos_cpy.y += pipe_ctx->plane_state->src_rect.y;
    2920             :         }
    2921             : 
    2922           0 :         if (pipe_ctx->plane_state->address.type
    2923             :                         == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
    2924           0 :                 pos_cpy.enable = false;
    2925             : 
    2926           0 :         if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
    2927           0 :                 pos_cpy.enable = false;
    2928             : 
    2929           0 :         if (ipp->funcs->ipp_cursor_set_position)
    2930           0 :                 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, &param);
    2931           0 :         if (mi->funcs->set_cursor_position)
    2932           0 :                 mi->funcs->set_cursor_position(mi, &pos_cpy, &param);
    2933           0 : }
    2934             : 
    2935           0 : static void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
    2936             : {
    2937           0 :         struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
    2938             : 
    2939           0 :         if (pipe_ctx->plane_res.ipp &&
    2940           0 :             pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
    2941           0 :                 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
    2942             :                                 pipe_ctx->plane_res.ipp, attributes);
    2943             : 
    2944           0 :         if (pipe_ctx->plane_res.mi &&
    2945           0 :             pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
    2946           0 :                 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
    2947             :                                 pipe_ctx->plane_res.mi, attributes);
    2948             : 
    2949           0 :         if (pipe_ctx->plane_res.xfm &&
    2950           0 :             pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
    2951           0 :                 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
    2952             :                                 pipe_ctx->plane_res.xfm, attributes);
    2953           0 : }
    2954             : 
    2955           0 : bool dce110_set_backlight_level(struct pipe_ctx *pipe_ctx,
    2956             :                 uint32_t backlight_pwm_u16_16,
    2957             :                 uint32_t frame_ramp)
    2958             : {
    2959           0 :         struct dc_link *link = pipe_ctx->stream->link;
    2960           0 :         struct dc  *dc = link->ctx->dc;
    2961           0 :         struct abm *abm = pipe_ctx->stream_res.abm;
    2962           0 :         struct panel_cntl *panel_cntl = link->panel_cntl;
    2963           0 :         struct dmcu *dmcu = dc->res_pool->dmcu;
    2964           0 :         bool fw_set_brightness = true;
    2965             :         /* DMCU -1 for all controller id values,
    2966             :          * therefore +1 here
    2967             :          */
    2968           0 :         uint32_t controller_id = pipe_ctx->stream_res.tg->inst + 1;
    2969             : 
    2970           0 :         if (abm == NULL || panel_cntl == NULL || (abm->funcs->set_backlight_level_pwm == NULL))
    2971             :                 return false;
    2972             : 
    2973           0 :         if (dmcu)
    2974           0 :                 fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
    2975             : 
    2976           0 :         if (!fw_set_brightness && panel_cntl->funcs->driver_set_backlight)
    2977           0 :                 panel_cntl->funcs->driver_set_backlight(panel_cntl, backlight_pwm_u16_16);
    2978             :         else
    2979           0 :                 abm->funcs->set_backlight_level_pwm(
    2980             :                                 abm,
    2981             :                                 backlight_pwm_u16_16,
    2982             :                                 frame_ramp,
    2983             :                                 controller_id,
    2984           0 :                                 link->panel_cntl->inst);
    2985             : 
    2986             :         return true;
    2987             : }
    2988             : 
    2989           0 : void dce110_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx)
    2990             : {
    2991           0 :         struct abm *abm = pipe_ctx->stream_res.abm;
    2992           0 :         struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
    2993             : 
    2994           0 :         if (abm)
    2995           0 :                 abm->funcs->set_abm_immediate_disable(abm,
    2996             :                                 pipe_ctx->stream->link->panel_cntl->inst);
    2997             : 
    2998           0 :         if (panel_cntl)
    2999           0 :                 panel_cntl->funcs->store_backlight_level(panel_cntl);
    3000           0 : }
    3001             : 
    3002           0 : void dce110_set_pipe(struct pipe_ctx *pipe_ctx)
    3003             : {
    3004           0 :         struct abm *abm = pipe_ctx->stream_res.abm;
    3005           0 :         struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl;
    3006           0 :         uint32_t otg_inst = pipe_ctx->stream_res.tg->inst + 1;
    3007             : 
    3008           0 :         if (abm && panel_cntl)
    3009           0 :                 abm->funcs->set_pipe(abm, otg_inst, panel_cntl->inst);
    3010           0 : }
    3011             : 
    3012             : static const struct hw_sequencer_funcs dce110_funcs = {
    3013             :         .program_gamut_remap = program_gamut_remap,
    3014             :         .program_output_csc = program_output_csc,
    3015             :         .init_hw = init_hw,
    3016             :         .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
    3017             :         .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
    3018             :         .post_unlock_program_front_end = dce110_post_unlock_program_front_end,
    3019             :         .update_plane_addr = update_plane_addr,
    3020             :         .update_pending_status = dce110_update_pending_status,
    3021             :         .enable_accelerated_mode = dce110_enable_accelerated_mode,
    3022             :         .enable_timing_synchronization = dce110_enable_timing_synchronization,
    3023             :         .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset,
    3024             :         .update_info_frame = dce110_update_info_frame,
    3025             :         .enable_stream = dce110_enable_stream,
    3026             :         .disable_stream = dce110_disable_stream,
    3027             :         .unblank_stream = dce110_unblank_stream,
    3028             :         .blank_stream = dce110_blank_stream,
    3029             :         .enable_audio_stream = dce110_enable_audio_stream,
    3030             :         .disable_audio_stream = dce110_disable_audio_stream,
    3031             :         .disable_plane = dce110_power_down_fe,
    3032             :         .pipe_control_lock = dce_pipe_control_lock,
    3033             :         .interdependent_update_lock = NULL,
    3034             :         .cursor_lock = dce_pipe_control_lock,
    3035             :         .prepare_bandwidth = dce110_prepare_bandwidth,
    3036             :         .optimize_bandwidth = dce110_optimize_bandwidth,
    3037             :         .set_drr = set_drr,
    3038             :         .get_position = get_position,
    3039             :         .set_static_screen_control = set_static_screen_control,
    3040             :         .setup_stereo = NULL,
    3041             :         .set_avmute = dce110_set_avmute,
    3042             :         .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
    3043             :         .edp_backlight_control = dce110_edp_backlight_control,
    3044             :         .edp_power_control = dce110_edp_power_control,
    3045             :         .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
    3046             :         .set_cursor_position = dce110_set_cursor_position,
    3047             :         .set_cursor_attribute = dce110_set_cursor_attribute,
    3048             :         .set_backlight_level = dce110_set_backlight_level,
    3049             :         .set_abm_immediate_disable = dce110_set_abm_immediate_disable,
    3050             :         .set_pipe = dce110_set_pipe,
    3051             : };
    3052             : 
    3053             : static const struct hwseq_private_funcs dce110_private_funcs = {
    3054             :         .init_pipes = init_pipes,
    3055             :         .update_plane_addr = update_plane_addr,
    3056             :         .set_input_transfer_func = dce110_set_input_transfer_func,
    3057             :         .set_output_transfer_func = dce110_set_output_transfer_func,
    3058             :         .power_down = dce110_power_down,
    3059             :         .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
    3060             :         .enable_display_power_gating = dce110_enable_display_power_gating,
    3061             :         .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap,
    3062             :         .enable_stream_timing = dce110_enable_stream_timing,
    3063             :         .disable_stream_gating = NULL,
    3064             :         .enable_stream_gating = NULL,
    3065             :         .edp_backlight_control = dce110_edp_backlight_control,
    3066             : };
    3067             : 
    3068           0 : void dce110_hw_sequencer_construct(struct dc *dc)
    3069             : {
    3070           0 :         dc->hwss = dce110_funcs;
    3071           0 :         dc->hwseq->funcs = dce110_private_funcs;
    3072           0 : }
    3073             : 

Generated by: LCOV version 1.14