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