linux/drivers/gpu/drm/amd/display/dc/bios/command_table.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012-15 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "dm_services.h"
  27#include "amdgpu.h"
  28#include "atom.h"
  29
  30#include "include/bios_parser_interface.h"
  31
  32#include "command_table.h"
  33#include "command_table_helper.h"
  34#include "bios_parser_helper.h"
  35#include "bios_parser_types_internal.h"
  36
  37#define EXEC_BIOS_CMD_TABLE(command, params)\
  38        (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
  39                GetIndexIntoMasterTable(COMMAND, command), \
  40                (uint32_t *)&params) == 0)
  41
  42#define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
  43        amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
  44                GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
  45
  46#define BIOS_CMD_TABLE_PARA_REVISION(command)\
  47        bios_cmd_table_para_revision(bp->base.ctx->driver_context, \
  48                GetIndexIntoMasterTable(COMMAND, command))
  49
  50static void init_dig_encoder_control(struct bios_parser *bp);
  51static void init_transmitter_control(struct bios_parser *bp);
  52static void init_set_pixel_clock(struct bios_parser *bp);
  53static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
  54static void init_adjust_display_pll(struct bios_parser *bp);
  55static void init_dac_encoder_control(struct bios_parser *bp);
  56static void init_dac_output_control(struct bios_parser *bp);
  57static void init_set_crtc_timing(struct bios_parser *bp);
  58static void init_enable_crtc(struct bios_parser *bp);
  59static void init_enable_crtc_mem_req(struct bios_parser *bp);
  60static void init_external_encoder_control(struct bios_parser *bp);
  61static void init_enable_disp_power_gating(struct bios_parser *bp);
  62static void init_program_clock(struct bios_parser *bp);
  63static void init_set_dce_clock(struct bios_parser *bp);
  64
  65void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
  66{
  67        init_dig_encoder_control(bp);
  68        init_transmitter_control(bp);
  69        init_set_pixel_clock(bp);
  70        init_enable_spread_spectrum_on_ppll(bp);
  71        init_adjust_display_pll(bp);
  72        init_dac_encoder_control(bp);
  73        init_dac_output_control(bp);
  74        init_set_crtc_timing(bp);
  75        init_enable_crtc(bp);
  76        init_enable_crtc_mem_req(bp);
  77        init_program_clock(bp);
  78        init_external_encoder_control(bp);
  79        init_enable_disp_power_gating(bp);
  80        init_set_dce_clock(bp);
  81}
  82
  83static uint32_t bios_cmd_table_para_revision(void *dev,
  84                                             uint32_t index)
  85{
  86        struct amdgpu_device *adev = dev;
  87        uint8_t frev, crev;
  88
  89        if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,
  90                                        index,
  91                                        &frev, &crev))
  92                return crev;
  93        else
  94                return 0;
  95}
  96
  97/*******************************************************************************
  98 ********************************************************************************
  99 **
 100 **                  D I G E N C O D E R C O N T R O L
 101 **
 102 ********************************************************************************
 103 *******************************************************************************/
 104static enum bp_result encoder_control_digx_v3(
 105        struct bios_parser *bp,
 106        struct bp_encoder_control *cntl);
 107
 108static enum bp_result encoder_control_digx_v4(
 109        struct bios_parser *bp,
 110        struct bp_encoder_control *cntl);
 111
 112static enum bp_result encoder_control_digx_v5(
 113        struct bios_parser *bp,
 114        struct bp_encoder_control *cntl);
 115
 116static void init_encoder_control_dig_v1(struct bios_parser *bp);
 117
 118static void init_dig_encoder_control(struct bios_parser *bp)
 119{
 120        uint32_t version =
 121                BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
 122
 123        switch (version) {
 124        case 2:
 125                bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
 126                break;
 127        case 4:
 128                bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
 129                break;
 130
 131        case 5:
 132                bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;
 133                break;
 134
 135        default:
 136                init_encoder_control_dig_v1(bp);
 137                break;
 138        }
 139}
 140
 141static enum bp_result encoder_control_dig_v1(
 142        struct bios_parser *bp,
 143        struct bp_encoder_control *cntl);
 144static enum bp_result encoder_control_dig1_v1(
 145        struct bios_parser *bp,
 146        struct bp_encoder_control *cntl);
 147static enum bp_result encoder_control_dig2_v1(
 148        struct bios_parser *bp,
 149        struct bp_encoder_control *cntl);
 150
 151static void init_encoder_control_dig_v1(struct bios_parser *bp)
 152{
 153        struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
 154
 155        if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
 156                cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
 157        else
 158                cmd_tbl->encoder_control_dig1 = NULL;
 159
 160        if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
 161                cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
 162        else
 163                cmd_tbl->encoder_control_dig2 = NULL;
 164
 165        cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
 166}
 167
 168static enum bp_result encoder_control_dig_v1(
 169        struct bios_parser *bp,
 170        struct bp_encoder_control *cntl)
 171{
 172        enum bp_result result = BP_RESULT_FAILURE;
 173        struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
 174
 175        if (cntl != NULL)
 176                switch (cntl->engine_id) {
 177                case ENGINE_ID_DIGA:
 178                        if (cmd_tbl->encoder_control_dig1 != NULL)
 179                                result =
 180                                        cmd_tbl->encoder_control_dig1(bp, cntl);
 181                        break;
 182                case ENGINE_ID_DIGB:
 183                        if (cmd_tbl->encoder_control_dig2 != NULL)
 184                                result =
 185                                        cmd_tbl->encoder_control_dig2(bp, cntl);
 186                        break;
 187
 188                default:
 189                        break;
 190                }
 191
 192        return result;
 193}
 194
 195static enum bp_result encoder_control_dig1_v1(
 196        struct bios_parser *bp,
 197        struct bp_encoder_control *cntl)
 198{
 199        enum bp_result result = BP_RESULT_FAILURE;
 200        DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
 201
 202        bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
 203
 204        if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
 205                result = BP_RESULT_OK;
 206
 207        return result;
 208}
 209
 210static enum bp_result encoder_control_dig2_v1(
 211        struct bios_parser *bp,
 212        struct bp_encoder_control *cntl)
 213{
 214        enum bp_result result = BP_RESULT_FAILURE;
 215        DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
 216
 217        bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
 218
 219        if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
 220                result = BP_RESULT_OK;
 221
 222        return result;
 223}
 224
 225static enum bp_result encoder_control_digx_v3(
 226        struct bios_parser *bp,
 227        struct bp_encoder_control *cntl)
 228{
 229        enum bp_result result = BP_RESULT_FAILURE;
 230        DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
 231
 232        if (LANE_COUNT_FOUR < cntl->lanes_number)
 233                params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
 234        else
 235                params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
 236
 237        params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
 238
 239        /* We need to convert from KHz units into 10KHz units */
 240        params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
 241        params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 242        params.ucEncoderMode =
 243                        (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
 244                                        cntl->signal,
 245                                        cntl->enable_dp_audio);
 246        params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 247
 248        if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 249                result = BP_RESULT_OK;
 250
 251        return result;
 252}
 253
 254static enum bp_result encoder_control_digx_v4(
 255        struct bios_parser *bp,
 256        struct bp_encoder_control *cntl)
 257{
 258        enum bp_result result = BP_RESULT_FAILURE;
 259        DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
 260
 261        if (LANE_COUNT_FOUR < cntl->lanes_number)
 262                params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
 263        else
 264                params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
 265
 266        params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
 267
 268        /* We need to convert from KHz units into 10KHz units */
 269        params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
 270        params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 271        params.ucEncoderMode =
 272                        (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
 273                                        cntl->signal,
 274                                        cntl->enable_dp_audio));
 275        params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 276
 277        if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 278                result = BP_RESULT_OK;
 279
 280        return result;
 281}
 282
 283static enum bp_result encoder_control_digx_v5(
 284        struct bios_parser *bp,
 285        struct bp_encoder_control *cntl)
 286{
 287        enum bp_result result = BP_RESULT_FAILURE;
 288        ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
 289
 290        params.ucDigId = (uint8_t)(cntl->engine_id);
 291        params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
 292
 293        params.ulPixelClock = cntl->pixel_clock / 10;
 294        params.ucDigMode =
 295                        (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
 296                                        cntl->signal,
 297                                        cntl->enable_dp_audio));
 298        params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 299
 300        switch (cntl->color_depth) {
 301        case COLOR_DEPTH_888:
 302                params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
 303                break;
 304        case COLOR_DEPTH_101010:
 305                params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
 306                break;
 307        case COLOR_DEPTH_121212:
 308                params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
 309                break;
 310        case COLOR_DEPTH_161616:
 311                params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
 312                break;
 313        default:
 314                break;
 315        }
 316
 317        if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
 318                switch (cntl->color_depth) {
 319                case COLOR_DEPTH_101010:
 320                        params.ulPixelClock =
 321                                (params.ulPixelClock * 30) / 24;
 322                        break;
 323                case COLOR_DEPTH_121212:
 324                        params.ulPixelClock =
 325                                (params.ulPixelClock * 36) / 24;
 326                        break;
 327                case COLOR_DEPTH_161616:
 328                        params.ulPixelClock =
 329                                (params.ulPixelClock * 48) / 24;
 330                        break;
 331                default:
 332                        break;
 333                }
 334
 335        if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 336                result = BP_RESULT_OK;
 337
 338        return result;
 339}
 340
 341/*******************************************************************************
 342 ********************************************************************************
 343 **
 344 **                  TRANSMITTER CONTROL
 345 **
 346 ********************************************************************************
 347 *******************************************************************************/
 348
 349static enum bp_result transmitter_control_v2(
 350        struct bios_parser *bp,
 351        struct bp_transmitter_control *cntl);
 352static enum bp_result transmitter_control_v3(
 353        struct bios_parser *bp,
 354        struct bp_transmitter_control *cntl);
 355static enum bp_result transmitter_control_v4(
 356        struct bios_parser *bp,
 357        struct bp_transmitter_control *cntl);
 358static enum bp_result transmitter_control_v1_5(
 359        struct bios_parser *bp,
 360        struct bp_transmitter_control *cntl);
 361static enum bp_result transmitter_control_v1_6(
 362        struct bios_parser *bp,
 363        struct bp_transmitter_control *cntl);
 364
 365static void init_transmitter_control(struct bios_parser *bp)
 366{
 367        uint8_t frev;
 368        uint8_t crev;
 369
 370        if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
 371                        frev, crev) == false)
 372                BREAK_TO_DEBUGGER();
 373        switch (crev) {
 374        case 2:
 375                bp->cmd_tbl.transmitter_control = transmitter_control_v2;
 376                break;
 377        case 3:
 378                bp->cmd_tbl.transmitter_control = transmitter_control_v3;
 379                break;
 380        case 4:
 381                bp->cmd_tbl.transmitter_control = transmitter_control_v4;
 382                break;
 383        case 5:
 384                bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
 385                break;
 386        case 6:
 387                bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
 388                break;
 389        default:
 390                dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
 391                bp->cmd_tbl.transmitter_control = NULL;
 392                break;
 393        }
 394}
 395
 396static enum bp_result transmitter_control_v2(
 397        struct bios_parser *bp,
 398        struct bp_transmitter_control *cntl)
 399{
 400        enum bp_result result = BP_RESULT_FAILURE;
 401        DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
 402        enum connector_id connector_id =
 403                dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
 404
 405        memset(&params, 0, sizeof(params));
 406
 407        switch (cntl->transmitter) {
 408        case TRANSMITTER_UNIPHY_A:
 409        case TRANSMITTER_UNIPHY_B:
 410        case TRANSMITTER_UNIPHY_C:
 411        case TRANSMITTER_UNIPHY_D:
 412        case TRANSMITTER_UNIPHY_E:
 413        case TRANSMITTER_UNIPHY_F:
 414        case TRANSMITTER_TRAVIS_LCD:
 415                break;
 416        default:
 417                return BP_RESULT_BADINPUT;
 418        }
 419
 420        switch (cntl->action) {
 421        case TRANSMITTER_CONTROL_INIT:
 422                if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
 423                                (CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
 424                        /* on INIT this bit should be set according to the
 425                         * phisycal connector
 426                         * Bit0: dual link connector flag
 427                         * =0 connector is single link connector
 428                         * =1 connector is dual link connector
 429                         */
 430                        params.acConfig.fDualLinkConnector = 1;
 431
 432                /* connector object id */
 433                params.usInitInfo =
 434                                cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
 435                break;
 436        case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
 437                /* votage swing and pre-emphsis */
 438                params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
 439                params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
 440                break;
 441        default:
 442                /* if dual-link */
 443                if (LANE_COUNT_FOUR < cntl->lanes_number) {
 444                        /* on ENABLE/DISABLE this bit should be set according to
 445                         * actual timing (number of lanes)
 446                         * Bit0: dual link connector flag
 447                         * =0 connector is single link connector
 448                         * =1 connector is dual link connector
 449                         */
 450                        params.acConfig.fDualLinkConnector = 1;
 451
 452                        /* link rate, half for dual link
 453                         * We need to convert from KHz units into 20KHz units
 454                         */
 455                        params.usPixelClock =
 456                                        cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
 457                } else
 458                        /* link rate, half for dual link
 459                         * We need to convert from KHz units into 10KHz units
 460                         */
 461                        params.usPixelClock =
 462                                        cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 463                break;
 464        }
 465
 466        /* 00 - coherent mode
 467         * 01 - incoherent mode
 468         */
 469
 470        params.acConfig.fCoherentMode = cntl->coherent;
 471
 472        if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
 473                        || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
 474                        || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
 475                /* Bit2: Transmitter Link selection
 476                 * =0 when bit0=0, single link A/C/E, when bit0=1,
 477                 * master link A/C/E
 478                 * =1 when bit0=0, single link B/D/F, when bit0=1,
 479                 * master link B/D/F
 480                 */
 481                params.acConfig.ucLinkSel = 1;
 482
 483        if (ENGINE_ID_DIGB == cntl->engine_id)
 484                /* Bit3: Transmitter data source selection
 485                 * =0 DIGA is data source.
 486                 * =1 DIGB is data source.
 487                 * This bit is only useful when ucAction= ATOM_ENABLE
 488                 */
 489                params.acConfig.ucEncoderSel = 1;
 490
 491        if (CONNECTOR_ID_DISPLAY_PORT == connector_id)
 492                /* Bit4: DP connector flag
 493                 * =0 connector is none-DP connector
 494                 * =1 connector is DP connector
 495                 */
 496                params.acConfig.fDPConnector = 1;
 497
 498        /* Bit[7:6]: Transmitter selection
 499         * =0 UNIPHY_ENCODER: UNIPHYA/B
 500         * =1 UNIPHY1_ENCODER: UNIPHYC/D
 501         * =2 UNIPHY2_ENCODER: UNIPHYE/F
 502         * =3 reserved
 503         */
 504        params.acConfig.ucTransmitterSel =
 505                        (uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
 506                                        cntl->transmitter);
 507
 508        params.ucAction = (uint8_t)cntl->action;
 509
 510        if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 511                result = BP_RESULT_OK;
 512
 513        return result;
 514}
 515
 516static enum bp_result transmitter_control_v3(
 517        struct bios_parser *bp,
 518        struct bp_transmitter_control *cntl)
 519{
 520        enum bp_result result = BP_RESULT_FAILURE;
 521        DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
 522        uint32_t pll_id;
 523        enum connector_id conn_id =
 524                        dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
 525        const struct command_table_helper *cmd = bp->cmd_helper;
 526        bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
 527                                        || (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
 528
 529        memset(&params, 0, sizeof(params));
 530
 531        switch (cntl->transmitter) {
 532        case TRANSMITTER_UNIPHY_A:
 533        case TRANSMITTER_UNIPHY_B:
 534        case TRANSMITTER_UNIPHY_C:
 535        case TRANSMITTER_UNIPHY_D:
 536        case TRANSMITTER_UNIPHY_E:
 537        case TRANSMITTER_UNIPHY_F:
 538        case TRANSMITTER_TRAVIS_LCD:
 539                break;
 540        default:
 541                return BP_RESULT_BADINPUT;
 542        }
 543
 544        if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
 545                return BP_RESULT_BADINPUT;
 546
 547        /* fill information based on the action */
 548        switch (cntl->action) {
 549        case TRANSMITTER_CONTROL_INIT:
 550                if (dual_link_conn) {
 551                        /* on INIT this bit should be set according to the
 552                         * phisycal connector
 553                         * Bit0: dual link connector flag
 554                         * =0 connector is single link connector
 555                         * =1 connector is dual link connector
 556                         */
 557                        params.acConfig.fDualLinkConnector = 1;
 558                }
 559
 560                /* connector object id */
 561                params.usInitInfo =
 562                                cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
 563                break;
 564        case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
 565                /* votage swing and pre-emphsis */
 566                params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
 567                params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
 568                break;
 569        default:
 570                if (dual_link_conn && cntl->multi_path)
 571                        /* on ENABLE/DISABLE this bit should be set according to
 572                         * actual timing (number of lanes)
 573                         * Bit0: dual link connector flag
 574                         * =0 connector is single link connector
 575                         * =1 connector is dual link connector
 576                         */
 577                        params.acConfig.fDualLinkConnector = 1;
 578
 579                /* if dual-link */
 580                if (LANE_COUNT_FOUR < cntl->lanes_number) {
 581                        /* on ENABLE/DISABLE this bit should be set according to
 582                         * actual timing (number of lanes)
 583                         * Bit0: dual link connector flag
 584                         * =0 connector is single link connector
 585                         * =1 connector is dual link connector
 586                         */
 587                        params.acConfig.fDualLinkConnector = 1;
 588
 589                        /* link rate, half for dual link
 590                         * We need to convert from KHz units into 20KHz units
 591                         */
 592                        params.usPixelClock =
 593                                        cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
 594                } else {
 595                        /* link rate, half for dual link
 596                         * We need to convert from KHz units into 10KHz units
 597                         */
 598                        params.usPixelClock =
 599                                        cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 600                }
 601                break;
 602        }
 603
 604        /* 00 - coherent mode
 605         * 01 - incoherent mode
 606         */
 607
 608        params.acConfig.fCoherentMode = cntl->coherent;
 609
 610        if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
 611                || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
 612                || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
 613                /* Bit2: Transmitter Link selection
 614                 * =0 when bit0=0, single link A/C/E, when bit0=1,
 615                 * master link A/C/E
 616                 * =1 when bit0=0, single link B/D/F, when bit0=1,
 617                 * master link B/D/F
 618                 */
 619                params.acConfig.ucLinkSel = 1;
 620
 621        if (ENGINE_ID_DIGB == cntl->engine_id)
 622                /* Bit3: Transmitter data source selection
 623                 * =0 DIGA is data source.
 624                 * =1 DIGB is data source.
 625                 * This bit is only useful when ucAction= ATOM_ENABLE
 626                 */
 627                params.acConfig.ucEncoderSel = 1;
 628
 629        /* Bit[7:6]: Transmitter selection
 630         * =0 UNIPHY_ENCODER: UNIPHYA/B
 631         * =1 UNIPHY1_ENCODER: UNIPHYC/D
 632         * =2 UNIPHY2_ENCODER: UNIPHYE/F
 633         * =3 reserved
 634         */
 635        params.acConfig.ucTransmitterSel =
 636                        (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
 637
 638        params.ucLaneNum = (uint8_t)cntl->lanes_number;
 639
 640        params.acConfig.ucRefClkSource = (uint8_t)pll_id;
 641
 642        params.ucAction = (uint8_t)cntl->action;
 643
 644        if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 645                result = BP_RESULT_OK;
 646
 647        return result;
 648}
 649
 650static enum bp_result transmitter_control_v4(
 651        struct bios_parser *bp,
 652        struct bp_transmitter_control *cntl)
 653{
 654        enum bp_result result = BP_RESULT_FAILURE;
 655        DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
 656        uint32_t ref_clk_src_id;
 657        enum connector_id conn_id =
 658                        dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
 659        const struct command_table_helper *cmd = bp->cmd_helper;
 660
 661        memset(&params, 0, sizeof(params));
 662
 663        switch (cntl->transmitter) {
 664        case TRANSMITTER_UNIPHY_A:
 665        case TRANSMITTER_UNIPHY_B:
 666        case TRANSMITTER_UNIPHY_C:
 667        case TRANSMITTER_UNIPHY_D:
 668        case TRANSMITTER_UNIPHY_E:
 669        case TRANSMITTER_UNIPHY_F:
 670        case TRANSMITTER_TRAVIS_LCD:
 671                break;
 672        default:
 673                return BP_RESULT_BADINPUT;
 674        }
 675
 676        if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
 677                return BP_RESULT_BADINPUT;
 678
 679        switch (cntl->action) {
 680        case TRANSMITTER_CONTROL_INIT:
 681        {
 682                if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
 683                                (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
 684                        /* on INIT this bit should be set according to the
 685                         * phisycal connector
 686                         * Bit0: dual link connector flag
 687                         * =0 connector is single link connector
 688                         * =1 connector is dual link connector
 689                         */
 690                        params.acConfig.fDualLinkConnector = 1;
 691
 692                /* connector object id */
 693                params.usInitInfo =
 694                                cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
 695        }
 696        break;
 697        case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
 698                /* votage swing and pre-emphsis */
 699                params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
 700                params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
 701                break;
 702        default:
 703                if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
 704                                (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
 705                        /* on ENABLE/DISABLE this bit should be set according to
 706                         * actual timing (number of lanes)
 707                         * Bit0: dual link connector flag
 708                         * =0 connector is single link connector
 709                         * =1 connector is dual link connector
 710                         */
 711                        params.acConfig.fDualLinkConnector = 1;
 712
 713                /* if dual-link */
 714                if (LANE_COUNT_FOUR < cntl->lanes_number)
 715                        /* link rate, half for dual link
 716                         * We need to convert from KHz units into 20KHz units
 717                         */
 718                        params.usPixelClock =
 719                                        cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
 720                else {
 721                        /* link rate, half for dual link
 722                         * We need to convert from KHz units into 10KHz units
 723                         */
 724                        params.usPixelClock =
 725                                        cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
 726                }
 727                break;
 728        }
 729
 730        /* 00 - coherent mode
 731         * 01 - incoherent mode
 732         */
 733
 734        params.acConfig.fCoherentMode = cntl->coherent;
 735
 736        if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
 737                || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
 738                || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
 739                /* Bit2: Transmitter Link selection
 740                 * =0 when bit0=0, single link A/C/E, when bit0=1,
 741                 * master link A/C/E
 742                 * =1 when bit0=0, single link B/D/F, when bit0=1,
 743                 * master link B/D/F
 744                 */
 745                params.acConfig.ucLinkSel = 1;
 746
 747        if (ENGINE_ID_DIGB == cntl->engine_id)
 748                /* Bit3: Transmitter data source selection
 749                 * =0 DIGA is data source.
 750                 * =1 DIGB is data source.
 751                 * This bit is only useful when ucAction= ATOM_ENABLE
 752                 */
 753                params.acConfig.ucEncoderSel = 1;
 754
 755        /* Bit[7:6]: Transmitter selection
 756         * =0 UNIPHY_ENCODER: UNIPHYA/B
 757         * =1 UNIPHY1_ENCODER: UNIPHYC/D
 758         * =2 UNIPHY2_ENCODER: UNIPHYE/F
 759         * =3 reserved
 760         */
 761        params.acConfig.ucTransmitterSel =
 762                (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
 763        params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 764        params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
 765        params.ucAction = (uint8_t)(cntl->action);
 766
 767        if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 768                result = BP_RESULT_OK;
 769
 770        return result;
 771}
 772
 773static enum bp_result transmitter_control_v1_5(
 774        struct bios_parser *bp,
 775        struct bp_transmitter_control *cntl)
 776{
 777        enum bp_result result = BP_RESULT_FAILURE;
 778        const struct command_table_helper *cmd = bp->cmd_helper;
 779        DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
 780
 781        memset(&params, 0, sizeof(params));
 782        params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
 783        params.ucAction = (uint8_t)cntl->action;
 784        params.ucLaneNum = (uint8_t)cntl->lanes_number;
 785        params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
 786
 787        params.ucDigMode =
 788                cmd->signal_type_to_atom_dig_mode(cntl->signal);
 789        params.asConfig.ucPhyClkSrcId =
 790                cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
 791        /* 00 - coherent mode */
 792        params.asConfig.ucCoherentMode = cntl->coherent;
 793        params.asConfig.ucHPDSel =
 794                cmd->hpd_sel_to_atom(cntl->hpd_sel);
 795        params.ucDigEncoderSel =
 796                cmd->dig_encoder_sel_to_atom(cntl->engine_id);
 797        params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
 798        params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
 799        /*
 800         * In SI/TN case, caller have to set usPixelClock as following:
 801         * DP mode: usPixelClock = DP_LINK_CLOCK/10
 802         * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
 803         * DVI single link mode: usPixelClock = pixel clock
 804         * DVI dual link mode: usPixelClock = pixel clock
 805         * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
 806         * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
 807         * LVDS mode: usPixelClock = pixel clock
 808         */
 809        if  (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
 810                switch (cntl->color_depth) {
 811                case COLOR_DEPTH_101010:
 812                        params.usSymClock =
 813                                cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
 814                        break;
 815                case COLOR_DEPTH_121212:
 816                        params.usSymClock =
 817                                cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
 818                        break;
 819                case COLOR_DEPTH_161616:
 820                        params.usSymClock =
 821                                cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
 822                        break;
 823                default:
 824                        break;
 825                }
 826        }
 827
 828        if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 829                result = BP_RESULT_OK;
 830
 831        return result;
 832}
 833
 834static enum bp_result transmitter_control_v1_6(
 835        struct bios_parser *bp,
 836        struct bp_transmitter_control *cntl)
 837{
 838        enum bp_result result = BP_RESULT_FAILURE;
 839        const struct command_table_helper *cmd = bp->cmd_helper;
 840        DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
 841
 842        memset(&params, 0, sizeof(params));
 843        params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
 844        params.ucAction = (uint8_t)cntl->action;
 845
 846        if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
 847                params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
 848        else
 849                params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
 850
 851        params.ucLaneNum = (uint8_t)cntl->lanes_number;
 852        params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
 853        params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
 854        params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
 855        params.ulSymClock = cntl->pixel_clock/10;
 856
 857        /*
 858         * In SI/TN case, caller have to set usPixelClock as following:
 859         * DP mode: usPixelClock = DP_LINK_CLOCK/10
 860         * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
 861         * DVI single link mode: usPixelClock = pixel clock
 862         * DVI dual link mode: usPixelClock = pixel clock
 863         * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
 864         * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
 865         * LVDS mode: usPixelClock = pixel clock
 866         */
 867        switch (cntl->signal) {
 868        case SIGNAL_TYPE_HDMI_TYPE_A:
 869                switch (cntl->color_depth) {
 870                case COLOR_DEPTH_101010:
 871                        params.ulSymClock =
 872                                cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
 873                        break;
 874                case COLOR_DEPTH_121212:
 875                        params.ulSymClock =
 876                                cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
 877                        break;
 878                case COLOR_DEPTH_161616:
 879                        params.ulSymClock =
 880                                cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
 881                        break;
 882                default:
 883                        break;
 884                }
 885                break;
 886                default:
 887                        break;
 888        }
 889
 890        if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
 891                result = BP_RESULT_OK;
 892        return result;
 893}
 894
 895/*******************************************************************************
 896 ********************************************************************************
 897 **
 898 **                  SET PIXEL CLOCK
 899 **
 900 ********************************************************************************
 901 *******************************************************************************/
 902
 903static enum bp_result set_pixel_clock_v3(
 904        struct bios_parser *bp,
 905        struct bp_pixel_clock_parameters *bp_params);
 906static enum bp_result set_pixel_clock_v5(
 907        struct bios_parser *bp,
 908        struct bp_pixel_clock_parameters *bp_params);
 909static enum bp_result set_pixel_clock_v6(
 910        struct bios_parser *bp,
 911        struct bp_pixel_clock_parameters *bp_params);
 912static enum bp_result set_pixel_clock_v7(
 913        struct bios_parser *bp,
 914        struct bp_pixel_clock_parameters *bp_params);
 915
 916static void init_set_pixel_clock(struct bios_parser *bp)
 917{
 918        switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
 919        case 3:
 920                bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
 921                break;
 922        case 5:
 923                bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
 924                break;
 925        case 6:
 926                bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
 927                break;
 928        case 7:
 929                bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
 930                break;
 931        default:
 932                dm_output_to_console("Don't have set_pixel_clock for v%d\n",
 933                         BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
 934                bp->cmd_tbl.set_pixel_clock = NULL;
 935                break;
 936        }
 937}
 938
 939static enum bp_result set_pixel_clock_v3(
 940        struct bios_parser *bp,
 941        struct bp_pixel_clock_parameters *bp_params)
 942{
 943        enum bp_result result = BP_RESULT_FAILURE;
 944        PIXEL_CLOCK_PARAMETERS_V3 *params;
 945        SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
 946
 947        memset(&allocation, 0, sizeof(allocation));
 948
 949        if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
 950                allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
 951        else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
 952                allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
 953        else
 954                return BP_RESULT_BADINPUT;
 955
 956        allocation.sPCLKInput.usRefDiv =
 957                        cpu_to_le16((uint16_t)bp_params->reference_divider);
 958        allocation.sPCLKInput.usFbDiv =
 959                        cpu_to_le16((uint16_t)bp_params->feedback_divider);
 960        allocation.sPCLKInput.ucFracFbDiv =
 961                        (uint8_t)bp_params->fractional_feedback_divider;
 962        allocation.sPCLKInput.ucPostDiv =
 963                        (uint8_t)bp_params->pixel_clock_post_divider;
 964
 965        /* We need to convert from 100Hz units into 10KHz units */
 966        allocation.sPCLKInput.usPixelClock =
 967                        cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
 968
 969        params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
 970        params->ucTransmitterId =
 971                        bp->cmd_helper->encoder_id_to_atom(
 972                                        dal_graphics_object_id_get_encoder_id(
 973                                                        bp_params->encoder_object_id));
 974        params->ucEncoderMode =
 975                        (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
 976                                        bp_params->signal_type, false));
 977
 978        if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
 979                params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
 980
 981        if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
 982                params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
 983
 984        if (CONTROLLER_ID_D1 != bp_params->controller_id)
 985                params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
 986
 987        if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
 988                result = BP_RESULT_OK;
 989
 990        return result;
 991}
 992
 993#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
 994/* video bios did not define this: */
 995typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
 996        PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
 997        /* Caller doesn't need to init this portion */
 998        ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
 999} SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
1000#endif
1001
1002#ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
1003/* video bios did not define this: */
1004typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
1005        PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
1006        /* Caller doesn't need to init this portion */
1007        ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1008} SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
1009#endif
1010
1011static enum bp_result set_pixel_clock_v5(
1012        struct bios_parser *bp,
1013        struct bp_pixel_clock_parameters *bp_params)
1014{
1015        enum bp_result result = BP_RESULT_FAILURE;
1016        SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
1017        uint8_t controller_id;
1018        uint32_t pll_id;
1019
1020        memset(&clk, 0, sizeof(clk));
1021
1022        if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1023                        && bp->cmd_helper->controller_id_to_atom(
1024                                        bp_params->controller_id, &controller_id)) {
1025                clk.sPCLKInput.ucCRTC = controller_id;
1026                clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1027                clk.sPCLKInput.ucRefDiv =
1028                                (uint8_t)(bp_params->reference_divider);
1029                clk.sPCLKInput.usFbDiv =
1030                                cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1031                clk.sPCLKInput.ulFbDivDecFrac =
1032                                cpu_to_le32(bp_params->fractional_feedback_divider);
1033                clk.sPCLKInput.ucPostDiv =
1034                                (uint8_t)(bp_params->pixel_clock_post_divider);
1035                clk.sPCLKInput.ucTransmitterID =
1036                                bp->cmd_helper->encoder_id_to_atom(
1037                                                dal_graphics_object_id_get_encoder_id(
1038                                                                bp_params->encoder_object_id));
1039                clk.sPCLKInput.ucEncoderMode =
1040                                (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1041                                                bp_params->signal_type, false);
1042
1043                /* We need to convert from 100Hz units into 10KHz units */
1044                clk.sPCLKInput.usPixelClock =
1045                                cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1046
1047                if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1048                        clk.sPCLKInput.ucMiscInfo |=
1049                                        PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1050
1051                if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1052                        clk.sPCLKInput.ucMiscInfo |=
1053                                        PIXEL_CLOCK_MISC_REF_DIV_SRC;
1054
1055                /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1056                 * =1:30bpp, =2:32bpp
1057                 * driver choose program it itself, i.e. here we program it
1058                 * to 888 by default.
1059                 */
1060
1061                if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1062                        result = BP_RESULT_OK;
1063        }
1064
1065        return result;
1066}
1067
1068static enum bp_result set_pixel_clock_v6(
1069        struct bios_parser *bp,
1070        struct bp_pixel_clock_parameters *bp_params)
1071{
1072        enum bp_result result = BP_RESULT_FAILURE;
1073        SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1074        uint8_t controller_id;
1075        uint32_t pll_id;
1076
1077        memset(&clk, 0, sizeof(clk));
1078
1079        if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1080                        && bp->cmd_helper->controller_id_to_atom(
1081                                        bp_params->controller_id, &controller_id)) {
1082                /* Note: VBIOS still wants to use ucCRTC name which is now
1083                 * 1 byte in ULONG
1084                 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1085                 *{
1086                 * target the pixel clock to drive the CRTC timing.
1087                 * ULONG ulPixelClock:24;
1088                 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1089                 * previous version.
1090                 * ATOM_CRTC1~6, indicate the CRTC controller to
1091                 * ULONG ucCRTC:8;
1092                 * drive the pixel clock. not used for DCPLL case.
1093                 *}CRTC_PIXEL_CLOCK_FREQ;
1094                 *union
1095                 *{
1096                 * pixel clock and CRTC id frequency
1097                 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1098                 * ULONG ulDispEngClkFreq; dispclk frequency
1099                 *};
1100                 */
1101                clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1102                clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1103                clk.sPCLKInput.ucRefDiv =
1104                                (uint8_t) bp_params->reference_divider;
1105                clk.sPCLKInput.usFbDiv =
1106                                cpu_to_le16((uint16_t) bp_params->feedback_divider);
1107                clk.sPCLKInput.ulFbDivDecFrac =
1108                                cpu_to_le32(bp_params->fractional_feedback_divider);
1109                clk.sPCLKInput.ucPostDiv =
1110                                (uint8_t) bp_params->pixel_clock_post_divider;
1111                clk.sPCLKInput.ucTransmitterID =
1112                                bp->cmd_helper->encoder_id_to_atom(
1113                                                dal_graphics_object_id_get_encoder_id(
1114                                                                bp_params->encoder_object_id));
1115                clk.sPCLKInput.ucEncoderMode =
1116                                (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1117                                                bp_params->signal_type, false);
1118
1119                /* We need to convert from 100 Hz units into 10KHz units */
1120                clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1121                                cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
1122
1123                if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1124                        clk.sPCLKInput.ucMiscInfo |=
1125                                        PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1126                }
1127
1128                if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1129                        clk.sPCLKInput.ucMiscInfo |=
1130                                        PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1131                }
1132
1133                /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1134                 * 24bpp =1:30bpp, =2:32bpp
1135                 * driver choose program it itself, i.e. here we pass required
1136                 * target rate that includes deep color.
1137                 */
1138
1139                if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1140                        result = BP_RESULT_OK;
1141        }
1142
1143        return result;
1144}
1145
1146static enum bp_result set_pixel_clock_v7(
1147        struct bios_parser *bp,
1148        struct bp_pixel_clock_parameters *bp_params)
1149{
1150        enum bp_result result = BP_RESULT_FAILURE;
1151        PIXEL_CLOCK_PARAMETERS_V7 clk;
1152        uint8_t controller_id;
1153        uint32_t pll_id;
1154
1155        memset(&clk, 0, sizeof(clk));
1156
1157        if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1158                        && bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1159                /* Note: VBIOS still wants to use ucCRTC name which is now
1160                 * 1 byte in ULONG
1161                 *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1162                 *{
1163                 * target the pixel clock to drive the CRTC timing.
1164                 * ULONG ulPixelClock:24;
1165                 * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1166                 * previous version.
1167                 * ATOM_CRTC1~6, indicate the CRTC controller to
1168                 * ULONG ucCRTC:8;
1169                 * drive the pixel clock. not used for DCPLL case.
1170                 *}CRTC_PIXEL_CLOCK_FREQ;
1171                 *union
1172                 *{
1173                 * pixel clock and CRTC id frequency
1174                 * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1175                 * ULONG ulDispEngClkFreq; dispclk frequency
1176                 *};
1177                 */
1178                clk.ucCRTC = controller_id;
1179                clk.ucPpll = (uint8_t) pll_id;
1180                clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1181                clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1182
1183                clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
1184
1185                clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1186
1187                if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1188                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1189
1190                if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1191                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1192
1193                if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1194                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1195
1196                if (bp_params->flags.SUPPORT_YUV_420)
1197                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1198
1199                if (bp_params->flags.SET_XTALIN_REF_SRC)
1200                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1201
1202                if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1203                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1204
1205                if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1206                        clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1207
1208                if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1209                        result = BP_RESULT_OK;
1210        }
1211        return result;
1212}
1213
1214/*******************************************************************************
1215 ********************************************************************************
1216 **
1217 **                  ENABLE PIXEL CLOCK SS
1218 **
1219 ********************************************************************************
1220 *******************************************************************************/
1221static enum bp_result enable_spread_spectrum_on_ppll_v1(
1222        struct bios_parser *bp,
1223        struct bp_spread_spectrum_parameters *bp_params,
1224        bool enable);
1225static enum bp_result enable_spread_spectrum_on_ppll_v2(
1226        struct bios_parser *bp,
1227        struct bp_spread_spectrum_parameters *bp_params,
1228        bool enable);
1229static enum bp_result enable_spread_spectrum_on_ppll_v3(
1230        struct bios_parser *bp,
1231        struct bp_spread_spectrum_parameters *bp_params,
1232        bool enable);
1233
1234static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1235{
1236        switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1237        case 1:
1238                bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1239                                enable_spread_spectrum_on_ppll_v1;
1240                break;
1241        case 2:
1242                bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1243                                enable_spread_spectrum_on_ppll_v2;
1244                break;
1245        case 3:
1246                bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1247                                enable_spread_spectrum_on_ppll_v3;
1248                break;
1249        default:
1250                dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1251                         BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1252                bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1253                break;
1254        }
1255}
1256
1257static enum bp_result enable_spread_spectrum_on_ppll_v1(
1258        struct bios_parser *bp,
1259        struct bp_spread_spectrum_parameters *bp_params,
1260        bool enable)
1261{
1262        enum bp_result result = BP_RESULT_FAILURE;
1263        ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1264
1265        memset(&params, 0, sizeof(params));
1266
1267        if ((enable == true) && (bp_params->percentage > 0))
1268                params.ucEnable = ATOM_ENABLE;
1269        else
1270                params.ucEnable = ATOM_DISABLE;
1271
1272        params.usSpreadSpectrumPercentage =
1273                        cpu_to_le16((uint16_t)bp_params->percentage);
1274        params.ucSpreadSpectrumStep =
1275                        (uint8_t)bp_params->ver1.step;
1276        params.ucSpreadSpectrumDelay =
1277                        (uint8_t)bp_params->ver1.delay;
1278        /* convert back to unit of 10KHz */
1279        params.ucSpreadSpectrumRange =
1280                        (uint8_t)(bp_params->ver1.range / 10000);
1281
1282        if (bp_params->flags.EXTERNAL_SS)
1283                params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1284
1285        if (bp_params->flags.CENTER_SPREAD)
1286                params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1287
1288        if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1289                params.ucPpll = ATOM_PPLL1;
1290        else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1291                params.ucPpll = ATOM_PPLL2;
1292        else
1293                BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1294
1295        if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1296                result = BP_RESULT_OK;
1297
1298        return result;
1299}
1300
1301static enum bp_result enable_spread_spectrum_on_ppll_v2(
1302        struct bios_parser *bp,
1303        struct bp_spread_spectrum_parameters *bp_params,
1304        bool enable)
1305{
1306        enum bp_result result = BP_RESULT_FAILURE;
1307        ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1308
1309        memset(&params, 0, sizeof(params));
1310
1311        if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1312                params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1313        else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1314                params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1315        else
1316                BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1317
1318        if ((enable == true) && (bp_params->percentage > 0)) {
1319                params.ucEnable = ATOM_ENABLE;
1320
1321                params.usSpreadSpectrumPercentage =
1322                                cpu_to_le16((uint16_t)(bp_params->percentage));
1323                params.usSpreadSpectrumStep =
1324                                cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1325
1326                if (bp_params->flags.EXTERNAL_SS)
1327                        params.ucSpreadSpectrumType |=
1328                                        ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1329
1330                if (bp_params->flags.CENTER_SPREAD)
1331                        params.ucSpreadSpectrumType |=
1332                                        ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1333
1334                /* Both amounts need to be left shifted first before bit
1335                 * comparison. Otherwise, the result will always be zero here
1336                 */
1337                params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1338                                ((bp_params->ds.feedback_amount <<
1339                                                ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1340                                                ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1341                                                ((bp_params->ds.nfrac_amount <<
1342                                                                ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1343                                                                ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1344        } else
1345                params.ucEnable = ATOM_DISABLE;
1346
1347        if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1348                result = BP_RESULT_OK;
1349
1350        return result;
1351}
1352
1353static enum bp_result enable_spread_spectrum_on_ppll_v3(
1354        struct bios_parser *bp,
1355        struct bp_spread_spectrum_parameters *bp_params,
1356        bool enable)
1357{
1358        enum bp_result result = BP_RESULT_FAILURE;
1359        ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1360
1361        memset(&params, 0, sizeof(params));
1362
1363        switch (bp_params->pll_id) {
1364        case CLOCK_SOURCE_ID_PLL0:
1365                /* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1366                 * not for SI display clock.
1367                 */
1368                params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1369                break;
1370        case CLOCK_SOURCE_ID_PLL1:
1371                params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1372                break;
1373
1374        case CLOCK_SOURCE_ID_PLL2:
1375                params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1376                break;
1377
1378        case CLOCK_SOURCE_ID_DCPLL:
1379                params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1380                break;
1381
1382        default:
1383                BREAK_TO_DEBUGGER();
1384                /* Unexpected PLL value!! */
1385                return result;
1386        }
1387
1388        if (enable == true) {
1389                params.ucEnable = ATOM_ENABLE;
1390
1391                params.usSpreadSpectrumAmountFrac =
1392                                cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1393                params.usSpreadSpectrumStep =
1394                                cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1395
1396                if (bp_params->flags.EXTERNAL_SS)
1397                        params.ucSpreadSpectrumType |=
1398                                        ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1399                if (bp_params->flags.CENTER_SPREAD)
1400                        params.ucSpreadSpectrumType |=
1401                                        ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1402
1403                /* Both amounts need to be left shifted first before bit
1404                 * comparison. Otherwise, the result will always be zero here
1405                 */
1406                params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1407                                ((bp_params->ds.feedback_amount <<
1408                                                ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1409                                                ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1410                                                ((bp_params->ds.nfrac_amount <<
1411                                                                ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1412                                                                ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1413        } else
1414                params.ucEnable = ATOM_DISABLE;
1415
1416        if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1417                result = BP_RESULT_OK;
1418
1419        return result;
1420}
1421
1422/*******************************************************************************
1423 ********************************************************************************
1424 **
1425 **                  ADJUST DISPLAY PLL
1426 **
1427 ********************************************************************************
1428 *******************************************************************************/
1429
1430static enum bp_result adjust_display_pll_v2(
1431        struct bios_parser *bp,
1432        struct bp_adjust_pixel_clock_parameters *bp_params);
1433static enum bp_result adjust_display_pll_v3(
1434        struct bios_parser *bp,
1435        struct bp_adjust_pixel_clock_parameters *bp_params);
1436
1437static void init_adjust_display_pll(struct bios_parser *bp)
1438{
1439        switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1440        case 2:
1441                bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1442                break;
1443        case 3:
1444                bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1445                break;
1446        default:
1447                dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1448                         BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1449                bp->cmd_tbl.adjust_display_pll = NULL;
1450                break;
1451        }
1452}
1453
1454static enum bp_result adjust_display_pll_v2(
1455        struct bios_parser *bp,
1456        struct bp_adjust_pixel_clock_parameters *bp_params)
1457{
1458        enum bp_result result = BP_RESULT_FAILURE;
1459        ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1460
1461        /* We need to convert from KHz units into 10KHz units and then convert
1462         * output pixel clock back 10KHz-->KHz */
1463        uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1464
1465        params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1466        params.ucTransmitterID =
1467                        bp->cmd_helper->encoder_id_to_atom(
1468                                        dal_graphics_object_id_get_encoder_id(
1469                                                        bp_params->encoder_object_id));
1470        params.ucEncodeMode =
1471                        (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1472                                        bp_params->signal_type, false);
1473        return result;
1474}
1475
1476static enum bp_result adjust_display_pll_v3(
1477        struct bios_parser *bp,
1478        struct bp_adjust_pixel_clock_parameters *bp_params)
1479{
1480        enum bp_result result = BP_RESULT_FAILURE;
1481        ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1482        uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1483
1484        memset(&params, 0, sizeof(params));
1485
1486        /* We need to convert from KHz units into 10KHz units and then convert
1487         * output pixel clock back 10KHz-->KHz */
1488        params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1489        params.sInput.ucTransmitterID =
1490                        bp->cmd_helper->encoder_id_to_atom(
1491                                        dal_graphics_object_id_get_encoder_id(
1492                                                        bp_params->encoder_object_id));
1493        params.sInput.ucEncodeMode =
1494                        (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1495                                        bp_params->signal_type, false);
1496
1497        if (bp_params->ss_enable == true)
1498                params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1499
1500        if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1501                params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1502
1503        if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1504                /* Convert output pixel clock back 10KHz-->KHz: multiply
1505                 * original pixel clock in KHz by ratio
1506                 * [output pxlClk/input pxlClk] */
1507                uint64_t pixel_clk_10_khz_out =
1508                                (uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1509                uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1510
1511                if (pixel_clk_10_kHz_in != 0) {
1512                        bp_params->adjusted_pixel_clock =
1513                                        div_u64(pixel_clk * pixel_clk_10_khz_out,
1514                                                        pixel_clk_10_kHz_in);
1515                } else {
1516                        bp_params->adjusted_pixel_clock = 0;
1517                        BREAK_TO_DEBUGGER();
1518                }
1519
1520                bp_params->reference_divider = params.sOutput.ucRefDiv;
1521                bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1522
1523                result = BP_RESULT_OK;
1524        }
1525
1526        return result;
1527}
1528
1529/*******************************************************************************
1530 ********************************************************************************
1531 **
1532 **                  DAC ENCODER CONTROL
1533 **
1534 ********************************************************************************
1535 *******************************************************************************/
1536
1537static enum bp_result dac1_encoder_control_v1(
1538        struct bios_parser *bp,
1539        bool enable,
1540        uint32_t pixel_clock,
1541        uint8_t dac_standard);
1542static enum bp_result dac2_encoder_control_v1(
1543        struct bios_parser *bp,
1544        bool enable,
1545        uint32_t pixel_clock,
1546        uint8_t dac_standard);
1547
1548static void init_dac_encoder_control(struct bios_parser *bp)
1549{
1550        switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1551        case 1:
1552                bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1553                break;
1554        default:
1555                bp->cmd_tbl.dac1_encoder_control = NULL;
1556                break;
1557        }
1558        switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1559        case 1:
1560                bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1561                break;
1562        default:
1563                bp->cmd_tbl.dac2_encoder_control = NULL;
1564                break;
1565        }
1566}
1567
1568static void dac_encoder_control_prepare_params(
1569        DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1570        bool enable,
1571        uint32_t pixel_clock,
1572        uint8_t dac_standard)
1573{
1574        params->ucDacStandard = dac_standard;
1575        if (enable)
1576                params->ucAction = ATOM_ENABLE;
1577        else
1578                params->ucAction = ATOM_DISABLE;
1579
1580        /* We need to convert from KHz units into 10KHz units
1581         * it looks as if the TvControl do not care about pixel clock
1582         */
1583        params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1584}
1585
1586static enum bp_result dac1_encoder_control_v1(
1587        struct bios_parser *bp,
1588        bool enable,
1589        uint32_t pixel_clock,
1590        uint8_t dac_standard)
1591{
1592        enum bp_result result = BP_RESULT_FAILURE;
1593        DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1594
1595        dac_encoder_control_prepare_params(
1596                &params,
1597                enable,
1598                pixel_clock,
1599                dac_standard);
1600
1601        if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1602                result = BP_RESULT_OK;
1603
1604        return result;
1605}
1606
1607static enum bp_result dac2_encoder_control_v1(
1608        struct bios_parser *bp,
1609        bool enable,
1610        uint32_t pixel_clock,
1611        uint8_t dac_standard)
1612{
1613        enum bp_result result = BP_RESULT_FAILURE;
1614        DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1615
1616        dac_encoder_control_prepare_params(
1617                &params,
1618                enable,
1619                pixel_clock,
1620                dac_standard);
1621
1622        if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1623                result = BP_RESULT_OK;
1624
1625        return result;
1626}
1627
1628/*******************************************************************************
1629 ********************************************************************************
1630 **
1631 **                  DAC OUTPUT CONTROL
1632 **
1633 ********************************************************************************
1634 *******************************************************************************/
1635static enum bp_result dac1_output_control_v1(
1636        struct bios_parser *bp,
1637        bool enable);
1638static enum bp_result dac2_output_control_v1(
1639        struct bios_parser *bp,
1640        bool enable);
1641
1642static void init_dac_output_control(struct bios_parser *bp)
1643{
1644        switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
1645        case 1:
1646                bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
1647                break;
1648        default:
1649                bp->cmd_tbl.dac1_output_control = NULL;
1650                break;
1651        }
1652        switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
1653        case 1:
1654                bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
1655                break;
1656        default:
1657                bp->cmd_tbl.dac2_output_control = NULL;
1658                break;
1659        }
1660}
1661
1662static enum bp_result dac1_output_control_v1(
1663        struct bios_parser *bp, bool enable)
1664{
1665        enum bp_result result = BP_RESULT_FAILURE;
1666        DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1667
1668        if (enable)
1669                params.ucAction = ATOM_ENABLE;
1670        else
1671                params.ucAction = ATOM_DISABLE;
1672
1673        if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
1674                result = BP_RESULT_OK;
1675
1676        return result;
1677}
1678
1679static enum bp_result dac2_output_control_v1(
1680        struct bios_parser *bp, bool enable)
1681{
1682        enum bp_result result = BP_RESULT_FAILURE;
1683        DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1684
1685        if (enable)
1686                params.ucAction = ATOM_ENABLE;
1687        else
1688                params.ucAction = ATOM_DISABLE;
1689
1690        if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
1691                result = BP_RESULT_OK;
1692
1693        return result;
1694}
1695
1696/*******************************************************************************
1697 ********************************************************************************
1698 **
1699 **                  SET CRTC TIMING
1700 **
1701 ********************************************************************************
1702 *******************************************************************************/
1703
1704static enum bp_result set_crtc_using_dtd_timing_v3(
1705        struct bios_parser *bp,
1706        struct bp_hw_crtc_timing_parameters *bp_params);
1707static enum bp_result set_crtc_timing_v1(
1708        struct bios_parser *bp,
1709        struct bp_hw_crtc_timing_parameters *bp_params);
1710
1711static void init_set_crtc_timing(struct bios_parser *bp)
1712{
1713        uint32_t dtd_version =
1714                        BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
1715        if (dtd_version > 2)
1716                switch (dtd_version) {
1717                case 3:
1718                        bp->cmd_tbl.set_crtc_timing =
1719                                        set_crtc_using_dtd_timing_v3;
1720                        break;
1721                default:
1722                        dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
1723                                 dtd_version);
1724                        bp->cmd_tbl.set_crtc_timing = NULL;
1725                        break;
1726                }
1727        else
1728                switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
1729                case 1:
1730                        bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
1731                        break;
1732                default:
1733                        dm_output_to_console("Don't have set_crtc_timing for v%d\n",
1734                                 BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
1735                        bp->cmd_tbl.set_crtc_timing = NULL;
1736                        break;
1737                }
1738}
1739
1740static enum bp_result set_crtc_timing_v1(
1741        struct bios_parser *bp,
1742        struct bp_hw_crtc_timing_parameters *bp_params)
1743{
1744        enum bp_result result = BP_RESULT_FAILURE;
1745        SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
1746        uint8_t atom_controller_id;
1747
1748        if (bp->cmd_helper->controller_id_to_atom(
1749                        bp_params->controller_id, &atom_controller_id))
1750                params.ucCRTC = atom_controller_id;
1751
1752        params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
1753        params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
1754        params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
1755        params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
1756        params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
1757        params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
1758        params.usV_SyncStart =
1759                        cpu_to_le16((uint16_t)(bp_params->v_sync_start));
1760        params.usV_SyncWidth =
1761                        cpu_to_le16((uint16_t)(bp_params->v_sync_width));
1762
1763        /* VBIOS does not expect any value except zero into this call, for
1764         * underscan use another entry ProgramOverscan call but when mode
1765         * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
1766         * but when same ,but 60 Hz there is corruption
1767         * DAL1 does not allow the mode 1776x1000@60
1768         */
1769        params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
1770        params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
1771        params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
1772        params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
1773
1774        if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1775                params.susModeMiscInfo.usAccess =
1776                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1777
1778        if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1779                params.susModeMiscInfo.usAccess =
1780                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1781
1782        if (bp_params->flags.INTERLACE) {
1783                params.susModeMiscInfo.usAccess =
1784                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1785
1786                /* original DAL code has this condition to apply tis for
1787                 * non-TV/CV only due to complex MV testing for possible
1788                 * impact
1789                 * if (pACParameters->signal != SignalType_YPbPr &&
1790                 *  pACParameters->signal != SignalType_Composite &&
1791                 *  pACParameters->signal != SignalType_SVideo)
1792                 */
1793                /* HW will deduct 0.5 line from 2nd feild.
1794                 * i.e. for 1080i, it is 2 lines for 1st field, 2.5
1795                 * lines for the 2nd feild. we need input as 5 instead
1796                 * of 4, but it is 4 either from Edid data
1797                 * (spec CEA 861) or CEA timing table.
1798                 */
1799                params.usV_SyncStart =
1800                                cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
1801        }
1802
1803        if (bp_params->flags.HORZ_COUNT_BY_TWO)
1804                params.susModeMiscInfo.usAccess =
1805                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1806
1807        if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
1808                result = BP_RESULT_OK;
1809
1810        return result;
1811}
1812
1813static enum bp_result set_crtc_using_dtd_timing_v3(
1814        struct bios_parser *bp,
1815        struct bp_hw_crtc_timing_parameters *bp_params)
1816{
1817        enum bp_result result = BP_RESULT_FAILURE;
1818        SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
1819        uint8_t atom_controller_id;
1820
1821        if (bp->cmd_helper->controller_id_to_atom(
1822                        bp_params->controller_id, &atom_controller_id))
1823                params.ucCRTC = atom_controller_id;
1824
1825        /* bios usH_Size wants h addressable size */
1826        params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
1827        /* bios usH_Blanking_Time wants borders included in blanking */
1828        params.usH_Blanking_Time =
1829                        cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
1830        /* bios usV_Size wants v addressable size */
1831        params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
1832        /* bios usV_Blanking_Time wants borders included in blanking */
1833        params.usV_Blanking_Time =
1834                        cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
1835        /* bios usHSyncOffset is the offset from the end of h addressable,
1836         * our horizontalSyncStart is the offset from the beginning
1837         * of h addressable */
1838        params.usH_SyncOffset =
1839                        cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
1840        params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
1841        /* bios usHSyncOffset is the offset from the end of v addressable,
1842         * our verticalSyncStart is the offset from the beginning of
1843         * v addressable */
1844        params.usV_SyncOffset =
1845                        cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
1846        params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
1847
1848        /* we assume that overscan from original timing does not get bigger
1849         * than 255
1850         * we will program all the borders in the Set CRTC Overscan call below
1851         */
1852
1853        if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1854                params.susModeMiscInfo.usAccess =
1855                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1856
1857        if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1858                params.susModeMiscInfo.usAccess =
1859                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1860
1861        if (bp_params->flags.INTERLACE) {
1862                params.susModeMiscInfo.usAccess =
1863                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1864
1865                /* original DAL code has this condition to apply this
1866                 * for non-TV/CV only
1867                 * due to complex MV testing for possible impact
1868                 * if ( pACParameters->signal != SignalType_YPbPr &&
1869                 *  pACParameters->signal != SignalType_Composite &&
1870                 *  pACParameters->signal != SignalType_SVideo)
1871                 */
1872                {
1873                        /* HW will deduct 0.5 line from 2nd feild.
1874                         * i.e. for 1080i, it is 2 lines for 1st field,
1875                         * 2.5 lines for the 2nd feild. we need input as 5
1876                         * instead of 4.
1877                         * but it is 4 either from Edid data (spec CEA 861)
1878                         * or CEA timing table.
1879                         */
1880                        params.usV_SyncOffset =
1881                                        cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1);
1882
1883                }
1884        }
1885
1886        if (bp_params->flags.HORZ_COUNT_BY_TWO)
1887                params.susModeMiscInfo.usAccess =
1888                                cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1889
1890        if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
1891                result = BP_RESULT_OK;
1892
1893        return result;
1894}
1895
1896/*******************************************************************************
1897 ********************************************************************************
1898 **
1899 **                  ENABLE CRTC
1900 **
1901 ********************************************************************************
1902 *******************************************************************************/
1903
1904static enum bp_result enable_crtc_v1(
1905        struct bios_parser *bp,
1906        enum controller_id controller_id,
1907        bool enable);
1908
1909static void init_enable_crtc(struct bios_parser *bp)
1910{
1911        switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
1912        case 1:
1913                bp->cmd_tbl.enable_crtc = enable_crtc_v1;
1914                break;
1915        default:
1916                dm_output_to_console("Don't have enable_crtc for v%d\n",
1917                         BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
1918                bp->cmd_tbl.enable_crtc = NULL;
1919                break;
1920        }
1921}
1922
1923static enum bp_result enable_crtc_v1(
1924        struct bios_parser *bp,
1925        enum controller_id controller_id,
1926        bool enable)
1927{
1928        bool result = BP_RESULT_FAILURE;
1929        ENABLE_CRTC_PARAMETERS params = {0};
1930        uint8_t id;
1931
1932        if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
1933                params.ucCRTC = id;
1934        else
1935                return BP_RESULT_BADINPUT;
1936
1937        if (enable)
1938                params.ucEnable = ATOM_ENABLE;
1939        else
1940                params.ucEnable = ATOM_DISABLE;
1941
1942        if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
1943                result = BP_RESULT_OK;
1944
1945        return result;
1946}
1947
1948/*******************************************************************************
1949 ********************************************************************************
1950 **
1951 **                  ENABLE CRTC MEM REQ
1952 **
1953 ********************************************************************************
1954 *******************************************************************************/
1955
1956static enum bp_result enable_crtc_mem_req_v1(
1957        struct bios_parser *bp,
1958        enum controller_id controller_id,
1959        bool enable);
1960
1961static void init_enable_crtc_mem_req(struct bios_parser *bp)
1962{
1963        switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
1964        case 1:
1965                bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
1966                break;
1967        default:
1968                bp->cmd_tbl.enable_crtc_mem_req = NULL;
1969                break;
1970        }
1971}
1972
1973static enum bp_result enable_crtc_mem_req_v1(
1974        struct bios_parser *bp,
1975        enum controller_id controller_id,
1976        bool enable)
1977{
1978        bool result = BP_RESULT_BADINPUT;
1979        ENABLE_CRTC_PARAMETERS params = {0};
1980        uint8_t id;
1981
1982        if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
1983                params.ucCRTC = id;
1984
1985                if (enable)
1986                        params.ucEnable = ATOM_ENABLE;
1987                else
1988                        params.ucEnable = ATOM_DISABLE;
1989
1990                if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
1991                        result = BP_RESULT_OK;
1992                else
1993                        result = BP_RESULT_FAILURE;
1994        }
1995
1996        return result;
1997}
1998
1999/*******************************************************************************
2000 ********************************************************************************
2001 **
2002 **                  DISPLAY PLL
2003 **
2004 ********************************************************************************
2005 *******************************************************************************/
2006
2007static enum bp_result program_clock_v5(
2008        struct bios_parser *bp,
2009        struct bp_pixel_clock_parameters *bp_params);
2010static enum bp_result program_clock_v6(
2011        struct bios_parser *bp,
2012        struct bp_pixel_clock_parameters *bp_params);
2013
2014static void init_program_clock(struct bios_parser *bp)
2015{
2016        switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2017        case 5:
2018                bp->cmd_tbl.program_clock = program_clock_v5;
2019                break;
2020        case 6:
2021                bp->cmd_tbl.program_clock = program_clock_v6;
2022                break;
2023        default:
2024                dm_output_to_console("Don't have program_clock for v%d\n",
2025                         BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2026                bp->cmd_tbl.program_clock = NULL;
2027                break;
2028        }
2029}
2030
2031static enum bp_result program_clock_v5(
2032        struct bios_parser *bp,
2033        struct bp_pixel_clock_parameters *bp_params)
2034{
2035        enum bp_result result = BP_RESULT_FAILURE;
2036
2037        SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2038        uint32_t atom_pll_id;
2039
2040        memset(&params, 0, sizeof(params));
2041        if (!bp->cmd_helper->clock_source_id_to_atom(
2042                        bp_params->pll_id, &atom_pll_id)) {
2043                BREAK_TO_DEBUGGER(); /* Invalid Inpute!! */
2044                return BP_RESULT_BADINPUT;
2045        }
2046
2047        /* We need to convert from KHz units into 10KHz units */
2048        params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2049        params.sPCLKInput.usPixelClock =
2050                        cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
2051        params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2052
2053        if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2054                params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2055
2056        if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2057                result = BP_RESULT_OK;
2058
2059        return result;
2060}
2061
2062static enum bp_result program_clock_v6(
2063        struct bios_parser *bp,
2064        struct bp_pixel_clock_parameters *bp_params)
2065{
2066        enum bp_result result = BP_RESULT_FAILURE;
2067
2068        SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2069        uint32_t atom_pll_id;
2070
2071        memset(&params, 0, sizeof(params));
2072
2073        if (!bp->cmd_helper->clock_source_id_to_atom(
2074                        bp_params->pll_id, &atom_pll_id)) {
2075                BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2076                return BP_RESULT_BADINPUT;
2077        }
2078
2079        /* We need to convert from KHz units into 10KHz units */
2080        params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2081        params.sPCLKInput.ulDispEngClkFreq =
2082                        cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
2083
2084        if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2085                params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2086
2087        if (bp_params->flags.SET_DISPCLK_DFS_BYPASS)
2088                params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_DPREFCLK_BYPASS;
2089
2090        if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2091                /* True display clock is returned by VBIOS if DFS bypass
2092                 * is enabled. */
2093                bp_params->dfs_bypass_display_clock =
2094                                (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2095                result = BP_RESULT_OK;
2096        }
2097
2098        return result;
2099}
2100
2101/*******************************************************************************
2102 ********************************************************************************
2103 **
2104 **                  EXTERNAL ENCODER CONTROL
2105 **
2106 ********************************************************************************
2107 *******************************************************************************/
2108
2109static enum bp_result external_encoder_control_v3(
2110        struct bios_parser *bp,
2111        struct bp_external_encoder_control *cntl);
2112
2113static void init_external_encoder_control(
2114        struct bios_parser *bp)
2115{
2116        switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2117        case 3:
2118                bp->cmd_tbl.external_encoder_control =
2119                                external_encoder_control_v3;
2120                break;
2121        default:
2122                bp->cmd_tbl.external_encoder_control = NULL;
2123                break;
2124        }
2125}
2126
2127static enum bp_result external_encoder_control_v3(
2128        struct bios_parser *bp,
2129        struct bp_external_encoder_control *cntl)
2130{
2131        enum bp_result result = BP_RESULT_FAILURE;
2132
2133        /* we need use _PS_Alloc struct */
2134        EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2135        EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2136        struct graphics_object_id encoder;
2137        bool is_input_signal_dp = false;
2138
2139        memset(&params, 0, sizeof(params));
2140
2141        cntl_params = &params.sExtEncoder;
2142
2143        encoder = cntl->encoder_id;
2144
2145        /* check if encoder supports external encoder control table */
2146        switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2147        case ENCODER_ID_EXTERNAL_NUTMEG:
2148        case ENCODER_ID_EXTERNAL_TRAVIS:
2149                is_input_signal_dp = true;
2150                break;
2151
2152        default:
2153                BREAK_TO_DEBUGGER();
2154                return BP_RESULT_BADINPUT;
2155        }
2156
2157        /* Fill information based on the action
2158         *
2159         * Bit[6:4]: indicate external encoder, applied to all functions.
2160         * =0: external encoder1, mapped to external encoder enum id1
2161         * =1: external encoder2, mapped to external encoder enum id2
2162         *
2163         * enum ObjectEnumId
2164         * {
2165         *  EnumId_Unknown = 0,
2166         *  EnumId_1,
2167         *  EnumId_2,
2168         * };
2169         */
2170        cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2171
2172        switch (cntl->action) {
2173        case EXTERNAL_ENCODER_CONTROL_INIT:
2174                /* output display connector type. Only valid in encoder
2175                 * initialization */
2176                cntl_params->usConnectorId =
2177                                cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2178                break;
2179        case EXTERNAL_ENCODER_CONTROL_SETUP:
2180                /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2181                 * 10KHz
2182                 * output display device pixel clock frequency in unit of 10KHz.
2183                 * Only valid in setup and enableoutput
2184                 */
2185                cntl_params->usPixelClock =
2186                                cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2187                /* Indicate display output signal type drive by external
2188                 * encoder, only valid in setup and enableoutput */
2189                cntl_params->ucEncoderMode =
2190                                (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2191                                                cntl->signal, false);
2192
2193                if (is_input_signal_dp) {
2194                        /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2195                         * only valid in encoder setup with DP mode. */
2196                        if (LINK_RATE_HIGH == cntl->link_rate)
2197                                cntl_params->ucConfig |= 1;
2198                        /* output color depth Indicate encoder data bpc format
2199                         * in DP mode, only valid in encoder setup in DP mode.
2200                         */
2201                        cntl_params->ucBitPerColor =
2202                                        (uint8_t)(cntl->color_depth);
2203                }
2204                /* Indicate how many lanes used by external encoder, only valid
2205                 * in encoder setup and enableoutput. */
2206                cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2207                break;
2208        case EXTERNAL_ENCODER_CONTROL_ENABLE:
2209                cntl_params->usPixelClock =
2210                                cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2211                cntl_params->ucEncoderMode =
2212                                (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2213                                                cntl->signal, false);
2214                cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2215                break;
2216        default:
2217                break;
2218        }
2219
2220        cntl_params->ucAction = (uint8_t)cntl->action;
2221
2222        if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2223                result = BP_RESULT_OK;
2224
2225        return result;
2226}
2227
2228/*******************************************************************************
2229 ********************************************************************************
2230 **
2231 **                  ENABLE DISPLAY POWER GATING
2232 **
2233 ********************************************************************************
2234 *******************************************************************************/
2235
2236static enum bp_result enable_disp_power_gating_v2_1(
2237        struct bios_parser *bp,
2238        enum controller_id crtc_id,
2239        enum bp_pipe_control_action action);
2240
2241static void init_enable_disp_power_gating(
2242        struct bios_parser *bp)
2243{
2244        switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2245        case 1:
2246                bp->cmd_tbl.enable_disp_power_gating =
2247                                enable_disp_power_gating_v2_1;
2248                break;
2249        default:
2250                dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2251                         BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2252                bp->cmd_tbl.enable_disp_power_gating = NULL;
2253                break;
2254        }
2255}
2256
2257static enum bp_result enable_disp_power_gating_v2_1(
2258        struct bios_parser *bp,
2259        enum controller_id crtc_id,
2260        enum bp_pipe_control_action action)
2261{
2262        enum bp_result result = BP_RESULT_FAILURE;
2263
2264        ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2265        uint8_t atom_crtc_id;
2266
2267        if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2268                params.ucDispPipeId = atom_crtc_id;
2269        else
2270                return BP_RESULT_BADINPUT;
2271
2272        params.ucEnable =
2273                        bp->cmd_helper->disp_power_gating_action_to_atom(action);
2274
2275        if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2276                result = BP_RESULT_OK;
2277
2278        return result;
2279}
2280
2281/*******************************************************************************
2282 ********************************************************************************
2283 **
2284 **                  SET DCE CLOCK
2285 **
2286 ********************************************************************************
2287 *******************************************************************************/
2288static enum bp_result set_dce_clock_v2_1(
2289        struct bios_parser *bp,
2290        struct bp_set_dce_clock_parameters *bp_params);
2291
2292static void init_set_dce_clock(struct bios_parser *bp)
2293{
2294        switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2295        case 1:
2296                bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2297                break;
2298        default:
2299                dm_output_to_console("Don't have set_dce_clock for v%d\n",
2300                         BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2301                bp->cmd_tbl.set_dce_clock = NULL;
2302                break;
2303        }
2304}
2305
2306static enum bp_result set_dce_clock_v2_1(
2307        struct bios_parser *bp,
2308        struct bp_set_dce_clock_parameters *bp_params)
2309{
2310        enum bp_result result = BP_RESULT_FAILURE;
2311
2312        SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2313        uint32_t atom_pll_id;
2314        uint32_t atom_clock_type;
2315        const struct command_table_helper *cmd = bp->cmd_helper;
2316
2317        memset(&params, 0, sizeof(params));
2318
2319        if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2320                        !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2321                return BP_RESULT_BADINPUT;
2322
2323        params.asParam.ucDCEClkSrc  = atom_pll_id;
2324        params.asParam.ucDCEClkType = atom_clock_type;
2325
2326        if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2327                if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2328                        params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2329
2330                if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2331                        params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2332
2333                if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2334                        params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2335
2336                if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2337                        params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2338        }
2339        else
2340                /* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2341                /* We need to convert from KHz units into 10KHz units */
2342                params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2343
2344        if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2345                /* Convert from 10KHz units back to KHz */
2346                bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2347                result = BP_RESULT_OK;
2348        }
2349
2350        return result;
2351}
2352