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