Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dm_services.h"
0027 #include "amdgpu.h"
0028 #include "atom.h"
0029 
0030 #include "include/bios_parser_interface.h"
0031 
0032 #include "command_table.h"
0033 #include "command_table_helper.h"
0034 #include "bios_parser_helper.h"
0035 #include "bios_parser_types_internal.h"
0036 
0037 #define EXEC_BIOS_CMD_TABLE(command, params)\
0038     (amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
0039         GetIndexIntoMasterTable(COMMAND, command), \
0040         (uint32_t *)&params) == 0)
0041 
0042 #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\
0043     amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \
0044         GetIndexIntoMasterTable(COMMAND, command), &frev, &crev)
0045 
0046 #define BIOS_CMD_TABLE_PARA_REVISION(command)\
0047     bios_cmd_table_para_revision(bp->base.ctx->driver_context, \
0048         GetIndexIntoMasterTable(COMMAND, command))
0049 
0050 static void init_dig_encoder_control(struct bios_parser *bp);
0051 static void init_transmitter_control(struct bios_parser *bp);
0052 static void init_set_pixel_clock(struct bios_parser *bp);
0053 static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp);
0054 static void init_adjust_display_pll(struct bios_parser *bp);
0055 static void init_dac_encoder_control(struct bios_parser *bp);
0056 static void init_dac_output_control(struct bios_parser *bp);
0057 static void init_set_crtc_timing(struct bios_parser *bp);
0058 static void init_enable_crtc(struct bios_parser *bp);
0059 static void init_enable_crtc_mem_req(struct bios_parser *bp);
0060 static void init_external_encoder_control(struct bios_parser *bp);
0061 static void init_enable_disp_power_gating(struct bios_parser *bp);
0062 static void init_program_clock(struct bios_parser *bp);
0063 static void init_set_dce_clock(struct bios_parser *bp);
0064 
0065 void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp)
0066 {
0067     init_dig_encoder_control(bp);
0068     init_transmitter_control(bp);
0069     init_set_pixel_clock(bp);
0070     init_enable_spread_spectrum_on_ppll(bp);
0071     init_adjust_display_pll(bp);
0072     init_dac_encoder_control(bp);
0073     init_dac_output_control(bp);
0074     init_set_crtc_timing(bp);
0075     init_enable_crtc(bp);
0076     init_enable_crtc_mem_req(bp);
0077     init_program_clock(bp);
0078     init_external_encoder_control(bp);
0079     init_enable_disp_power_gating(bp);
0080     init_set_dce_clock(bp);
0081 }
0082 
0083 static uint32_t bios_cmd_table_para_revision(void *dev,
0084                          uint32_t index)
0085 {
0086     struct amdgpu_device *adev = dev;
0087     uint8_t frev, crev;
0088 
0089     if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,
0090                     index,
0091                     &frev, &crev))
0092         return crev;
0093     else
0094         return 0;
0095 }
0096 
0097 /*******************************************************************************
0098  ********************************************************************************
0099  **
0100  **                  D I G E N C O D E R C O N T R O L
0101  **
0102  ********************************************************************************
0103  *******************************************************************************/
0104 static enum bp_result encoder_control_digx_v3(
0105     struct bios_parser *bp,
0106     struct bp_encoder_control *cntl);
0107 
0108 static enum bp_result encoder_control_digx_v4(
0109     struct bios_parser *bp,
0110     struct bp_encoder_control *cntl);
0111 
0112 static enum bp_result encoder_control_digx_v5(
0113     struct bios_parser *bp,
0114     struct bp_encoder_control *cntl);
0115 
0116 static void init_encoder_control_dig_v1(struct bios_parser *bp);
0117 
0118 static void init_dig_encoder_control(struct bios_parser *bp)
0119 {
0120     uint32_t version =
0121         BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl);
0122 
0123     switch (version) {
0124     case 2:
0125         bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;
0126         break;
0127     case 4:
0128         bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;
0129         break;
0130 
0131     case 5:
0132         bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;
0133         break;
0134 
0135     default:
0136         init_encoder_control_dig_v1(bp);
0137         break;
0138     }
0139 }
0140 
0141 static enum bp_result encoder_control_dig_v1(
0142     struct bios_parser *bp,
0143     struct bp_encoder_control *cntl);
0144 static enum bp_result encoder_control_dig1_v1(
0145     struct bios_parser *bp,
0146     struct bp_encoder_control *cntl);
0147 static enum bp_result encoder_control_dig2_v1(
0148     struct bios_parser *bp,
0149     struct bp_encoder_control *cntl);
0150 
0151 static void init_encoder_control_dig_v1(struct bios_parser *bp)
0152 {
0153     struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
0154 
0155     if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))
0156         cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;
0157     else
0158         cmd_tbl->encoder_control_dig1 = NULL;
0159 
0160     if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))
0161         cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;
0162     else
0163         cmd_tbl->encoder_control_dig2 = NULL;
0164 
0165     cmd_tbl->dig_encoder_control = encoder_control_dig_v1;
0166 }
0167 
0168 static enum bp_result encoder_control_dig_v1(
0169     struct bios_parser *bp,
0170     struct bp_encoder_control *cntl)
0171 {
0172     enum bp_result result = BP_RESULT_FAILURE;
0173     struct cmd_tbl *cmd_tbl = &bp->cmd_tbl;
0174 
0175     if (cntl != NULL)
0176         switch (cntl->engine_id) {
0177         case ENGINE_ID_DIGA:
0178             if (cmd_tbl->encoder_control_dig1 != NULL)
0179                 result =
0180                     cmd_tbl->encoder_control_dig1(bp, cntl);
0181             break;
0182         case ENGINE_ID_DIGB:
0183             if (cmd_tbl->encoder_control_dig2 != NULL)
0184                 result =
0185                     cmd_tbl->encoder_control_dig2(bp, cntl);
0186             break;
0187 
0188         default:
0189             break;
0190         }
0191 
0192     return result;
0193 }
0194 
0195 static enum bp_result encoder_control_dig1_v1(
0196     struct bios_parser *bp,
0197     struct bp_encoder_control *cntl)
0198 {
0199     enum bp_result result = BP_RESULT_FAILURE;
0200     DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
0201 
0202     bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
0203 
0204     if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))
0205         result = BP_RESULT_OK;
0206 
0207     return result;
0208 }
0209 
0210 static enum bp_result encoder_control_dig2_v1(
0211     struct bios_parser *bp,
0212     struct bp_encoder_control *cntl)
0213 {
0214     enum bp_result result = BP_RESULT_FAILURE;
0215     DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0};
0216 
0217     bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params);
0218 
0219     if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))
0220         result = BP_RESULT_OK;
0221 
0222     return result;
0223 }
0224 
0225 static enum bp_result encoder_control_digx_v3(
0226     struct bios_parser *bp,
0227     struct bp_encoder_control *cntl)
0228 {
0229     enum bp_result result = BP_RESULT_FAILURE;
0230     DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0};
0231 
0232     if (LANE_COUNT_FOUR < cntl->lanes_number)
0233         params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
0234     else
0235         params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
0236 
0237     params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
0238 
0239     /* We need to convert from KHz units into 10KHz units */
0240     params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
0241     params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
0242     params.ucEncoderMode =
0243             (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
0244                     cntl->signal,
0245                     cntl->enable_dp_audio);
0246     params.ucLaneNum = (uint8_t)(cntl->lanes_number);
0247 
0248     switch (cntl->color_depth) {
0249     case COLOR_DEPTH_888:
0250         params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
0251         break;
0252     case COLOR_DEPTH_101010:
0253         params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
0254         break;
0255     case COLOR_DEPTH_121212:
0256         params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
0257         break;
0258     case COLOR_DEPTH_161616:
0259         params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
0260         break;
0261     default:
0262         break;
0263     }
0264 
0265     if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
0266         result = BP_RESULT_OK;
0267 
0268     return result;
0269 }
0270 
0271 static enum bp_result encoder_control_digx_v4(
0272     struct bios_parser *bp,
0273     struct bp_encoder_control *cntl)
0274 {
0275     enum bp_result result = BP_RESULT_FAILURE;
0276     DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0};
0277 
0278     if (LANE_COUNT_FOUR < cntl->lanes_number)
0279         params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */
0280     else
0281         params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */
0282 
0283     params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id);
0284 
0285     /* We need to convert from KHz units into 10KHz units */
0286     params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
0287     params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
0288     params.ucEncoderMode =
0289             (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
0290                     cntl->signal,
0291                     cntl->enable_dp_audio));
0292     params.ucLaneNum = (uint8_t)(cntl->lanes_number);
0293 
0294     switch (cntl->color_depth) {
0295     case COLOR_DEPTH_888:
0296         params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
0297         break;
0298     case COLOR_DEPTH_101010:
0299         params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
0300         break;
0301     case COLOR_DEPTH_121212:
0302         params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
0303         break;
0304     case COLOR_DEPTH_161616:
0305         params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
0306         break;
0307     default:
0308         break;
0309     }
0310 
0311     if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
0312         result = BP_RESULT_OK;
0313 
0314     return result;
0315 }
0316 
0317 static enum bp_result encoder_control_digx_v5(
0318     struct bios_parser *bp,
0319     struct bp_encoder_control *cntl)
0320 {
0321     enum bp_result result = BP_RESULT_FAILURE;
0322     ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0};
0323 
0324     params.ucDigId = (uint8_t)(cntl->engine_id);
0325     params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);
0326 
0327     params.ulPixelClock = cntl->pixel_clock / 10;
0328     params.ucDigMode =
0329             (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
0330                     cntl->signal,
0331                     cntl->enable_dp_audio));
0332     params.ucLaneNum = (uint8_t)(cntl->lanes_number);
0333 
0334     switch (cntl->color_depth) {
0335     case COLOR_DEPTH_888:
0336         params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
0337         break;
0338     case COLOR_DEPTH_101010:
0339         params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
0340         break;
0341     case COLOR_DEPTH_121212:
0342         params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
0343         break;
0344     case COLOR_DEPTH_161616:
0345         params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
0346         break;
0347     default:
0348         break;
0349     }
0350 
0351     if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
0352         switch (cntl->color_depth) {
0353         case COLOR_DEPTH_101010:
0354             params.ulPixelClock =
0355                 (params.ulPixelClock * 30) / 24;
0356             break;
0357         case COLOR_DEPTH_121212:
0358             params.ulPixelClock =
0359                 (params.ulPixelClock * 36) / 24;
0360             break;
0361         case COLOR_DEPTH_161616:
0362             params.ulPixelClock =
0363                 (params.ulPixelClock * 48) / 24;
0364             break;
0365         default:
0366             break;
0367         }
0368 
0369     if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
0370         result = BP_RESULT_OK;
0371 
0372     return result;
0373 }
0374 
0375 /*******************************************************************************
0376  ********************************************************************************
0377  **
0378  **                  TRANSMITTER CONTROL
0379  **
0380  ********************************************************************************
0381  *******************************************************************************/
0382 
0383 static enum bp_result transmitter_control_v2(
0384     struct bios_parser *bp,
0385     struct bp_transmitter_control *cntl);
0386 static enum bp_result transmitter_control_v3(
0387     struct bios_parser *bp,
0388     struct bp_transmitter_control *cntl);
0389 static enum bp_result transmitter_control_v4(
0390     struct bios_parser *bp,
0391     struct bp_transmitter_control *cntl);
0392 static enum bp_result transmitter_control_v1_5(
0393     struct bios_parser *bp,
0394     struct bp_transmitter_control *cntl);
0395 static enum bp_result transmitter_control_v1_6(
0396     struct bios_parser *bp,
0397     struct bp_transmitter_control *cntl);
0398 
0399 static void init_transmitter_control(struct bios_parser *bp)
0400 {
0401     uint8_t frev;
0402     uint8_t crev;
0403 
0404     if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,
0405             frev, crev) == false)
0406         BREAK_TO_DEBUGGER();
0407     switch (crev) {
0408     case 2:
0409         bp->cmd_tbl.transmitter_control = transmitter_control_v2;
0410         break;
0411     case 3:
0412         bp->cmd_tbl.transmitter_control = transmitter_control_v3;
0413         break;
0414     case 4:
0415         bp->cmd_tbl.transmitter_control = transmitter_control_v4;
0416         break;
0417     case 5:
0418         bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;
0419         break;
0420     case 6:
0421         bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
0422         break;
0423     default:
0424         dm_output_to_console("Don't have transmitter_control for v%d\n", crev);
0425         bp->cmd_tbl.transmitter_control = NULL;
0426         break;
0427     }
0428 }
0429 
0430 static enum bp_result transmitter_control_v2(
0431     struct bios_parser *bp,
0432     struct bp_transmitter_control *cntl)
0433 {
0434     enum bp_result result = BP_RESULT_FAILURE;
0435     DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;
0436     enum connector_id connector_id =
0437         dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
0438 
0439     memset(&params, 0, sizeof(params));
0440 
0441     switch (cntl->transmitter) {
0442     case TRANSMITTER_UNIPHY_A:
0443     case TRANSMITTER_UNIPHY_B:
0444     case TRANSMITTER_UNIPHY_C:
0445     case TRANSMITTER_UNIPHY_D:
0446     case TRANSMITTER_UNIPHY_E:
0447     case TRANSMITTER_UNIPHY_F:
0448     case TRANSMITTER_TRAVIS_LCD:
0449         break;
0450     default:
0451         return BP_RESULT_BADINPUT;
0452     }
0453 
0454     switch (cntl->action) {
0455     case TRANSMITTER_CONTROL_INIT:
0456         if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||
0457                 (CONNECTOR_ID_DUAL_LINK_DVID == connector_id))
0458             /* on INIT this bit should be set according to the
0459              * physical connector
0460              * Bit0: dual link connector flag
0461              * =0 connector is single link connector
0462              * =1 connector is dual link connector
0463              */
0464             params.acConfig.fDualLinkConnector = 1;
0465 
0466         /* connector object id */
0467         params.usInitInfo =
0468                 cpu_to_le16((uint8_t)cntl->connector_obj_id.id);
0469         break;
0470     case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
0471         /* voltage swing and pre-emphsis */
0472         params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
0473         params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
0474         break;
0475     default:
0476         /* if dual-link */
0477         if (LANE_COUNT_FOUR < cntl->lanes_number) {
0478             /* on ENABLE/DISABLE this bit should be set according to
0479              * actual timing (number of lanes)
0480              * Bit0: dual link connector flag
0481              * =0 connector is single link connector
0482              * =1 connector is dual link connector
0483              */
0484             params.acConfig.fDualLinkConnector = 1;
0485 
0486             /* link rate, half for dual link
0487              * We need to convert from KHz units into 20KHz units
0488              */
0489             params.usPixelClock =
0490                     cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
0491         } else
0492             /* link rate, half for dual link
0493              * We need to convert from KHz units into 10KHz units
0494              */
0495             params.usPixelClock =
0496                     cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
0497         break;
0498     }
0499 
0500     /* 00 - coherent mode
0501      * 01 - incoherent mode
0502      */
0503 
0504     params.acConfig.fCoherentMode = cntl->coherent;
0505 
0506     if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
0507             || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
0508             || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
0509         /* Bit2: Transmitter Link selection
0510          * =0 when bit0=0, single link A/C/E, when bit0=1,
0511          * master link A/C/E
0512          * =1 when bit0=0, single link B/D/F, when bit0=1,
0513          * master link B/D/F
0514          */
0515         params.acConfig.ucLinkSel = 1;
0516 
0517     if (ENGINE_ID_DIGB == cntl->engine_id)
0518         /* Bit3: Transmitter data source selection
0519          * =0 DIGA is data source.
0520          * =1 DIGB is data source.
0521          * This bit is only useful when ucAction= ATOM_ENABLE
0522          */
0523         params.acConfig.ucEncoderSel = 1;
0524 
0525     if (CONNECTOR_ID_DISPLAY_PORT == connector_id ||
0526         CONNECTOR_ID_USBC == connector_id)
0527         /* Bit4: DP connector flag
0528          * =0 connector is none-DP connector
0529          * =1 connector is DP connector
0530          */
0531         params.acConfig.fDPConnector = 1;
0532 
0533     /* Bit[7:6]: Transmitter selection
0534      * =0 UNIPHY_ENCODER: UNIPHYA/B
0535      * =1 UNIPHY1_ENCODER: UNIPHYC/D
0536      * =2 UNIPHY2_ENCODER: UNIPHYE/F
0537      * =3 reserved
0538      */
0539     params.acConfig.ucTransmitterSel =
0540             (uint8_t)bp->cmd_helper->transmitter_bp_to_atom(
0541                     cntl->transmitter);
0542 
0543     params.ucAction = (uint8_t)cntl->action;
0544 
0545     if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
0546         result = BP_RESULT_OK;
0547 
0548     return result;
0549 }
0550 
0551 static enum bp_result transmitter_control_v3(
0552     struct bios_parser *bp,
0553     struct bp_transmitter_control *cntl)
0554 {
0555     enum bp_result result = BP_RESULT_FAILURE;
0556     DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 params;
0557     uint32_t pll_id;
0558     enum connector_id conn_id =
0559             dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
0560     const struct command_table_helper *cmd = bp->cmd_helper;
0561     bool dual_link_conn = (CONNECTOR_ID_DUAL_LINK_DVII == conn_id)
0562                     || (CONNECTOR_ID_DUAL_LINK_DVID == conn_id);
0563 
0564     memset(&params, 0, sizeof(params));
0565 
0566     switch (cntl->transmitter) {
0567     case TRANSMITTER_UNIPHY_A:
0568     case TRANSMITTER_UNIPHY_B:
0569     case TRANSMITTER_UNIPHY_C:
0570     case TRANSMITTER_UNIPHY_D:
0571     case TRANSMITTER_UNIPHY_E:
0572     case TRANSMITTER_UNIPHY_F:
0573     case TRANSMITTER_TRAVIS_LCD:
0574         break;
0575     default:
0576         return BP_RESULT_BADINPUT;
0577     }
0578 
0579     if (!cmd->clock_source_id_to_atom(cntl->pll_id, &pll_id))
0580         return BP_RESULT_BADINPUT;
0581 
0582     /* fill information based on the action */
0583     switch (cntl->action) {
0584     case TRANSMITTER_CONTROL_INIT:
0585         if (dual_link_conn) {
0586             /* on INIT this bit should be set according to the
0587              * phisycal connector
0588              * Bit0: dual link connector flag
0589              * =0 connector is single link connector
0590              * =1 connector is dual link connector
0591              */
0592             params.acConfig.fDualLinkConnector = 1;
0593         }
0594 
0595         /* connector object id */
0596         params.usInitInfo =
0597                 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
0598         break;
0599     case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
0600         /* votage swing and pre-emphsis */
0601         params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;
0602         params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;
0603         break;
0604     default:
0605         if (dual_link_conn && cntl->multi_path)
0606             /* on ENABLE/DISABLE this bit should be set according to
0607              * actual timing (number of lanes)
0608              * Bit0: dual link connector flag
0609              * =0 connector is single link connector
0610              * =1 connector is dual link connector
0611              */
0612             params.acConfig.fDualLinkConnector = 1;
0613 
0614         /* if dual-link */
0615         if (LANE_COUNT_FOUR < cntl->lanes_number) {
0616             /* on ENABLE/DISABLE this bit should be set according to
0617              * actual timing (number of lanes)
0618              * Bit0: dual link connector flag
0619              * =0 connector is single link connector
0620              * =1 connector is dual link connector
0621              */
0622             params.acConfig.fDualLinkConnector = 1;
0623 
0624             /* link rate, half for dual link
0625              * We need to convert from KHz units into 20KHz units
0626              */
0627             params.usPixelClock =
0628                     cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
0629         } else {
0630             /* link rate, half for dual link
0631              * We need to convert from KHz units into 10KHz units
0632              */
0633             params.usPixelClock =
0634                     cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
0635         }
0636         break;
0637     }
0638 
0639     /* 00 - coherent mode
0640      * 01 - incoherent mode
0641      */
0642 
0643     params.acConfig.fCoherentMode = cntl->coherent;
0644 
0645     if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
0646         || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
0647         || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
0648         /* Bit2: Transmitter Link selection
0649          * =0 when bit0=0, single link A/C/E, when bit0=1,
0650          * master link A/C/E
0651          * =1 when bit0=0, single link B/D/F, when bit0=1,
0652          * master link B/D/F
0653          */
0654         params.acConfig.ucLinkSel = 1;
0655 
0656     if (ENGINE_ID_DIGB == cntl->engine_id)
0657         /* Bit3: Transmitter data source selection
0658          * =0 DIGA is data source.
0659          * =1 DIGB is data source.
0660          * This bit is only useful when ucAction= ATOM_ENABLE
0661          */
0662         params.acConfig.ucEncoderSel = 1;
0663 
0664     /* Bit[7:6]: Transmitter selection
0665      * =0 UNIPHY_ENCODER: UNIPHYA/B
0666      * =1 UNIPHY1_ENCODER: UNIPHYC/D
0667      * =2 UNIPHY2_ENCODER: UNIPHYE/F
0668      * =3 reserved
0669      */
0670     params.acConfig.ucTransmitterSel =
0671             (uint8_t)cmd->transmitter_bp_to_atom(cntl->transmitter);
0672 
0673     params.ucLaneNum = (uint8_t)cntl->lanes_number;
0674 
0675     params.acConfig.ucRefClkSource = (uint8_t)pll_id;
0676 
0677     params.ucAction = (uint8_t)cntl->action;
0678 
0679     if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
0680         result = BP_RESULT_OK;
0681 
0682     return result;
0683 }
0684 
0685 static enum bp_result transmitter_control_v4(
0686     struct bios_parser *bp,
0687     struct bp_transmitter_control *cntl)
0688 {
0689     enum bp_result result = BP_RESULT_FAILURE;
0690     DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 params;
0691     uint32_t ref_clk_src_id;
0692     enum connector_id conn_id =
0693             dal_graphics_object_id_get_connector_id(cntl->connector_obj_id);
0694     const struct command_table_helper *cmd = bp->cmd_helper;
0695 
0696     memset(&params, 0, sizeof(params));
0697 
0698     switch (cntl->transmitter) {
0699     case TRANSMITTER_UNIPHY_A:
0700     case TRANSMITTER_UNIPHY_B:
0701     case TRANSMITTER_UNIPHY_C:
0702     case TRANSMITTER_UNIPHY_D:
0703     case TRANSMITTER_UNIPHY_E:
0704     case TRANSMITTER_UNIPHY_F:
0705     case TRANSMITTER_TRAVIS_LCD:
0706         break;
0707     default:
0708         return BP_RESULT_BADINPUT;
0709     }
0710 
0711     if (!cmd->clock_source_id_to_ref_clk_src(cntl->pll_id, &ref_clk_src_id))
0712         return BP_RESULT_BADINPUT;
0713 
0714     switch (cntl->action) {
0715     case TRANSMITTER_CONTROL_INIT:
0716     {
0717         if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
0718                 (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
0719             /* on INIT this bit should be set according to the
0720              * phisycal connector
0721              * Bit0: dual link connector flag
0722              * =0 connector is single link connector
0723              * =1 connector is dual link connector
0724              */
0725             params.acConfig.fDualLinkConnector = 1;
0726 
0727         /* connector object id */
0728         params.usInitInfo =
0729                 cpu_to_le16((uint8_t)(cntl->connector_obj_id.id));
0730     }
0731     break;
0732     case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:
0733         /* votage swing and pre-emphsis */
0734         params.asMode.ucLaneSel = (uint8_t)(cntl->lane_select);
0735         params.asMode.ucLaneSet = (uint8_t)(cntl->lane_settings);
0736         break;
0737     default:
0738         if ((CONNECTOR_ID_DUAL_LINK_DVII == conn_id) ||
0739                 (CONNECTOR_ID_DUAL_LINK_DVID == conn_id))
0740             /* on ENABLE/DISABLE this bit should be set according to
0741              * actual timing (number of lanes)
0742              * Bit0: dual link connector flag
0743              * =0 connector is single link connector
0744              * =1 connector is dual link connector
0745              */
0746             params.acConfig.fDualLinkConnector = 1;
0747 
0748         /* if dual-link */
0749         if (LANE_COUNT_FOUR < cntl->lanes_number)
0750             /* link rate, half for dual link
0751              * We need to convert from KHz units into 20KHz units
0752              */
0753             params.usPixelClock =
0754                     cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));
0755         else {
0756             /* link rate, half for dual link
0757              * We need to convert from KHz units into 10KHz units
0758              */
0759             params.usPixelClock =
0760                     cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
0761         }
0762         break;
0763     }
0764 
0765     /* 00 - coherent mode
0766      * 01 - incoherent mode
0767      */
0768 
0769     params.acConfig.fCoherentMode = cntl->coherent;
0770 
0771     if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)
0772         || (TRANSMITTER_UNIPHY_D == cntl->transmitter)
0773         || (TRANSMITTER_UNIPHY_F == cntl->transmitter))
0774         /* Bit2: Transmitter Link selection
0775          * =0 when bit0=0, single link A/C/E, when bit0=1,
0776          * master link A/C/E
0777          * =1 when bit0=0, single link B/D/F, when bit0=1,
0778          * master link B/D/F
0779          */
0780         params.acConfig.ucLinkSel = 1;
0781 
0782     if (ENGINE_ID_DIGB == cntl->engine_id)
0783         /* Bit3: Transmitter data source selection
0784          * =0 DIGA is data source.
0785          * =1 DIGB is data source.
0786          * This bit is only useful when ucAction= ATOM_ENABLE
0787          */
0788         params.acConfig.ucEncoderSel = 1;
0789 
0790     /* Bit[7:6]: Transmitter selection
0791      * =0 UNIPHY_ENCODER: UNIPHYA/B
0792      * =1 UNIPHY1_ENCODER: UNIPHYC/D
0793      * =2 UNIPHY2_ENCODER: UNIPHYE/F
0794      * =3 reserved
0795      */
0796     params.acConfig.ucTransmitterSel =
0797         (uint8_t)(cmd->transmitter_bp_to_atom(cntl->transmitter));
0798     params.ucLaneNum = (uint8_t)(cntl->lanes_number);
0799     params.acConfig.ucRefClkSource = (uint8_t)(ref_clk_src_id);
0800     params.ucAction = (uint8_t)(cntl->action);
0801 
0802     if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
0803         result = BP_RESULT_OK;
0804 
0805     return result;
0806 }
0807 
0808 static enum bp_result transmitter_control_v1_5(
0809     struct bios_parser *bp,
0810     struct bp_transmitter_control *cntl)
0811 {
0812     enum bp_result result = BP_RESULT_FAILURE;
0813     const struct command_table_helper *cmd = bp->cmd_helper;
0814     DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 params;
0815 
0816     memset(&params, 0, sizeof(params));
0817     params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
0818     params.ucAction = (uint8_t)cntl->action;
0819     params.ucLaneNum = (uint8_t)cntl->lanes_number;
0820     params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
0821 
0822     params.ucDigMode =
0823         cmd->signal_type_to_atom_dig_mode(cntl->signal);
0824     params.asConfig.ucPhyClkSrcId =
0825         cmd->clock_source_id_to_atom_phy_clk_src_id(cntl->pll_id);
0826     /* 00 - coherent mode */
0827     params.asConfig.ucCoherentMode = cntl->coherent;
0828     params.asConfig.ucHPDSel =
0829         cmd->hpd_sel_to_atom(cntl->hpd_sel);
0830     params.ucDigEncoderSel =
0831         cmd->dig_encoder_sel_to_atom(cntl->engine_id);
0832     params.ucDPLaneSet = (uint8_t) cntl->lane_settings;
0833     params.usSymClock = cpu_to_le16((uint16_t) (cntl->pixel_clock / 10));
0834     /*
0835      * In SI/TN case, caller have to set usPixelClock as following:
0836      * DP mode: usPixelClock = DP_LINK_CLOCK/10
0837      * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
0838      * DVI single link mode: usPixelClock = pixel clock
0839      * DVI dual link mode: usPixelClock = pixel clock
0840      * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
0841      * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
0842      * LVDS mode: usPixelClock = pixel clock
0843      */
0844     if  (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
0845         switch (cntl->color_depth) {
0846         case COLOR_DEPTH_101010:
0847             params.usSymClock =
0848                 cpu_to_le16((le16_to_cpu(params.usSymClock) * 30) / 24);
0849             break;
0850         case COLOR_DEPTH_121212:
0851             params.usSymClock =
0852                 cpu_to_le16((le16_to_cpu(params.usSymClock) * 36) / 24);
0853             break;
0854         case COLOR_DEPTH_161616:
0855             params.usSymClock =
0856                 cpu_to_le16((le16_to_cpu(params.usSymClock) * 48) / 24);
0857             break;
0858         default:
0859             break;
0860         }
0861     }
0862 
0863     if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
0864         result = BP_RESULT_OK;
0865 
0866     return result;
0867 }
0868 
0869 static enum bp_result transmitter_control_v1_6(
0870     struct bios_parser *bp,
0871     struct bp_transmitter_control *cntl)
0872 {
0873     enum bp_result result = BP_RESULT_FAILURE;
0874     const struct command_table_helper *cmd = bp->cmd_helper;
0875     DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 params;
0876 
0877     memset(&params, 0, sizeof(params));
0878     params.ucPhyId = cmd->phy_id_to_atom(cntl->transmitter);
0879     params.ucAction = (uint8_t)cntl->action;
0880 
0881     if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
0882         params.ucDPLaneSet = (uint8_t)cntl->lane_settings;
0883     else
0884         params.ucDigMode = cmd->signal_type_to_atom_dig_mode(cntl->signal);
0885 
0886     params.ucLaneNum = (uint8_t)cntl->lanes_number;
0887     params.ucHPDSel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
0888     params.ucDigEncoderSel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
0889     params.ucConnObjId = (uint8_t)cntl->connector_obj_id.id;
0890     params.ulSymClock = cntl->pixel_clock/10;
0891 
0892     /*
0893      * In SI/TN case, caller have to set usPixelClock as following:
0894      * DP mode: usPixelClock = DP_LINK_CLOCK/10
0895      * (DP_LINK_CLOCK = 1.62GHz, 2.7GHz, 5.4GHz)
0896      * DVI single link mode: usPixelClock = pixel clock
0897      * DVI dual link mode: usPixelClock = pixel clock
0898      * HDMI mode: usPixelClock = pixel clock * deep_color_ratio
0899      * (=1: 8bpp, =1.25: 10bpp, =1.5:12bpp, =2: 16bpp)
0900      * LVDS mode: usPixelClock = pixel clock
0901      */
0902     switch (cntl->signal) {
0903     case SIGNAL_TYPE_HDMI_TYPE_A:
0904         switch (cntl->color_depth) {
0905         case COLOR_DEPTH_101010:
0906             params.ulSymClock =
0907                 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 30) / 24);
0908             break;
0909         case COLOR_DEPTH_121212:
0910             params.ulSymClock =
0911                 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 36) / 24);
0912             break;
0913         case COLOR_DEPTH_161616:
0914             params.ulSymClock =
0915                 cpu_to_le16((le16_to_cpu(params.ulSymClock) * 48) / 24);
0916             break;
0917         default:
0918             break;
0919         }
0920         break;
0921         default:
0922             break;
0923     }
0924 
0925     if (EXEC_BIOS_CMD_TABLE(UNIPHYTransmitterControl, params))
0926         result = BP_RESULT_OK;
0927     return result;
0928 }
0929 
0930 /*******************************************************************************
0931  ********************************************************************************
0932  **
0933  **                  SET PIXEL CLOCK
0934  **
0935  ********************************************************************************
0936  *******************************************************************************/
0937 
0938 static enum bp_result set_pixel_clock_v3(
0939     struct bios_parser *bp,
0940     struct bp_pixel_clock_parameters *bp_params);
0941 static enum bp_result set_pixel_clock_v5(
0942     struct bios_parser *bp,
0943     struct bp_pixel_clock_parameters *bp_params);
0944 static enum bp_result set_pixel_clock_v6(
0945     struct bios_parser *bp,
0946     struct bp_pixel_clock_parameters *bp_params);
0947 static enum bp_result set_pixel_clock_v7(
0948     struct bios_parser *bp,
0949     struct bp_pixel_clock_parameters *bp_params);
0950 
0951 static void init_set_pixel_clock(struct bios_parser *bp)
0952 {
0953     switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
0954     case 3:
0955         bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v3;
0956         break;
0957     case 5:
0958         bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v5;
0959         break;
0960     case 6:
0961         bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v6;
0962         break;
0963     case 7:
0964         bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
0965         break;
0966     default:
0967         dm_output_to_console("Don't have set_pixel_clock for v%d\n",
0968              BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
0969         bp->cmd_tbl.set_pixel_clock = NULL;
0970         break;
0971     }
0972 }
0973 
0974 static enum bp_result set_pixel_clock_v3(
0975     struct bios_parser *bp,
0976     struct bp_pixel_clock_parameters *bp_params)
0977 {
0978     enum bp_result result = BP_RESULT_FAILURE;
0979     PIXEL_CLOCK_PARAMETERS_V3 *params;
0980     SET_PIXEL_CLOCK_PS_ALLOCATION allocation;
0981 
0982     memset(&allocation, 0, sizeof(allocation));
0983 
0984     if (CLOCK_SOURCE_ID_PLL1 == bp_params->pll_id)
0985         allocation.sPCLKInput.ucPpll = ATOM_PPLL1;
0986     else if (CLOCK_SOURCE_ID_PLL2 == bp_params->pll_id)
0987         allocation.sPCLKInput.ucPpll = ATOM_PPLL2;
0988     else
0989         return BP_RESULT_BADINPUT;
0990 
0991     allocation.sPCLKInput.usRefDiv =
0992             cpu_to_le16((uint16_t)bp_params->reference_divider);
0993     allocation.sPCLKInput.usFbDiv =
0994             cpu_to_le16((uint16_t)bp_params->feedback_divider);
0995     allocation.sPCLKInput.ucFracFbDiv =
0996             (uint8_t)bp_params->fractional_feedback_divider;
0997     allocation.sPCLKInput.ucPostDiv =
0998             (uint8_t)bp_params->pixel_clock_post_divider;
0999 
1000     /* We need to convert from 100Hz units into 10KHz units */
1001     allocation.sPCLKInput.usPixelClock =
1002             cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1003 
1004     params = (PIXEL_CLOCK_PARAMETERS_V3 *)&allocation.sPCLKInput;
1005     params->ucTransmitterId =
1006             bp->cmd_helper->encoder_id_to_atom(
1007                     dal_graphics_object_id_get_encoder_id(
1008                             bp_params->encoder_object_id));
1009     params->ucEncoderMode =
1010             (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
1011                     bp_params->signal_type, false));
1012 
1013     if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1014         params->ucMiscInfo |= PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1015 
1016     if (bp_params->flags.USE_E_CLOCK_AS_SOURCE_FOR_D_CLOCK)
1017         params->ucMiscInfo |= PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK;
1018 
1019     if (CONTROLLER_ID_D1 != bp_params->controller_id)
1020         params->ucMiscInfo |= PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2;
1021 
1022     if (EXEC_BIOS_CMD_TABLE(SetPixelClock, allocation))
1023         result = BP_RESULT_OK;
1024 
1025     return result;
1026 }
1027 
1028 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V5
1029 /* video bios did not define this: */
1030 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V5 {
1031     PIXEL_CLOCK_PARAMETERS_V5 sPCLKInput;
1032     /* Caller doesn't need to init this portion */
1033     ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1034 } SET_PIXEL_CLOCK_PS_ALLOCATION_V5;
1035 #endif
1036 
1037 #ifndef SET_PIXEL_CLOCK_PS_ALLOCATION_V6
1038 /* video bios did not define this: */
1039 typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION_V6 {
1040     PIXEL_CLOCK_PARAMETERS_V6 sPCLKInput;
1041     /* Caller doesn't need to init this portion */
1042     ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved;
1043 } SET_PIXEL_CLOCK_PS_ALLOCATION_V6;
1044 #endif
1045 
1046 static enum bp_result set_pixel_clock_v5(
1047     struct bios_parser *bp,
1048     struct bp_pixel_clock_parameters *bp_params)
1049 {
1050     enum bp_result result = BP_RESULT_FAILURE;
1051     SET_PIXEL_CLOCK_PS_ALLOCATION_V5 clk;
1052     uint8_t controller_id;
1053     uint32_t pll_id;
1054 
1055     memset(&clk, 0, sizeof(clk));
1056 
1057     if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1058             && bp->cmd_helper->controller_id_to_atom(
1059                     bp_params->controller_id, &controller_id)) {
1060         clk.sPCLKInput.ucCRTC = controller_id;
1061         clk.sPCLKInput.ucPpll = (uint8_t)pll_id;
1062         clk.sPCLKInput.ucRefDiv =
1063                 (uint8_t)(bp_params->reference_divider);
1064         clk.sPCLKInput.usFbDiv =
1065                 cpu_to_le16((uint16_t)(bp_params->feedback_divider));
1066         clk.sPCLKInput.ulFbDivDecFrac =
1067                 cpu_to_le32(bp_params->fractional_feedback_divider);
1068         clk.sPCLKInput.ucPostDiv =
1069                 (uint8_t)(bp_params->pixel_clock_post_divider);
1070         clk.sPCLKInput.ucTransmitterID =
1071                 bp->cmd_helper->encoder_id_to_atom(
1072                         dal_graphics_object_id_get_encoder_id(
1073                                 bp_params->encoder_object_id));
1074         clk.sPCLKInput.ucEncoderMode =
1075                 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1076                         bp_params->signal_type, false);
1077 
1078         /* We need to convert from 100Hz units into 10KHz units */
1079         clk.sPCLKInput.usPixelClock =
1080                 cpu_to_le16((uint16_t)(bp_params->target_pixel_clock_100hz / 100));
1081 
1082         if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1083             clk.sPCLKInput.ucMiscInfo |=
1084                     PIXEL_CLOCK_MISC_FORCE_PROG_PPLL;
1085 
1086         if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1087             clk.sPCLKInput.ucMiscInfo |=
1088                     PIXEL_CLOCK_MISC_REF_DIV_SRC;
1089 
1090         /* clkV5.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0: 24bpp
1091          * =1:30bpp, =2:32bpp
1092          * driver choose program it itself, i.e. here we program it
1093          * to 888 by default.
1094          */
1095         if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1096             switch (bp_params->color_depth) {
1097             case TRANSMITTER_COLOR_DEPTH_30:
1098                 /* yes this is correct, the atom define is wrong */
1099                 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
1100                 break;
1101             case TRANSMITTER_COLOR_DEPTH_36:
1102                 /* yes this is correct, the atom define is wrong */
1103                 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
1104                 break;
1105             default:
1106                 break;
1107             }
1108 
1109         if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1110             result = BP_RESULT_OK;
1111     }
1112 
1113     return result;
1114 }
1115 
1116 static enum bp_result set_pixel_clock_v6(
1117     struct bios_parser *bp,
1118     struct bp_pixel_clock_parameters *bp_params)
1119 {
1120     enum bp_result result = BP_RESULT_FAILURE;
1121     SET_PIXEL_CLOCK_PS_ALLOCATION_V6 clk;
1122     uint8_t controller_id;
1123     uint32_t pll_id;
1124 
1125     memset(&clk, 0, sizeof(clk));
1126 
1127     if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1128             && bp->cmd_helper->controller_id_to_atom(
1129                     bp_params->controller_id, &controller_id)) {
1130         /* Note: VBIOS still wants to use ucCRTC name which is now
1131          * 1 byte in ULONG
1132          *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1133          *{
1134          * target the pixel clock to drive the CRTC timing.
1135          * ULONG ulPixelClock:24;
1136          * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1137          * previous version.
1138          * ATOM_CRTC1~6, indicate the CRTC controller to
1139          * ULONG ucCRTC:8;
1140          * drive the pixel clock. not used for DCPLL case.
1141          *}CRTC_PIXEL_CLOCK_FREQ;
1142          *union
1143          *{
1144          * pixel clock and CRTC id frequency
1145          * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1146          * ULONG ulDispEngClkFreq; dispclk frequency
1147          *};
1148          */
1149         clk.sPCLKInput.ulCrtcPclkFreq.ucCRTC = controller_id;
1150         clk.sPCLKInput.ucPpll = (uint8_t) pll_id;
1151         clk.sPCLKInput.ucRefDiv =
1152                 (uint8_t) bp_params->reference_divider;
1153         clk.sPCLKInput.usFbDiv =
1154                 cpu_to_le16((uint16_t) bp_params->feedback_divider);
1155         clk.sPCLKInput.ulFbDivDecFrac =
1156                 cpu_to_le32(bp_params->fractional_feedback_divider);
1157         clk.sPCLKInput.ucPostDiv =
1158                 (uint8_t) bp_params->pixel_clock_post_divider;
1159         clk.sPCLKInput.ucTransmitterID =
1160                 bp->cmd_helper->encoder_id_to_atom(
1161                         dal_graphics_object_id_get_encoder_id(
1162                                 bp_params->encoder_object_id));
1163         clk.sPCLKInput.ucEncoderMode =
1164                 (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(
1165                         bp_params->signal_type, false);
1166 
1167         /* We need to convert from 100 Hz units into 10KHz units */
1168         clk.sPCLKInput.ulCrtcPclkFreq.ulPixelClock =
1169                 cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
1170 
1171         if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL) {
1172             clk.sPCLKInput.ucMiscInfo |=
1173                     PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL;
1174         }
1175 
1176         if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC) {
1177             clk.sPCLKInput.ucMiscInfo |=
1178                     PIXEL_CLOCK_V6_MISC_REF_DIV_SRC;
1179         }
1180 
1181         /* clkV6.ucMiscInfo bit[3:2]= HDMI panel bit depth: =0:
1182          * 24bpp =1:30bpp, =2:32bpp
1183          * driver choose program it itself, i.e. here we pass required
1184          * target rate that includes deep color.
1185          */
1186         if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
1187             switch (bp_params->color_depth) {
1188             case TRANSMITTER_COLOR_DEPTH_30:
1189                 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
1190                 break;
1191             case TRANSMITTER_COLOR_DEPTH_36:
1192                 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
1193                 break;
1194             case TRANSMITTER_COLOR_DEPTH_48:
1195                 clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
1196                 break;
1197             default:
1198                 break;
1199             }
1200 
1201         if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1202             result = BP_RESULT_OK;
1203     }
1204 
1205     return result;
1206 }
1207 
1208 static enum bp_result set_pixel_clock_v7(
1209     struct bios_parser *bp,
1210     struct bp_pixel_clock_parameters *bp_params)
1211 {
1212     enum bp_result result = BP_RESULT_FAILURE;
1213     PIXEL_CLOCK_PARAMETERS_V7 clk;
1214     uint8_t controller_id;
1215     uint32_t pll_id;
1216 
1217     memset(&clk, 0, sizeof(clk));
1218 
1219     if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
1220             && bp->cmd_helper->controller_id_to_atom(bp_params->controller_id, &controller_id)) {
1221         /* Note: VBIOS still wants to use ucCRTC name which is now
1222          * 1 byte in ULONG
1223          *typedef struct _CRTC_PIXEL_CLOCK_FREQ
1224          *{
1225          * target the pixel clock to drive the CRTC timing.
1226          * ULONG ulPixelClock:24;
1227          * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
1228          * previous version.
1229          * ATOM_CRTC1~6, indicate the CRTC controller to
1230          * ULONG ucCRTC:8;
1231          * drive the pixel clock. not used for DCPLL case.
1232          *}CRTC_PIXEL_CLOCK_FREQ;
1233          *union
1234          *{
1235          * pixel clock and CRTC id frequency
1236          * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
1237          * ULONG ulDispEngClkFreq; dispclk frequency
1238          *};
1239          */
1240         clk.ucCRTC = controller_id;
1241         clk.ucPpll = (uint8_t) pll_id;
1242         clk.ucTransmitterID = bp->cmd_helper->encoder_id_to_atom(dal_graphics_object_id_get_encoder_id(bp_params->encoder_object_id));
1243         clk.ucEncoderMode = (uint8_t) bp->cmd_helper->encoder_mode_bp_to_atom(bp_params->signal_type, false);
1244 
1245         clk.ulPixelClock = cpu_to_le32(bp_params->target_pixel_clock_100hz);
1246 
1247         clk.ucDeepColorRatio = (uint8_t) bp->cmd_helper->transmitter_color_depth_to_atom(bp_params->color_depth);
1248 
1249         if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
1250             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
1251 
1252         if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
1253             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC;
1254 
1255         if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
1256             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
1257 
1258         if (bp_params->flags.SUPPORT_YUV_420)
1259             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
1260 
1261         if (bp_params->flags.SET_XTALIN_REF_SRC)
1262             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
1263 
1264         if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
1265             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
1266 
1267         if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1268             clk.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
1269 
1270         if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
1271             result = BP_RESULT_OK;
1272     }
1273     return result;
1274 }
1275 
1276 /*******************************************************************************
1277  ********************************************************************************
1278  **
1279  **                  ENABLE PIXEL CLOCK SS
1280  **
1281  ********************************************************************************
1282  *******************************************************************************/
1283 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1284     struct bios_parser *bp,
1285     struct bp_spread_spectrum_parameters *bp_params,
1286     bool enable);
1287 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1288     struct bios_parser *bp,
1289     struct bp_spread_spectrum_parameters *bp_params,
1290     bool enable);
1291 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1292     struct bios_parser *bp,
1293     struct bp_spread_spectrum_parameters *bp_params,
1294     bool enable);
1295 
1296 static void init_enable_spread_spectrum_on_ppll(struct bios_parser *bp)
1297 {
1298     switch (BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL)) {
1299     case 1:
1300         bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1301                 enable_spread_spectrum_on_ppll_v1;
1302         break;
1303     case 2:
1304         bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1305                 enable_spread_spectrum_on_ppll_v2;
1306         break;
1307     case 3:
1308         bp->cmd_tbl.enable_spread_spectrum_on_ppll =
1309                 enable_spread_spectrum_on_ppll_v3;
1310         break;
1311     default:
1312         dm_output_to_console("Don't have enable_spread_spectrum_on_ppll for v%d\n",
1313              BIOS_CMD_TABLE_PARA_REVISION(EnableSpreadSpectrumOnPPLL));
1314         bp->cmd_tbl.enable_spread_spectrum_on_ppll = NULL;
1315         break;
1316     }
1317 }
1318 
1319 static enum bp_result enable_spread_spectrum_on_ppll_v1(
1320     struct bios_parser *bp,
1321     struct bp_spread_spectrum_parameters *bp_params,
1322     bool enable)
1323 {
1324     enum bp_result result = BP_RESULT_FAILURE;
1325     ENABLE_SPREAD_SPECTRUM_ON_PPLL params;
1326 
1327     memset(&params, 0, sizeof(params));
1328 
1329     if ((enable == true) && (bp_params->percentage > 0))
1330         params.ucEnable = ATOM_ENABLE;
1331     else
1332         params.ucEnable = ATOM_DISABLE;
1333 
1334     params.usSpreadSpectrumPercentage =
1335             cpu_to_le16((uint16_t)bp_params->percentage);
1336     params.ucSpreadSpectrumStep =
1337             (uint8_t)bp_params->ver1.step;
1338     params.ucSpreadSpectrumDelay =
1339             (uint8_t)bp_params->ver1.delay;
1340     /* convert back to unit of 10KHz */
1341     params.ucSpreadSpectrumRange =
1342             (uint8_t)(bp_params->ver1.range / 10000);
1343 
1344     if (bp_params->flags.EXTERNAL_SS)
1345         params.ucSpreadSpectrumType |= ATOM_EXTERNAL_SS_MASK;
1346 
1347     if (bp_params->flags.CENTER_SPREAD)
1348         params.ucSpreadSpectrumType |= ATOM_SS_CENTRE_SPREAD_MODE;
1349 
1350     if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1351         params.ucPpll = ATOM_PPLL1;
1352     else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1353         params.ucPpll = ATOM_PPLL2;
1354     else
1355         BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1356 
1357     if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1358         result = BP_RESULT_OK;
1359 
1360     return result;
1361 }
1362 
1363 static enum bp_result enable_spread_spectrum_on_ppll_v2(
1364     struct bios_parser *bp,
1365     struct bp_spread_spectrum_parameters *bp_params,
1366     bool enable)
1367 {
1368     enum bp_result result = BP_RESULT_FAILURE;
1369     ENABLE_SPREAD_SPECTRUM_ON_PPLL_V2 params;
1370 
1371     memset(&params, 0, sizeof(params));
1372 
1373     if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL1)
1374         params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P1PLL;
1375     else if (bp_params->pll_id == CLOCK_SOURCE_ID_PLL2)
1376         params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V2_P2PLL;
1377     else
1378         BREAK_TO_DEBUGGER(); /* Unexpected PLL value!! */
1379 
1380     if ((enable == true) && (bp_params->percentage > 0)) {
1381         params.ucEnable = ATOM_ENABLE;
1382 
1383         params.usSpreadSpectrumPercentage =
1384                 cpu_to_le16((uint16_t)(bp_params->percentage));
1385         params.usSpreadSpectrumStep =
1386                 cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1387 
1388         if (bp_params->flags.EXTERNAL_SS)
1389             params.ucSpreadSpectrumType |=
1390                     ATOM_PPLL_SS_TYPE_V2_EXT_SPREAD;
1391 
1392         if (bp_params->flags.CENTER_SPREAD)
1393             params.ucSpreadSpectrumType |=
1394                     ATOM_PPLL_SS_TYPE_V2_CENTRE_SPREAD;
1395 
1396         /* Both amounts need to be left shifted first before bit
1397          * comparison. Otherwise, the result will always be zero here
1398          */
1399         params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1400                 ((bp_params->ds.feedback_amount <<
1401                         ATOM_PPLL_SS_AMOUNT_V2_FBDIV_SHIFT) &
1402                         ATOM_PPLL_SS_AMOUNT_V2_FBDIV_MASK) |
1403                         ((bp_params->ds.nfrac_amount <<
1404                                 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT) &
1405                                 ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK)));
1406     } else
1407         params.ucEnable = ATOM_DISABLE;
1408 
1409     if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1410         result = BP_RESULT_OK;
1411 
1412     return result;
1413 }
1414 
1415 static enum bp_result enable_spread_spectrum_on_ppll_v3(
1416     struct bios_parser *bp,
1417     struct bp_spread_spectrum_parameters *bp_params,
1418     bool enable)
1419 {
1420     enum bp_result result = BP_RESULT_FAILURE;
1421     ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 params;
1422 
1423     memset(&params, 0, sizeof(params));
1424 
1425     switch (bp_params->pll_id) {
1426     case CLOCK_SOURCE_ID_PLL0:
1427         /* ATOM_PPLL_SS_TYPE_V3_P0PLL; this is pixel clock only,
1428          * not for SI display clock.
1429          */
1430         params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1431         break;
1432     case CLOCK_SOURCE_ID_PLL1:
1433         params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P1PLL;
1434         break;
1435 
1436     case CLOCK_SOURCE_ID_PLL2:
1437         params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_P2PLL;
1438         break;
1439 
1440     case CLOCK_SOURCE_ID_DCPLL:
1441         params.ucSpreadSpectrumType = ATOM_PPLL_SS_TYPE_V3_DCPLL;
1442         break;
1443 
1444     default:
1445         BREAK_TO_DEBUGGER();
1446         /* Unexpected PLL value!! */
1447         return result;
1448     }
1449 
1450     if (enable == true) {
1451         params.ucEnable = ATOM_ENABLE;
1452 
1453         params.usSpreadSpectrumAmountFrac =
1454                 cpu_to_le16((uint16_t)(bp_params->ds_frac_amount));
1455         params.usSpreadSpectrumStep =
1456                 cpu_to_le16((uint16_t)(bp_params->ds.ds_frac_size));
1457 
1458         if (bp_params->flags.EXTERNAL_SS)
1459             params.ucSpreadSpectrumType |=
1460                     ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD;
1461         if (bp_params->flags.CENTER_SPREAD)
1462             params.ucSpreadSpectrumType |=
1463                     ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD;
1464 
1465         /* Both amounts need to be left shifted first before bit
1466          * comparison. Otherwise, the result will always be zero here
1467          */
1468         params.usSpreadSpectrumAmount = cpu_to_le16((uint16_t)(
1469                 ((bp_params->ds.feedback_amount <<
1470                         ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT) &
1471                         ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK) |
1472                         ((bp_params->ds.nfrac_amount <<
1473                                 ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT) &
1474                                 ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK)));
1475     } else
1476         params.ucEnable = ATOM_DISABLE;
1477 
1478     if (EXEC_BIOS_CMD_TABLE(EnableSpreadSpectrumOnPPLL, params))
1479         result = BP_RESULT_OK;
1480 
1481     return result;
1482 }
1483 
1484 /*******************************************************************************
1485  ********************************************************************************
1486  **
1487  **                  ADJUST DISPLAY PLL
1488  **
1489  ********************************************************************************
1490  *******************************************************************************/
1491 
1492 static enum bp_result adjust_display_pll_v2(
1493     struct bios_parser *bp,
1494     struct bp_adjust_pixel_clock_parameters *bp_params);
1495 static enum bp_result adjust_display_pll_v3(
1496     struct bios_parser *bp,
1497     struct bp_adjust_pixel_clock_parameters *bp_params);
1498 
1499 static void init_adjust_display_pll(struct bios_parser *bp)
1500 {
1501     switch (BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll)) {
1502     case 2:
1503         bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v2;
1504         break;
1505     case 3:
1506         bp->cmd_tbl.adjust_display_pll = adjust_display_pll_v3;
1507         break;
1508     default:
1509         dm_output_to_console("Don't have adjust_display_pll for v%d\n",
1510              BIOS_CMD_TABLE_PARA_REVISION(AdjustDisplayPll));
1511         bp->cmd_tbl.adjust_display_pll = NULL;
1512         break;
1513     }
1514 }
1515 
1516 static enum bp_result adjust_display_pll_v2(
1517     struct bios_parser *bp,
1518     struct bp_adjust_pixel_clock_parameters *bp_params)
1519 {
1520     enum bp_result result = BP_RESULT_FAILURE;
1521     ADJUST_DISPLAY_PLL_PS_ALLOCATION params = { 0 };
1522 
1523     /* We need to convert from KHz units into 10KHz units and then convert
1524      * output pixel clock back 10KHz-->KHz */
1525     uint32_t pixel_clock_10KHz_in = bp_params->pixel_clock / 10;
1526 
1527     params.usPixelClock = cpu_to_le16((uint16_t)(pixel_clock_10KHz_in));
1528     params.ucTransmitterID =
1529             bp->cmd_helper->encoder_id_to_atom(
1530                     dal_graphics_object_id_get_encoder_id(
1531                             bp_params->encoder_object_id));
1532     params.ucEncodeMode =
1533             (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1534                     bp_params->signal_type, false);
1535 
1536     if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1537         /* Convert output pixel clock back 10KHz-->KHz: multiply
1538          * original pixel clock in KHz by ratio
1539          * [output pxlClk/input pxlClk] */
1540         uint64_t pixel_clk_10_khz_out =
1541                 (uint64_t)le16_to_cpu(params.usPixelClock);
1542         uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1543 
1544         if (pixel_clock_10KHz_in != 0) {
1545             bp_params->adjusted_pixel_clock =
1546                     div_u64(pixel_clk * pixel_clk_10_khz_out,
1547                             pixel_clock_10KHz_in);
1548         } else {
1549             bp_params->adjusted_pixel_clock = 0;
1550             BREAK_TO_DEBUGGER();
1551         }
1552 
1553         result = BP_RESULT_OK;
1554     }
1555 
1556     return result;
1557 }
1558 
1559 static enum bp_result adjust_display_pll_v3(
1560     struct bios_parser *bp,
1561     struct bp_adjust_pixel_clock_parameters *bp_params)
1562 {
1563     enum bp_result result = BP_RESULT_FAILURE;
1564     ADJUST_DISPLAY_PLL_PS_ALLOCATION_V3 params;
1565     uint32_t pixel_clk_10_kHz_in = bp_params->pixel_clock / 10;
1566 
1567     memset(&params, 0, sizeof(params));
1568 
1569     /* We need to convert from KHz units into 10KHz units and then convert
1570      * output pixel clock back 10KHz-->KHz */
1571     params.sInput.usPixelClock = cpu_to_le16((uint16_t)pixel_clk_10_kHz_in);
1572     params.sInput.ucTransmitterID =
1573             bp->cmd_helper->encoder_id_to_atom(
1574                     dal_graphics_object_id_get_encoder_id(
1575                             bp_params->encoder_object_id));
1576     params.sInput.ucEncodeMode =
1577             (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
1578                     bp_params->signal_type, false);
1579 
1580     if (bp_params->ss_enable == true)
1581         params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_SS_ENABLE;
1582 
1583     if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
1584         params.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK;
1585 
1586     if (EXEC_BIOS_CMD_TABLE(AdjustDisplayPll, params)) {
1587         /* Convert output pixel clock back 10KHz-->KHz: multiply
1588          * original pixel clock in KHz by ratio
1589          * [output pxlClk/input pxlClk] */
1590         uint64_t pixel_clk_10_khz_out =
1591                 (uint64_t)le32_to_cpu(params.sOutput.ulDispPllFreq);
1592         uint64_t pixel_clk = (uint64_t)bp_params->pixel_clock;
1593 
1594         if (pixel_clk_10_kHz_in != 0) {
1595             bp_params->adjusted_pixel_clock =
1596                     div_u64(pixel_clk * pixel_clk_10_khz_out,
1597                             pixel_clk_10_kHz_in);
1598         } else {
1599             bp_params->adjusted_pixel_clock = 0;
1600             BREAK_TO_DEBUGGER();
1601         }
1602 
1603         bp_params->reference_divider = params.sOutput.ucRefDiv;
1604         bp_params->pixel_clock_post_divider = params.sOutput.ucPostDiv;
1605 
1606         result = BP_RESULT_OK;
1607     }
1608 
1609     return result;
1610 }
1611 
1612 /*******************************************************************************
1613  ********************************************************************************
1614  **
1615  **                  DAC ENCODER CONTROL
1616  **
1617  ********************************************************************************
1618  *******************************************************************************/
1619 
1620 static enum bp_result dac1_encoder_control_v1(
1621     struct bios_parser *bp,
1622     bool enable,
1623     uint32_t pixel_clock,
1624     uint8_t dac_standard);
1625 static enum bp_result dac2_encoder_control_v1(
1626     struct bios_parser *bp,
1627     bool enable,
1628     uint32_t pixel_clock,
1629     uint8_t dac_standard);
1630 
1631 static void init_dac_encoder_control(struct bios_parser *bp)
1632 {
1633     switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1EncoderControl)) {
1634     case 1:
1635         bp->cmd_tbl.dac1_encoder_control = dac1_encoder_control_v1;
1636         break;
1637     default:
1638         bp->cmd_tbl.dac1_encoder_control = NULL;
1639         break;
1640     }
1641     switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2EncoderControl)) {
1642     case 1:
1643         bp->cmd_tbl.dac2_encoder_control = dac2_encoder_control_v1;
1644         break;
1645     default:
1646         bp->cmd_tbl.dac2_encoder_control = NULL;
1647         break;
1648     }
1649 }
1650 
1651 static void dac_encoder_control_prepare_params(
1652     DAC_ENCODER_CONTROL_PS_ALLOCATION *params,
1653     bool enable,
1654     uint32_t pixel_clock,
1655     uint8_t dac_standard)
1656 {
1657     params->ucDacStandard = dac_standard;
1658     if (enable)
1659         params->ucAction = ATOM_ENABLE;
1660     else
1661         params->ucAction = ATOM_DISABLE;
1662 
1663     /* We need to convert from KHz units into 10KHz units
1664      * it looks as if the TvControl do not care about pixel clock
1665      */
1666     params->usPixelClock = cpu_to_le16((uint16_t)(pixel_clock / 10));
1667 }
1668 
1669 static enum bp_result dac1_encoder_control_v1(
1670     struct bios_parser *bp,
1671     bool enable,
1672     uint32_t pixel_clock,
1673     uint8_t dac_standard)
1674 {
1675     enum bp_result result = BP_RESULT_FAILURE;
1676     DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1677 
1678     dac_encoder_control_prepare_params(
1679         &params,
1680         enable,
1681         pixel_clock,
1682         dac_standard);
1683 
1684     if (EXEC_BIOS_CMD_TABLE(DAC1EncoderControl, params))
1685         result = BP_RESULT_OK;
1686 
1687     return result;
1688 }
1689 
1690 static enum bp_result dac2_encoder_control_v1(
1691     struct bios_parser *bp,
1692     bool enable,
1693     uint32_t pixel_clock,
1694     uint8_t dac_standard)
1695 {
1696     enum bp_result result = BP_RESULT_FAILURE;
1697     DAC_ENCODER_CONTROL_PS_ALLOCATION params;
1698 
1699     dac_encoder_control_prepare_params(
1700         &params,
1701         enable,
1702         pixel_clock,
1703         dac_standard);
1704 
1705     if (EXEC_BIOS_CMD_TABLE(DAC2EncoderControl, params))
1706         result = BP_RESULT_OK;
1707 
1708     return result;
1709 }
1710 
1711 /*******************************************************************************
1712  ********************************************************************************
1713  **
1714  **                  DAC OUTPUT CONTROL
1715  **
1716  ********************************************************************************
1717  *******************************************************************************/
1718 static enum bp_result dac1_output_control_v1(
1719     struct bios_parser *bp,
1720     bool enable);
1721 static enum bp_result dac2_output_control_v1(
1722     struct bios_parser *bp,
1723     bool enable);
1724 
1725 static void init_dac_output_control(struct bios_parser *bp)
1726 {
1727     switch (BIOS_CMD_TABLE_PARA_REVISION(DAC1OutputControl)) {
1728     case 1:
1729         bp->cmd_tbl.dac1_output_control = dac1_output_control_v1;
1730         break;
1731     default:
1732         bp->cmd_tbl.dac1_output_control = NULL;
1733         break;
1734     }
1735     switch (BIOS_CMD_TABLE_PARA_REVISION(DAC2OutputControl)) {
1736     case 1:
1737         bp->cmd_tbl.dac2_output_control = dac2_output_control_v1;
1738         break;
1739     default:
1740         bp->cmd_tbl.dac2_output_control = NULL;
1741         break;
1742     }
1743 }
1744 
1745 static enum bp_result dac1_output_control_v1(
1746     struct bios_parser *bp, bool enable)
1747 {
1748     enum bp_result result = BP_RESULT_FAILURE;
1749     DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1750 
1751     if (enable)
1752         params.ucAction = ATOM_ENABLE;
1753     else
1754         params.ucAction = ATOM_DISABLE;
1755 
1756     if (EXEC_BIOS_CMD_TABLE(DAC1OutputControl, params))
1757         result = BP_RESULT_OK;
1758 
1759     return result;
1760 }
1761 
1762 static enum bp_result dac2_output_control_v1(
1763     struct bios_parser *bp, bool enable)
1764 {
1765     enum bp_result result = BP_RESULT_FAILURE;
1766     DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION params;
1767 
1768     if (enable)
1769         params.ucAction = ATOM_ENABLE;
1770     else
1771         params.ucAction = ATOM_DISABLE;
1772 
1773     if (EXEC_BIOS_CMD_TABLE(DAC2OutputControl, params))
1774         result = BP_RESULT_OK;
1775 
1776     return result;
1777 }
1778 
1779 /*******************************************************************************
1780  ********************************************************************************
1781  **
1782  **                  SET CRTC TIMING
1783  **
1784  ********************************************************************************
1785  *******************************************************************************/
1786 
1787 static enum bp_result set_crtc_using_dtd_timing_v3(
1788     struct bios_parser *bp,
1789     struct bp_hw_crtc_timing_parameters *bp_params);
1790 static enum bp_result set_crtc_timing_v1(
1791     struct bios_parser *bp,
1792     struct bp_hw_crtc_timing_parameters *bp_params);
1793 
1794 static void init_set_crtc_timing(struct bios_parser *bp)
1795 {
1796     uint32_t dtd_version =
1797             BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_UsingDTDTiming);
1798     if (dtd_version > 2)
1799         switch (dtd_version) {
1800         case 3:
1801             bp->cmd_tbl.set_crtc_timing =
1802                     set_crtc_using_dtd_timing_v3;
1803             break;
1804         default:
1805             dm_output_to_console("Don't have set_crtc_timing for dtd v%d\n",
1806                  dtd_version);
1807             bp->cmd_tbl.set_crtc_timing = NULL;
1808             break;
1809         }
1810     else
1811         switch (BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing)) {
1812         case 1:
1813             bp->cmd_tbl.set_crtc_timing = set_crtc_timing_v1;
1814             break;
1815         default:
1816             dm_output_to_console("Don't have set_crtc_timing for v%d\n",
1817                  BIOS_CMD_TABLE_PARA_REVISION(SetCRTC_Timing));
1818             bp->cmd_tbl.set_crtc_timing = NULL;
1819             break;
1820         }
1821 }
1822 
1823 static enum bp_result set_crtc_timing_v1(
1824     struct bios_parser *bp,
1825     struct bp_hw_crtc_timing_parameters *bp_params)
1826 {
1827     enum bp_result result = BP_RESULT_FAILURE;
1828     SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION params = {0};
1829     uint8_t atom_controller_id;
1830 
1831     if (bp->cmd_helper->controller_id_to_atom(
1832             bp_params->controller_id, &atom_controller_id))
1833         params.ucCRTC = atom_controller_id;
1834 
1835     params.usH_Total = cpu_to_le16((uint16_t)(bp_params->h_total));
1836     params.usH_Disp = cpu_to_le16((uint16_t)(bp_params->h_addressable));
1837     params.usH_SyncStart = cpu_to_le16((uint16_t)(bp_params->h_sync_start));
1838     params.usH_SyncWidth = cpu_to_le16((uint16_t)(bp_params->h_sync_width));
1839     params.usV_Total = cpu_to_le16((uint16_t)(bp_params->v_total));
1840     params.usV_Disp = cpu_to_le16((uint16_t)(bp_params->v_addressable));
1841     params.usV_SyncStart =
1842             cpu_to_le16((uint16_t)(bp_params->v_sync_start));
1843     params.usV_SyncWidth =
1844             cpu_to_le16((uint16_t)(bp_params->v_sync_width));
1845 
1846     /* VBIOS does not expect any value except zero into this call, for
1847      * underscan use another entry ProgramOverscan call but when mode
1848      * 1776x1000 with the overscan 72x44 .e.i. 1920x1080 @30 DAL2 is ok,
1849      * but when same ,but 60 Hz there is corruption
1850      * DAL1 does not allow the mode 1776x1000@60
1851      */
1852     params.ucOverscanRight = (uint8_t)bp_params->h_overscan_right;
1853     params.ucOverscanLeft = (uint8_t)bp_params->h_overscan_left;
1854     params.ucOverscanBottom = (uint8_t)bp_params->v_overscan_bottom;
1855     params.ucOverscanTop = (uint8_t)bp_params->v_overscan_top;
1856 
1857     if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1858         params.susModeMiscInfo.usAccess =
1859                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1860 
1861     if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1862         params.susModeMiscInfo.usAccess =
1863                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1864 
1865     if (bp_params->flags.INTERLACE) {
1866         params.susModeMiscInfo.usAccess =
1867                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1868 
1869         /* original DAL code has this condition to apply tis for
1870          * non-TV/CV only due to complex MV testing for possible
1871          * impact
1872          * if (pACParameters->signal != SignalType_YPbPr &&
1873          *  pACParameters->signal != SignalType_Composite &&
1874          *  pACParameters->signal != SignalType_SVideo)
1875          */
1876         /* HW will deduct 0.5 line from 2nd feild.
1877          * i.e. for 1080i, it is 2 lines for 1st field, 2.5
1878          * lines for the 2nd feild. we need input as 5 instead
1879          * of 4, but it is 4 either from Edid data
1880          * (spec CEA 861) or CEA timing table.
1881          */
1882         params.usV_SyncStart =
1883                 cpu_to_le16((uint16_t)(bp_params->v_sync_start + 1));
1884     }
1885 
1886     if (bp_params->flags.HORZ_COUNT_BY_TWO)
1887         params.susModeMiscInfo.usAccess =
1888                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1889 
1890     if (EXEC_BIOS_CMD_TABLE(SetCRTC_Timing, params))
1891         result = BP_RESULT_OK;
1892 
1893     return result;
1894 }
1895 
1896 static enum bp_result set_crtc_using_dtd_timing_v3(
1897     struct bios_parser *bp,
1898     struct bp_hw_crtc_timing_parameters *bp_params)
1899 {
1900     enum bp_result result = BP_RESULT_FAILURE;
1901     SET_CRTC_USING_DTD_TIMING_PARAMETERS params = {0};
1902     uint8_t atom_controller_id;
1903 
1904     if (bp->cmd_helper->controller_id_to_atom(
1905             bp_params->controller_id, &atom_controller_id))
1906         params.ucCRTC = atom_controller_id;
1907 
1908     /* bios usH_Size wants h addressable size */
1909     params.usH_Size = cpu_to_le16((uint16_t)bp_params->h_addressable);
1910     /* bios usH_Blanking_Time wants borders included in blanking */
1911     params.usH_Blanking_Time =
1912             cpu_to_le16((uint16_t)(bp_params->h_total - bp_params->h_addressable));
1913     /* bios usV_Size wants v addressable size */
1914     params.usV_Size = cpu_to_le16((uint16_t)bp_params->v_addressable);
1915     /* bios usV_Blanking_Time wants borders included in blanking */
1916     params.usV_Blanking_Time =
1917             cpu_to_le16((uint16_t)(bp_params->v_total - bp_params->v_addressable));
1918     /* bios usHSyncOffset is the offset from the end of h addressable,
1919      * our horizontalSyncStart is the offset from the beginning
1920      * of h addressable */
1921     params.usH_SyncOffset =
1922             cpu_to_le16((uint16_t)(bp_params->h_sync_start - bp_params->h_addressable));
1923     params.usH_SyncWidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
1924     /* bios usHSyncOffset is the offset from the end of v addressable,
1925      * our verticalSyncStart is the offset from the beginning of
1926      * v addressable */
1927     params.usV_SyncOffset =
1928             cpu_to_le16((uint16_t)(bp_params->v_sync_start - bp_params->v_addressable));
1929     params.usV_SyncWidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
1930 
1931     /* we assume that overscan from original timing does not get bigger
1932      * than 255
1933      * we will program all the borders in the Set CRTC Overscan call below
1934      */
1935 
1936     if (0 == bp_params->flags.HSYNC_POSITIVE_POLARITY)
1937         params.susModeMiscInfo.usAccess =
1938                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_HSYNC_POLARITY);
1939 
1940     if (0 == bp_params->flags.VSYNC_POSITIVE_POLARITY)
1941         params.susModeMiscInfo.usAccess =
1942                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_VSYNC_POLARITY);
1943 
1944     if (bp_params->flags.INTERLACE) {
1945         params.susModeMiscInfo.usAccess =
1946                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_INTERLACE);
1947 
1948         /* original DAL code has this condition to apply this
1949          * for non-TV/CV only
1950          * due to complex MV testing for possible impact
1951          * if ( pACParameters->signal != SignalType_YPbPr &&
1952          *  pACParameters->signal != SignalType_Composite &&
1953          *  pACParameters->signal != SignalType_SVideo)
1954          */
1955         {
1956             /* HW will deduct 0.5 line from 2nd feild.
1957              * i.e. for 1080i, it is 2 lines for 1st field,
1958              * 2.5 lines for the 2nd feild. we need input as 5
1959              * instead of 4.
1960              * but it is 4 either from Edid data (spec CEA 861)
1961              * or CEA timing table.
1962              */
1963             le16_add_cpu(&params.usV_SyncOffset, 1);
1964         }
1965     }
1966 
1967     if (bp_params->flags.HORZ_COUNT_BY_TWO)
1968         params.susModeMiscInfo.usAccess =
1969                 cpu_to_le16(le16_to_cpu(params.susModeMiscInfo.usAccess) | ATOM_DOUBLE_CLOCK_MODE);
1970 
1971     if (EXEC_BIOS_CMD_TABLE(SetCRTC_UsingDTDTiming, params))
1972         result = BP_RESULT_OK;
1973 
1974     return result;
1975 }
1976 
1977 /*******************************************************************************
1978  ********************************************************************************
1979  **
1980  **                  ENABLE CRTC
1981  **
1982  ********************************************************************************
1983  *******************************************************************************/
1984 
1985 static enum bp_result enable_crtc_v1(
1986     struct bios_parser *bp,
1987     enum controller_id controller_id,
1988     bool enable);
1989 
1990 static void init_enable_crtc(struct bios_parser *bp)
1991 {
1992     switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC)) {
1993     case 1:
1994         bp->cmd_tbl.enable_crtc = enable_crtc_v1;
1995         break;
1996     default:
1997         dm_output_to_console("Don't have enable_crtc for v%d\n",
1998              BIOS_CMD_TABLE_PARA_REVISION(EnableCRTC));
1999         bp->cmd_tbl.enable_crtc = NULL;
2000         break;
2001     }
2002 }
2003 
2004 static enum bp_result enable_crtc_v1(
2005     struct bios_parser *bp,
2006     enum controller_id controller_id,
2007     bool enable)
2008 {
2009     bool result = BP_RESULT_FAILURE;
2010     ENABLE_CRTC_PARAMETERS params = {0};
2011     uint8_t id;
2012 
2013     if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
2014         params.ucCRTC = id;
2015     else
2016         return BP_RESULT_BADINPUT;
2017 
2018     if (enable)
2019         params.ucEnable = ATOM_ENABLE;
2020     else
2021         params.ucEnable = ATOM_DISABLE;
2022 
2023     if (EXEC_BIOS_CMD_TABLE(EnableCRTC, params))
2024         result = BP_RESULT_OK;
2025 
2026     return result;
2027 }
2028 
2029 /*******************************************************************************
2030  ********************************************************************************
2031  **
2032  **                  ENABLE CRTC MEM REQ
2033  **
2034  ********************************************************************************
2035  *******************************************************************************/
2036 
2037 static enum bp_result enable_crtc_mem_req_v1(
2038     struct bios_parser *bp,
2039     enum controller_id controller_id,
2040     bool enable);
2041 
2042 static void init_enable_crtc_mem_req(struct bios_parser *bp)
2043 {
2044     switch (BIOS_CMD_TABLE_PARA_REVISION(EnableCRTCMemReq)) {
2045     case 1:
2046         bp->cmd_tbl.enable_crtc_mem_req = enable_crtc_mem_req_v1;
2047         break;
2048     default:
2049         bp->cmd_tbl.enable_crtc_mem_req = NULL;
2050         break;
2051     }
2052 }
2053 
2054 static enum bp_result enable_crtc_mem_req_v1(
2055     struct bios_parser *bp,
2056     enum controller_id controller_id,
2057     bool enable)
2058 {
2059     bool result = BP_RESULT_BADINPUT;
2060     ENABLE_CRTC_PARAMETERS params = {0};
2061     uint8_t id;
2062 
2063     if (bp->cmd_helper->controller_id_to_atom(controller_id, &id)) {
2064         params.ucCRTC = id;
2065 
2066         if (enable)
2067             params.ucEnable = ATOM_ENABLE;
2068         else
2069             params.ucEnable = ATOM_DISABLE;
2070 
2071         if (EXEC_BIOS_CMD_TABLE(EnableCRTCMemReq, params))
2072             result = BP_RESULT_OK;
2073         else
2074             result = BP_RESULT_FAILURE;
2075     }
2076 
2077     return result;
2078 }
2079 
2080 /*******************************************************************************
2081  ********************************************************************************
2082  **
2083  **                  DISPLAY PLL
2084  **
2085  ********************************************************************************
2086  *******************************************************************************/
2087 
2088 static enum bp_result program_clock_v5(
2089     struct bios_parser *bp,
2090     struct bp_pixel_clock_parameters *bp_params);
2091 static enum bp_result program_clock_v6(
2092     struct bios_parser *bp,
2093     struct bp_pixel_clock_parameters *bp_params);
2094 
2095 static void init_program_clock(struct bios_parser *bp)
2096 {
2097     switch (BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock)) {
2098     case 5:
2099         bp->cmd_tbl.program_clock = program_clock_v5;
2100         break;
2101     case 6:
2102         bp->cmd_tbl.program_clock = program_clock_v6;
2103         break;
2104     default:
2105         dm_output_to_console("Don't have program_clock for v%d\n",
2106              BIOS_CMD_TABLE_PARA_REVISION(SetPixelClock));
2107         bp->cmd_tbl.program_clock = NULL;
2108         break;
2109     }
2110 }
2111 
2112 static enum bp_result program_clock_v5(
2113     struct bios_parser *bp,
2114     struct bp_pixel_clock_parameters *bp_params)
2115 {
2116     enum bp_result result = BP_RESULT_FAILURE;
2117 
2118     SET_PIXEL_CLOCK_PS_ALLOCATION_V5 params;
2119     uint32_t atom_pll_id;
2120 
2121     memset(&params, 0, sizeof(params));
2122     if (!bp->cmd_helper->clock_source_id_to_atom(
2123             bp_params->pll_id, &atom_pll_id)) {
2124         BREAK_TO_DEBUGGER(); /* Invalid Input!! */
2125         return BP_RESULT_BADINPUT;
2126     }
2127 
2128     /* We need to convert from KHz units into 10KHz units */
2129     params.sPCLKInput.ucPpll = (uint8_t) atom_pll_id;
2130     params.sPCLKInput.usPixelClock =
2131             cpu_to_le16((uint16_t) (bp_params->target_pixel_clock_100hz / 100));
2132     params.sPCLKInput.ucCRTC = (uint8_t) ATOM_CRTC_INVALID;
2133 
2134     if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2135         params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2136 
2137     if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params))
2138         result = BP_RESULT_OK;
2139 
2140     return result;
2141 }
2142 
2143 static enum bp_result program_clock_v6(
2144     struct bios_parser *bp,
2145     struct bp_pixel_clock_parameters *bp_params)
2146 {
2147     enum bp_result result = BP_RESULT_FAILURE;
2148 
2149     SET_PIXEL_CLOCK_PS_ALLOCATION_V6 params;
2150     uint32_t atom_pll_id;
2151 
2152     memset(&params, 0, sizeof(params));
2153 
2154     if (!bp->cmd_helper->clock_source_id_to_atom(
2155             bp_params->pll_id, &atom_pll_id)) {
2156         BREAK_TO_DEBUGGER(); /*Invalid Input!!*/
2157         return BP_RESULT_BADINPUT;
2158     }
2159 
2160     /* We need to convert from KHz units into 10KHz units */
2161     params.sPCLKInput.ucPpll = (uint8_t)atom_pll_id;
2162     params.sPCLKInput.ulDispEngClkFreq =
2163             cpu_to_le32(bp_params->target_pixel_clock_100hz / 100);
2164 
2165     if (bp_params->flags.SET_EXTERNAL_REF_DIV_SRC)
2166         params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_MISC_REF_DIV_SRC;
2167 
2168     if (bp_params->flags.SET_DISPCLK_DFS_BYPASS)
2169         params.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_DPREFCLK_BYPASS;
2170 
2171     if (EXEC_BIOS_CMD_TABLE(SetPixelClock, params)) {
2172         /* True display clock is returned by VBIOS if DFS bypass
2173          * is enabled. */
2174         bp_params->dfs_bypass_display_clock =
2175                 (uint32_t)(le32_to_cpu(params.sPCLKInput.ulDispEngClkFreq) * 10);
2176         result = BP_RESULT_OK;
2177     }
2178 
2179     return result;
2180 }
2181 
2182 /*******************************************************************************
2183  ********************************************************************************
2184  **
2185  **                  EXTERNAL ENCODER CONTROL
2186  **
2187  ********************************************************************************
2188  *******************************************************************************/
2189 
2190 static enum bp_result external_encoder_control_v3(
2191     struct bios_parser *bp,
2192     struct bp_external_encoder_control *cntl);
2193 
2194 static void init_external_encoder_control(
2195     struct bios_parser *bp)
2196 {
2197     switch (BIOS_CMD_TABLE_PARA_REVISION(ExternalEncoderControl)) {
2198     case 3:
2199         bp->cmd_tbl.external_encoder_control =
2200                 external_encoder_control_v3;
2201         break;
2202     default:
2203         bp->cmd_tbl.external_encoder_control = NULL;
2204         break;
2205     }
2206 }
2207 
2208 static enum bp_result external_encoder_control_v3(
2209     struct bios_parser *bp,
2210     struct bp_external_encoder_control *cntl)
2211 {
2212     enum bp_result result = BP_RESULT_FAILURE;
2213 
2214     /* we need use _PS_Alloc struct */
2215     EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 params;
2216     EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 *cntl_params;
2217     struct graphics_object_id encoder;
2218     bool is_input_signal_dp = false;
2219 
2220     memset(&params, 0, sizeof(params));
2221 
2222     cntl_params = &params.sExtEncoder;
2223 
2224     encoder = cntl->encoder_id;
2225 
2226     /* check if encoder supports external encoder control table */
2227     switch (dal_graphics_object_id_get_encoder_id(encoder)) {
2228     case ENCODER_ID_EXTERNAL_NUTMEG:
2229     case ENCODER_ID_EXTERNAL_TRAVIS:
2230         is_input_signal_dp = true;
2231         break;
2232 
2233     default:
2234         BREAK_TO_DEBUGGER();
2235         return BP_RESULT_BADINPUT;
2236     }
2237 
2238     /* Fill information based on the action
2239      *
2240      * Bit[6:4]: indicate external encoder, applied to all functions.
2241      * =0: external encoder1, mapped to external encoder enum id1
2242      * =1: external encoder2, mapped to external encoder enum id2
2243      *
2244      * enum ObjectEnumId
2245      * {
2246      *  EnumId_Unknown = 0,
2247      *  EnumId_1,
2248      *  EnumId_2,
2249      * };
2250      */
2251     cntl_params->ucConfig = (uint8_t)((encoder.enum_id - 1) << 4);
2252 
2253     switch (cntl->action) {
2254     case EXTERNAL_ENCODER_CONTROL_INIT:
2255         /* output display connector type. Only valid in encoder
2256          * initialization */
2257         cntl_params->usConnectorId =
2258                 cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
2259         break;
2260     case EXTERNAL_ENCODER_CONTROL_SETUP:
2261         /* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
2262          * 10KHz
2263          * output display device pixel clock frequency in unit of 10KHz.
2264          * Only valid in setup and enableoutput
2265          */
2266         cntl_params->usPixelClock =
2267                 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2268         /* Indicate display output signal type drive by external
2269          * encoder, only valid in setup and enableoutput */
2270         cntl_params->ucEncoderMode =
2271                 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2272                         cntl->signal, false);
2273 
2274         if (is_input_signal_dp) {
2275             /* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
2276              * only valid in encoder setup with DP mode. */
2277             if (LINK_RATE_HIGH == cntl->link_rate)
2278                 cntl_params->ucConfig |= 1;
2279             /* output color depth Indicate encoder data bpc format
2280              * in DP mode, only valid in encoder setup in DP mode.
2281              */
2282             cntl_params->ucBitPerColor =
2283                     (uint8_t)(cntl->color_depth);
2284         }
2285         /* Indicate how many lanes used by external encoder, only valid
2286          * in encoder setup and enableoutput. */
2287         cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
2288         break;
2289     case EXTERNAL_ENCODER_CONTROL_ENABLE:
2290         cntl_params->usPixelClock =
2291                 cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
2292         cntl_params->ucEncoderMode =
2293                 (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
2294                         cntl->signal, false);
2295         cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
2296         break;
2297     default:
2298         break;
2299     }
2300 
2301     cntl_params->ucAction = (uint8_t)cntl->action;
2302 
2303     if (EXEC_BIOS_CMD_TABLE(ExternalEncoderControl, params))
2304         result = BP_RESULT_OK;
2305 
2306     return result;
2307 }
2308 
2309 /*******************************************************************************
2310  ********************************************************************************
2311  **
2312  **                  ENABLE DISPLAY POWER GATING
2313  **
2314  ********************************************************************************
2315  *******************************************************************************/
2316 
2317 static enum bp_result enable_disp_power_gating_v2_1(
2318     struct bios_parser *bp,
2319     enum controller_id crtc_id,
2320     enum bp_pipe_control_action action);
2321 
2322 static void init_enable_disp_power_gating(
2323     struct bios_parser *bp)
2324 {
2325     switch (BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating)) {
2326     case 1:
2327         bp->cmd_tbl.enable_disp_power_gating =
2328                 enable_disp_power_gating_v2_1;
2329         break;
2330     default:
2331         dm_output_to_console("Don't enable_disp_power_gating enable_crtc for v%d\n",
2332              BIOS_CMD_TABLE_PARA_REVISION(EnableDispPowerGating));
2333         bp->cmd_tbl.enable_disp_power_gating = NULL;
2334         break;
2335     }
2336 }
2337 
2338 static enum bp_result enable_disp_power_gating_v2_1(
2339     struct bios_parser *bp,
2340     enum controller_id crtc_id,
2341     enum bp_pipe_control_action action)
2342 {
2343     enum bp_result result = BP_RESULT_FAILURE;
2344 
2345     ENABLE_DISP_POWER_GATING_PS_ALLOCATION params = {0};
2346     uint8_t atom_crtc_id;
2347 
2348     if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
2349         params.ucDispPipeId = atom_crtc_id;
2350     else
2351         return BP_RESULT_BADINPUT;
2352 
2353     params.ucEnable =
2354             bp->cmd_helper->disp_power_gating_action_to_atom(action);
2355 
2356     if (EXEC_BIOS_CMD_TABLE(EnableDispPowerGating, params))
2357         result = BP_RESULT_OK;
2358 
2359     return result;
2360 }
2361 
2362 /*******************************************************************************
2363  ********************************************************************************
2364  **
2365  **                  SET DCE CLOCK
2366  **
2367  ********************************************************************************
2368  *******************************************************************************/
2369 static enum bp_result set_dce_clock_v2_1(
2370     struct bios_parser *bp,
2371     struct bp_set_dce_clock_parameters *bp_params);
2372 
2373 static void init_set_dce_clock(struct bios_parser *bp)
2374 {
2375     switch (BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock)) {
2376     case 1:
2377         bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
2378         break;
2379     default:
2380         dm_output_to_console("Don't have set_dce_clock for v%d\n",
2381              BIOS_CMD_TABLE_PARA_REVISION(SetDCEClock));
2382         bp->cmd_tbl.set_dce_clock = NULL;
2383         break;
2384     }
2385 }
2386 
2387 static enum bp_result set_dce_clock_v2_1(
2388     struct bios_parser *bp,
2389     struct bp_set_dce_clock_parameters *bp_params)
2390 {
2391     enum bp_result result = BP_RESULT_FAILURE;
2392 
2393     SET_DCE_CLOCK_PS_ALLOCATION_V2_1 params;
2394     uint32_t atom_pll_id;
2395     uint32_t atom_clock_type;
2396     const struct command_table_helper *cmd = bp->cmd_helper;
2397 
2398     memset(&params, 0, sizeof(params));
2399 
2400     if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
2401             !cmd->dc_clock_type_to_atom(bp_params->clock_type, &atom_clock_type))
2402         return BP_RESULT_BADINPUT;
2403 
2404     params.asParam.ucDCEClkSrc  = atom_pll_id;
2405     params.asParam.ucDCEClkType = atom_clock_type;
2406 
2407     if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
2408         if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
2409             params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
2410 
2411         if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
2412             params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
2413 
2414         if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
2415             params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
2416 
2417         if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
2418             params.asParam.ucDCEClkFlag |= DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
2419     }
2420     else
2421         /* only program clock frequency if display clock is used; VBIOS will program DPREFCLK */
2422         /* We need to convert from KHz units into 10KHz units */
2423         params.asParam.ulDCEClkFreq = cpu_to_le32(bp_params->target_clock_frequency / 10);
2424 
2425     if (EXEC_BIOS_CMD_TABLE(SetDCEClock, params)) {
2426         /* Convert from 10KHz units back to KHz */
2427         bp_params->target_clock_frequency = le32_to_cpu(params.asParam.ulDCEClkFreq) * 10;
2428         result = BP_RESULT_OK;
2429     }
2430 
2431     return result;
2432 }