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