root/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bios_parser_create
  2. destruct
  3. bios_parser_destroy
  4. get_number_of_objects
  5. bios_parser_get_connectors_number
  6. bios_parser_get_connector_id
  7. bios_parser_get_src_obj
  8. bios_parser_get_i2c_info
  9. bios_parser_get_hpd_info
  10. bios_parser_get_device_tag_record
  11. bios_parser_get_device_tag
  12. bios_parser_get_firmware_info
  13. get_firmware_info_v1_4
  14. get_firmware_info_v2_1
  15. get_firmware_info_v2_2
  16. get_ss_info_v3_1
  17. bios_parser_transmitter_control
  18. bios_parser_encoder_control
  19. bios_parser_adjust_pixel_clock
  20. bios_parser_set_pixel_clock
  21. bios_parser_set_dce_clock
  22. bios_parser_enable_spread_spectrum_on_ppll
  23. bios_parser_program_crtc_timing
  24. bios_parser_program_display_engine_pll
  25. bios_parser_enable_crtc
  26. bios_parser_enable_disp_power_gating
  27. bios_parser_is_device_id_supported
  28. get_hpd_record
  29. bios_parser_get_spread_spectrum_info
  30. get_ss_info_from_tbl
  31. get_ss_info_from_internal_ss_info_tbl_V2_1
  32. get_ss_info_from_ss_info_table
  33. bios_parser_get_embedded_panel_info
  34. get_embedded_panel_info_v1_2
  35. get_embedded_panel_info_v1_3
  36. bios_parser_get_encoder_cap_info
  37. get_encoder_cap_record
  38. bios_parser_get_ss_entry_number
  39. get_ss_entry_number_from_ss_info_tbl
  40. get_ss_entry_number
  41. get_ss_entry_number_from_internal_ss_info_tbl_v2_1
  42. get_ss_entry_number_from_internal_ss_info_tbl_V3_1
  43. bios_parser_get_gpio_pin_info
  44. get_gpio_i2c_info
  45. dal_graphics_object_id_is_valid
  46. dal_graphics_object_id_is_equal
  47. get_bios_object
  48. get_src_obj_list
  49. device_type_from_device_id
  50. get_atom_data_table_revision
  51. signal_to_ss_id
  52. get_support_mask_for_device_id
  53. bios_parser_set_scratch_critical_state
  54. get_integrated_info_v8
  55. get_integrated_info_v9
  56. construct_integrated_info
  57. bios_parser_create_integrated_info
  58. update_slot_layout_info
  59. get_bracket_layout_record
  60. bios_get_board_layout_info
  61. bios_parser_construct

   1 /*
   2  * Copyright 2012-15 Advanced Micro Devices, Inc.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: AMD
  23  *
  24  */
  25 
  26 #include <linux/slab.h>
  27 
  28 #include "dm_services.h"
  29 
  30 #include "atom.h"
  31 
  32 #include "dc_bios_types.h"
  33 #include "include/gpio_service_interface.h"
  34 #include "include/grph_object_ctrl_defs.h"
  35 #include "include/bios_parser_interface.h"
  36 #include "include/i2caux_interface.h"
  37 #include "include/logger_interface.h"
  38 
  39 #include "command_table.h"
  40 #include "bios_parser_helper.h"
  41 #include "command_table_helper.h"
  42 #include "bios_parser.h"
  43 #include "bios_parser_types_internal.h"
  44 #include "bios_parser_interface.h"
  45 
  46 #include "bios_parser_common.h"
  47 
  48 #include "dc.h"
  49 
  50 #define THREE_PERCENT_OF_10000 300
  51 
  52 #define LAST_RECORD_TYPE 0xff
  53 
  54 #define DC_LOGGER \
  55         bp->base.ctx->logger
  56 
  57 #define DATA_TABLES(table) (bp->master_data_tbl->ListOfDataTables.table)
  58 
  59 static void get_atom_data_table_revision(
  60         ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
  61         struct atom_data_revision *tbl_revision);
  62 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
  63         uint16_t **id_list);
  64 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
  65         struct graphics_object_id id);
  66 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
  67         ATOM_I2C_RECORD *record,
  68         struct graphics_object_i2c_info *info);
  69 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
  70         ATOM_OBJECT *object);
  71 static struct device_id device_type_from_device_id(uint16_t device_id);
  72 static uint32_t signal_to_ss_id(enum as_signal_type signal);
  73 static uint32_t get_support_mask_for_device_id(struct device_id device_id);
  74 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
  75         struct bios_parser *bp,
  76         ATOM_OBJECT *object);
  77 
  78 #define BIOS_IMAGE_SIZE_OFFSET 2
  79 #define BIOS_IMAGE_SIZE_UNIT 512
  80 
  81 /*****************************************************************************/
  82 static bool bios_parser_construct(
  83         struct bios_parser *bp,
  84         struct bp_init_data *init,
  85         enum dce_version dce_version);
  86 
  87 static uint8_t bios_parser_get_connectors_number(
  88         struct dc_bios *dcb);
  89 
  90 static enum bp_result bios_parser_get_embedded_panel_info(
  91         struct dc_bios *dcb,
  92         struct embedded_panel_info *info);
  93 
  94 /*****************************************************************************/
  95 
  96 struct dc_bios *bios_parser_create(
  97         struct bp_init_data *init,
  98         enum dce_version dce_version)
  99 {
 100         struct bios_parser *bp = NULL;
 101 
 102         bp = kzalloc(sizeof(struct bios_parser), GFP_KERNEL);
 103         if (!bp)
 104                 return NULL;
 105 
 106         if (bios_parser_construct(bp, init, dce_version))
 107                 return &bp->base;
 108 
 109         kfree(bp);
 110         BREAK_TO_DEBUGGER();
 111         return NULL;
 112 }
 113 
 114 static void destruct(struct bios_parser *bp)
 115 {
 116         kfree(bp->base.bios_local_image);
 117         kfree(bp->base.integrated_info);
 118 }
 119 
 120 static void bios_parser_destroy(struct dc_bios **dcb)
 121 {
 122         struct bios_parser *bp = BP_FROM_DCB(*dcb);
 123 
 124         if (!bp) {
 125                 BREAK_TO_DEBUGGER();
 126                 return;
 127         }
 128 
 129         destruct(bp);
 130 
 131         kfree(bp);
 132         *dcb = NULL;
 133 }
 134 
 135 static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
 136 {
 137         ATOM_OBJECT_TABLE *table;
 138 
 139         uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
 140 
 141         table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
 142 
 143         if (!table)
 144                 return 0;
 145         else
 146                 return table->ucNumberOfObjects;
 147 }
 148 
 149 static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
 150 {
 151         struct bios_parser *bp = BP_FROM_DCB(dcb);
 152 
 153         return get_number_of_objects(bp,
 154                 le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset));
 155 }
 156 
 157 static struct graphics_object_id bios_parser_get_connector_id(
 158         struct dc_bios *dcb,
 159         uint8_t i)
 160 {
 161         struct bios_parser *bp = BP_FROM_DCB(dcb);
 162         struct graphics_object_id object_id = dal_graphics_object_id_init(
 163                 0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
 164         uint16_t id;
 165 
 166         uint32_t connector_table_offset = bp->object_info_tbl_offset
 167                 + le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
 168 
 169         ATOM_OBJECT_TABLE *tbl =
 170                 GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
 171 
 172         if (!tbl) {
 173                 dm_error("Can't get connector table from atom bios.\n");
 174                 return object_id;
 175         }
 176 
 177         if (tbl->ucNumberOfObjects <= i) {
 178                 dm_error("Can't find connector id %d in connector table of size %d.\n",
 179                          i, tbl->ucNumberOfObjects);
 180                 return object_id;
 181         }
 182 
 183         id = le16_to_cpu(tbl->asObjects[i].usObjectID);
 184         object_id = object_id_from_bios_object_id(id);
 185         return object_id;
 186 }
 187 
 188 static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
 189         struct graphics_object_id object_id, uint32_t index,
 190         struct graphics_object_id *src_object_id)
 191 {
 192         uint32_t number;
 193         uint16_t *id;
 194         ATOM_OBJECT *object;
 195         struct bios_parser *bp = BP_FROM_DCB(dcb);
 196 
 197         if (!src_object_id)
 198                 return BP_RESULT_BADINPUT;
 199 
 200         object = get_bios_object(bp, object_id);
 201 
 202         if (!object) {
 203                 BREAK_TO_DEBUGGER(); /* Invalid object id */
 204                 return BP_RESULT_BADINPUT;
 205         }
 206 
 207         number = get_src_obj_list(bp, object, &id);
 208 
 209         if (number <= index)
 210                 return BP_RESULT_BADINPUT;
 211 
 212         *src_object_id = object_id_from_bios_object_id(id[index]);
 213 
 214         return BP_RESULT_OK;
 215 }
 216 
 217 static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
 218         struct graphics_object_id id,
 219         struct graphics_object_i2c_info *info)
 220 {
 221         uint32_t offset;
 222         ATOM_OBJECT *object;
 223         ATOM_COMMON_RECORD_HEADER *header;
 224         ATOM_I2C_RECORD *record;
 225         struct bios_parser *bp = BP_FROM_DCB(dcb);
 226 
 227         if (!info)
 228                 return BP_RESULT_BADINPUT;
 229 
 230         object = get_bios_object(bp, id);
 231 
 232         if (!object)
 233                 return BP_RESULT_BADINPUT;
 234 
 235         offset = le16_to_cpu(object->usRecordOffset)
 236                         + bp->object_info_tbl_offset;
 237 
 238         for (;;) {
 239                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
 240 
 241                 if (!header)
 242                         return BP_RESULT_BADBIOSTABLE;
 243 
 244                 if (LAST_RECORD_TYPE == header->ucRecordType ||
 245                         !header->ucRecordSize)
 246                         break;
 247 
 248                 if (ATOM_I2C_RECORD_TYPE == header->ucRecordType
 249                         && sizeof(ATOM_I2C_RECORD) <= header->ucRecordSize) {
 250                         /* get the I2C info */
 251                         record = (ATOM_I2C_RECORD *) header;
 252 
 253                         if (get_gpio_i2c_info(bp, record, info) == BP_RESULT_OK)
 254                                 return BP_RESULT_OK;
 255                 }
 256 
 257                 offset += header->ucRecordSize;
 258         }
 259 
 260         return BP_RESULT_NORECORD;
 261 }
 262 
 263 static enum bp_result bios_parser_get_hpd_info(struct dc_bios *dcb,
 264         struct graphics_object_id id,
 265         struct graphics_object_hpd_info *info)
 266 {
 267         struct bios_parser *bp = BP_FROM_DCB(dcb);
 268         ATOM_OBJECT *object;
 269         ATOM_HPD_INT_RECORD *record = NULL;
 270 
 271         if (!info)
 272                 return BP_RESULT_BADINPUT;
 273 
 274         object = get_bios_object(bp, id);
 275 
 276         if (!object)
 277                 return BP_RESULT_BADINPUT;
 278 
 279         record = get_hpd_record(bp, object);
 280 
 281         if (record != NULL) {
 282                 info->hpd_int_gpio_uid = record->ucHPDIntGPIOID;
 283                 info->hpd_active = record->ucPlugged_PinState;
 284                 return BP_RESULT_OK;
 285         }
 286 
 287         return BP_RESULT_NORECORD;
 288 }
 289 
 290 static enum bp_result bios_parser_get_device_tag_record(
 291         struct bios_parser *bp,
 292         ATOM_OBJECT *object,
 293         ATOM_CONNECTOR_DEVICE_TAG_RECORD **record)
 294 {
 295         ATOM_COMMON_RECORD_HEADER *header;
 296         uint32_t offset;
 297 
 298         offset = le16_to_cpu(object->usRecordOffset)
 299                         + bp->object_info_tbl_offset;
 300 
 301         for (;;) {
 302                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
 303 
 304                 if (!header)
 305                         return BP_RESULT_BADBIOSTABLE;
 306 
 307                 offset += header->ucRecordSize;
 308 
 309                 if (LAST_RECORD_TYPE == header->ucRecordType ||
 310                         !header->ucRecordSize)
 311                         break;
 312 
 313                 if (ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE !=
 314                         header->ucRecordType)
 315                         continue;
 316 
 317                 if (sizeof(ATOM_CONNECTOR_DEVICE_TAG) > header->ucRecordSize)
 318                         continue;
 319 
 320                 *record = (ATOM_CONNECTOR_DEVICE_TAG_RECORD *) header;
 321                 return BP_RESULT_OK;
 322         }
 323 
 324         return BP_RESULT_NORECORD;
 325 }
 326 
 327 static enum bp_result bios_parser_get_device_tag(
 328         struct dc_bios *dcb,
 329         struct graphics_object_id connector_object_id,
 330         uint32_t device_tag_index,
 331         struct connector_device_tag_info *info)
 332 {
 333         struct bios_parser *bp = BP_FROM_DCB(dcb);
 334         ATOM_OBJECT *object;
 335         ATOM_CONNECTOR_DEVICE_TAG_RECORD *record = NULL;
 336         ATOM_CONNECTOR_DEVICE_TAG *device_tag;
 337 
 338         if (!info)
 339                 return BP_RESULT_BADINPUT;
 340 
 341         /* getBiosObject will return MXM object */
 342         object = get_bios_object(bp, connector_object_id);
 343 
 344         if (!object) {
 345                 BREAK_TO_DEBUGGER(); /* Invalid object id */
 346                 return BP_RESULT_BADINPUT;
 347         }
 348 
 349         if (bios_parser_get_device_tag_record(bp, object, &record)
 350                 != BP_RESULT_OK)
 351                 return BP_RESULT_NORECORD;
 352 
 353         if (device_tag_index >= record->ucNumberOfDevice)
 354                 return BP_RESULT_NORECORD;
 355 
 356         device_tag = &record->asDeviceTag[device_tag_index];
 357 
 358         info->acpi_device = le32_to_cpu(device_tag->ulACPIDeviceEnum);
 359         info->dev_id =
 360                 device_type_from_device_id(le16_to_cpu(device_tag->usDeviceID));
 361 
 362         return BP_RESULT_OK;
 363 }
 364 
 365 static enum bp_result get_firmware_info_v1_4(
 366         struct bios_parser *bp,
 367         struct dc_firmware_info *info);
 368 static enum bp_result get_firmware_info_v2_1(
 369         struct bios_parser *bp,
 370         struct dc_firmware_info *info);
 371 static enum bp_result get_firmware_info_v2_2(
 372         struct bios_parser *bp,
 373         struct dc_firmware_info *info);
 374 
 375 static enum bp_result bios_parser_get_firmware_info(
 376         struct dc_bios *dcb,
 377         struct dc_firmware_info *info)
 378 {
 379         struct bios_parser *bp = BP_FROM_DCB(dcb);
 380         enum bp_result result = BP_RESULT_BADBIOSTABLE;
 381         ATOM_COMMON_TABLE_HEADER *header;
 382         struct atom_data_revision revision;
 383 
 384         if (info && DATA_TABLES(FirmwareInfo)) {
 385                 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
 386                         DATA_TABLES(FirmwareInfo));
 387                 get_atom_data_table_revision(header, &revision);
 388                 switch (revision.major) {
 389                 case 1:
 390                         switch (revision.minor) {
 391                         case 4:
 392                                 result = get_firmware_info_v1_4(bp, info);
 393                                 break;
 394                         default:
 395                                 break;
 396                         }
 397                         break;
 398 
 399                 case 2:
 400                         switch (revision.minor) {
 401                         case 1:
 402                                 result = get_firmware_info_v2_1(bp, info);
 403                                 break;
 404                         case 2:
 405                                 result = get_firmware_info_v2_2(bp, info);
 406                                 break;
 407                         default:
 408                                 break;
 409                         }
 410                         break;
 411                 default:
 412                         break;
 413                 }
 414         }
 415 
 416         return result;
 417 }
 418 
 419 static enum bp_result get_firmware_info_v1_4(
 420         struct bios_parser *bp,
 421         struct dc_firmware_info *info)
 422 {
 423         ATOM_FIRMWARE_INFO_V1_4 *firmware_info =
 424                 GET_IMAGE(ATOM_FIRMWARE_INFO_V1_4,
 425                         DATA_TABLES(FirmwareInfo));
 426 
 427         if (!info)
 428                 return BP_RESULT_BADINPUT;
 429 
 430         if (!firmware_info)
 431                 return BP_RESULT_BADBIOSTABLE;
 432 
 433         memset(info, 0, sizeof(*info));
 434 
 435         /* Pixel clock pll information. We need to convert from 10KHz units into
 436          * KHz units */
 437         info->pll_info.crystal_frequency =
 438                 le16_to_cpu(firmware_info->usReferenceClock) * 10;
 439         info->pll_info.min_input_pxl_clk_pll_frequency =
 440                 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
 441         info->pll_info.max_input_pxl_clk_pll_frequency =
 442                 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
 443         info->pll_info.min_output_pxl_clk_pll_frequency =
 444                 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
 445         info->pll_info.max_output_pxl_clk_pll_frequency =
 446                 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
 447 
 448         if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
 449                 /* Since there is no information on the SS, report conservative
 450                  * value 3% for bandwidth calculation */
 451                 /* unit of 0.01% */
 452                 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
 453 
 454         if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
 455                 /* Since there is no information on the SS,report conservative
 456                  * value 3% for bandwidth calculation */
 457                 /* unit of 0.01% */
 458                 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
 459 
 460         return BP_RESULT_OK;
 461 }
 462 
 463 static enum bp_result get_ss_info_v3_1(
 464         struct bios_parser *bp,
 465         uint32_t id,
 466         uint32_t index,
 467         struct spread_spectrum_info *ss_info);
 468 
 469 static enum bp_result get_firmware_info_v2_1(
 470         struct bios_parser *bp,
 471         struct dc_firmware_info *info)
 472 {
 473         ATOM_FIRMWARE_INFO_V2_1 *firmwareInfo =
 474                 GET_IMAGE(ATOM_FIRMWARE_INFO_V2_1, DATA_TABLES(FirmwareInfo));
 475         struct spread_spectrum_info internalSS;
 476         uint32_t index;
 477 
 478         if (!info)
 479                 return BP_RESULT_BADINPUT;
 480 
 481         if (!firmwareInfo)
 482                 return BP_RESULT_BADBIOSTABLE;
 483 
 484         memset(info, 0, sizeof(*info));
 485 
 486         /* Pixel clock pll information. We need to convert from 10KHz units into
 487          * KHz units */
 488         info->pll_info.crystal_frequency =
 489                 le16_to_cpu(firmwareInfo->usCoreReferenceClock) * 10;
 490         info->pll_info.min_input_pxl_clk_pll_frequency =
 491                 le16_to_cpu(firmwareInfo->usMinPixelClockPLL_Input) * 10;
 492         info->pll_info.max_input_pxl_clk_pll_frequency =
 493                 le16_to_cpu(firmwareInfo->usMaxPixelClockPLL_Input) * 10;
 494         info->pll_info.min_output_pxl_clk_pll_frequency =
 495                 le32_to_cpu(firmwareInfo->ulMinPixelClockPLL_Output) * 10;
 496         info->pll_info.max_output_pxl_clk_pll_frequency =
 497                 le32_to_cpu(firmwareInfo->ulMaxPixelClockPLL_Output) * 10;
 498         info->default_display_engine_pll_frequency =
 499                 le32_to_cpu(firmwareInfo->ulDefaultDispEngineClkFreq) * 10;
 500         info->external_clock_source_frequency_for_dp =
 501                 le16_to_cpu(firmwareInfo->usUniphyDPModeExtClkFreq) * 10;
 502         info->min_allowed_bl_level = firmwareInfo->ucMinAllowedBL_Level;
 503 
 504         /* There should be only one entry in the SS info table for Memory Clock
 505          */
 506         index = 0;
 507         if (firmwareInfo->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
 508                 /* Since there is no information for external SS, report
 509                  *  conservative value 3% for bandwidth calculation */
 510                 /* unit of 0.01% */
 511                 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
 512         else if (get_ss_info_v3_1(bp,
 513                 ASIC_INTERNAL_MEMORY_SS, index, &internalSS) == BP_RESULT_OK) {
 514                 if (internalSS.spread_spectrum_percentage) {
 515                         info->feature.memory_clk_ss_percentage =
 516                                 internalSS.spread_spectrum_percentage;
 517                         if (internalSS.type.CENTER_MODE) {
 518                                 /* if it is centermode, the exact SS Percentage
 519                                  * will be round up of half of the percentage
 520                                  * reported in the SS table */
 521                                 ++info->feature.memory_clk_ss_percentage;
 522                                 info->feature.memory_clk_ss_percentage /= 2;
 523                         }
 524                 }
 525         }
 526 
 527         /* There should be only one entry in the SS info table for Engine Clock
 528          */
 529         index = 1;
 530         if (firmwareInfo->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
 531                 /* Since there is no information for external SS, report
 532                  * conservative value 3% for bandwidth calculation */
 533                 /* unit of 0.01% */
 534                 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
 535         else if (get_ss_info_v3_1(bp,
 536                 ASIC_INTERNAL_ENGINE_SS, index, &internalSS) == BP_RESULT_OK) {
 537                 if (internalSS.spread_spectrum_percentage) {
 538                         info->feature.engine_clk_ss_percentage =
 539                                 internalSS.spread_spectrum_percentage;
 540                         if (internalSS.type.CENTER_MODE) {
 541                                 /* if it is centermode, the exact SS Percentage
 542                                  * will be round up of half of the percentage
 543                                  * reported in the SS table */
 544                                 ++info->feature.engine_clk_ss_percentage;
 545                                 info->feature.engine_clk_ss_percentage /= 2;
 546                         }
 547                 }
 548         }
 549 
 550         return BP_RESULT_OK;
 551 }
 552 
 553 static enum bp_result get_firmware_info_v2_2(
 554         struct bios_parser *bp,
 555         struct dc_firmware_info *info)
 556 {
 557         ATOM_FIRMWARE_INFO_V2_2 *firmware_info;
 558         struct spread_spectrum_info internal_ss;
 559         uint32_t index;
 560 
 561         if (!info)
 562                 return BP_RESULT_BADINPUT;
 563 
 564         firmware_info = GET_IMAGE(ATOM_FIRMWARE_INFO_V2_2,
 565                 DATA_TABLES(FirmwareInfo));
 566 
 567         if (!firmware_info)
 568                 return BP_RESULT_BADBIOSTABLE;
 569 
 570         memset(info, 0, sizeof(*info));
 571 
 572         /* Pixel clock pll information. We need to convert from 10KHz units into
 573          * KHz units */
 574         info->pll_info.crystal_frequency =
 575                 le16_to_cpu(firmware_info->usCoreReferenceClock) * 10;
 576         info->pll_info.min_input_pxl_clk_pll_frequency =
 577                 le16_to_cpu(firmware_info->usMinPixelClockPLL_Input) * 10;
 578         info->pll_info.max_input_pxl_clk_pll_frequency =
 579                 le16_to_cpu(firmware_info->usMaxPixelClockPLL_Input) * 10;
 580         info->pll_info.min_output_pxl_clk_pll_frequency =
 581                 le32_to_cpu(firmware_info->ulMinPixelClockPLL_Output) * 10;
 582         info->pll_info.max_output_pxl_clk_pll_frequency =
 583                 le32_to_cpu(firmware_info->ulMaxPixelClockPLL_Output) * 10;
 584         info->default_display_engine_pll_frequency =
 585                 le32_to_cpu(firmware_info->ulDefaultDispEngineClkFreq) * 10;
 586         info->external_clock_source_frequency_for_dp =
 587                 le16_to_cpu(firmware_info->usUniphyDPModeExtClkFreq) * 10;
 588 
 589         /* There should be only one entry in the SS info table for Memory Clock
 590          */
 591         index = 0;
 592         if (firmware_info->usFirmwareCapability.sbfAccess.MemoryClockSS_Support)
 593                 /* Since there is no information for external SS, report
 594                  *  conservative value 3% for bandwidth calculation */
 595                 /* unit of 0.01% */
 596                 info->feature.memory_clk_ss_percentage = THREE_PERCENT_OF_10000;
 597         else if (get_ss_info_v3_1(bp,
 598                         ASIC_INTERNAL_MEMORY_SS, index, &internal_ss) == BP_RESULT_OK) {
 599                 if (internal_ss.spread_spectrum_percentage) {
 600                         info->feature.memory_clk_ss_percentage =
 601                                         internal_ss.spread_spectrum_percentage;
 602                         if (internal_ss.type.CENTER_MODE) {
 603                                 /* if it is centermode, the exact SS Percentage
 604                                  * will be round up of half of the percentage
 605                                  * reported in the SS table */
 606                                 ++info->feature.memory_clk_ss_percentage;
 607                                 info->feature.memory_clk_ss_percentage /= 2;
 608                         }
 609                 }
 610         }
 611 
 612         /* There should be only one entry in the SS info table for Engine Clock
 613          */
 614         index = 1;
 615         if (firmware_info->usFirmwareCapability.sbfAccess.EngineClockSS_Support)
 616                 /* Since there is no information for external SS, report
 617                  * conservative value 3% for bandwidth calculation */
 618                 /* unit of 0.01% */
 619                 info->feature.engine_clk_ss_percentage = THREE_PERCENT_OF_10000;
 620         else if (get_ss_info_v3_1(bp,
 621                         ASIC_INTERNAL_ENGINE_SS, index, &internal_ss) == BP_RESULT_OK) {
 622                 if (internal_ss.spread_spectrum_percentage) {
 623                         info->feature.engine_clk_ss_percentage =
 624                                         internal_ss.spread_spectrum_percentage;
 625                         if (internal_ss.type.CENTER_MODE) {
 626                                 /* if it is centermode, the exact SS Percentage
 627                                  * will be round up of half of the percentage
 628                                  * reported in the SS table */
 629                                 ++info->feature.engine_clk_ss_percentage;
 630                                 info->feature.engine_clk_ss_percentage /= 2;
 631                         }
 632                 }
 633         }
 634 
 635         /* Remote Display */
 636         info->remote_display_config = firmware_info->ucRemoteDisplayConfig;
 637 
 638         /* Is allowed minimum BL level */
 639         info->min_allowed_bl_level = firmware_info->ucMinAllowedBL_Level;
 640         /* Used starting from CI */
 641         info->smu_gpu_pll_output_freq =
 642                         (uint32_t) (le32_to_cpu(firmware_info->ulGPUPLL_OutputFreq) * 10);
 643 
 644         return BP_RESULT_OK;
 645 }
 646 
 647 static enum bp_result get_ss_info_v3_1(
 648         struct bios_parser *bp,
 649         uint32_t id,
 650         uint32_t index,
 651         struct spread_spectrum_info *ss_info)
 652 {
 653         ATOM_ASIC_INTERNAL_SS_INFO_V3 *ss_table_header_include;
 654         ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
 655         uint32_t table_size;
 656         uint32_t i;
 657         uint32_t table_index = 0;
 658 
 659         if (!ss_info)
 660                 return BP_RESULT_BADINPUT;
 661 
 662         if (!DATA_TABLES(ASIC_InternalSS_Info))
 663                 return BP_RESULT_UNSUPPORTED;
 664 
 665         ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
 666                 DATA_TABLES(ASIC_InternalSS_Info));
 667         table_size =
 668                 (le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
 669                                 - sizeof(ATOM_COMMON_TABLE_HEADER))
 670                                 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
 671 
 672         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
 673                                 &ss_table_header_include->asSpreadSpectrum[0];
 674 
 675         memset(ss_info, 0, sizeof(struct spread_spectrum_info));
 676 
 677         for (i = 0; i < table_size; i++) {
 678                 if (tbl[i].ucClockIndication != (uint8_t) id)
 679                         continue;
 680 
 681                 if (table_index != index) {
 682                         table_index++;
 683                         continue;
 684                 }
 685                 /* VBIOS introduced new defines for Version 3, same values as
 686                  *  before, so now use these new ones for Version 3.
 687                  * Shouldn't affect field VBIOS's V3 as define values are still
 688                  *  same.
 689                  * #define SS_MODE_V3_CENTRE_SPREAD_MASK                0x01
 690                  * #define SS_MODE_V3_EXTERNAL_SS_MASK                  0x02
 691 
 692                  * Old VBIOS defines:
 693                  * #define ATOM_SS_CENTRE_SPREAD_MODE_MASK        0x00000001
 694                  * #define ATOM_EXTERNAL_SS_MASK                  0x00000002
 695                  */
 696 
 697                 if (SS_MODE_V3_EXTERNAL_SS_MASK & tbl[i].ucSpreadSpectrumMode)
 698                         ss_info->type.EXTERNAL = true;
 699 
 700                 if (SS_MODE_V3_CENTRE_SPREAD_MASK & tbl[i].ucSpreadSpectrumMode)
 701                         ss_info->type.CENTER_MODE = true;
 702 
 703                 /* Older VBIOS (in field) always provides SS percentage in 0.01%
 704                  * units set Divider to 100 */
 705                 ss_info->spread_percentage_divider = 100;
 706 
 707                 /* #define SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK 0x10 */
 708                 if (SS_MODE_V3_PERCENTAGE_DIV_BY_1000_MASK
 709                                 & tbl[i].ucSpreadSpectrumMode)
 710                         ss_info->spread_percentage_divider = 1000;
 711 
 712                 ss_info->type.STEP_AND_DELAY_INFO = false;
 713                 /* convert [10KHz] into [KHz] */
 714                 ss_info->target_clock_range =
 715                                 le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
 716                 ss_info->spread_spectrum_percentage =
 717                                 (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
 718                 ss_info->spread_spectrum_range =
 719                                 (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
 720 
 721                 return BP_RESULT_OK;
 722         }
 723         return BP_RESULT_NORECORD;
 724 }
 725 
 726 static enum bp_result bios_parser_transmitter_control(
 727         struct dc_bios *dcb,
 728         struct bp_transmitter_control *cntl)
 729 {
 730         struct bios_parser *bp = BP_FROM_DCB(dcb);
 731 
 732         if (!bp->cmd_tbl.transmitter_control)
 733                 return BP_RESULT_FAILURE;
 734 
 735         return bp->cmd_tbl.transmitter_control(bp, cntl);
 736 }
 737 
 738 static enum bp_result bios_parser_encoder_control(
 739         struct dc_bios *dcb,
 740         struct bp_encoder_control *cntl)
 741 {
 742         struct bios_parser *bp = BP_FROM_DCB(dcb);
 743 
 744         if (!bp->cmd_tbl.dig_encoder_control)
 745                 return BP_RESULT_FAILURE;
 746 
 747         return bp->cmd_tbl.dig_encoder_control(bp, cntl);
 748 }
 749 
 750 static enum bp_result bios_parser_adjust_pixel_clock(
 751         struct dc_bios *dcb,
 752         struct bp_adjust_pixel_clock_parameters *bp_params)
 753 {
 754         struct bios_parser *bp = BP_FROM_DCB(dcb);
 755 
 756         if (!bp->cmd_tbl.adjust_display_pll)
 757                 return BP_RESULT_FAILURE;
 758 
 759         return bp->cmd_tbl.adjust_display_pll(bp, bp_params);
 760 }
 761 
 762 static enum bp_result bios_parser_set_pixel_clock(
 763         struct dc_bios *dcb,
 764         struct bp_pixel_clock_parameters *bp_params)
 765 {
 766         struct bios_parser *bp = BP_FROM_DCB(dcb);
 767 
 768         if (!bp->cmd_tbl.set_pixel_clock)
 769                 return BP_RESULT_FAILURE;
 770 
 771         return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
 772 }
 773 
 774 static enum bp_result bios_parser_set_dce_clock(
 775         struct dc_bios *dcb,
 776         struct bp_set_dce_clock_parameters *bp_params)
 777 {
 778         struct bios_parser *bp = BP_FROM_DCB(dcb);
 779 
 780         if (!bp->cmd_tbl.set_dce_clock)
 781                 return BP_RESULT_FAILURE;
 782 
 783         return bp->cmd_tbl.set_dce_clock(bp, bp_params);
 784 }
 785 
 786 static enum bp_result bios_parser_enable_spread_spectrum_on_ppll(
 787         struct dc_bios *dcb,
 788         struct bp_spread_spectrum_parameters *bp_params,
 789         bool enable)
 790 {
 791         struct bios_parser *bp = BP_FROM_DCB(dcb);
 792 
 793         if (!bp->cmd_tbl.enable_spread_spectrum_on_ppll)
 794                 return BP_RESULT_FAILURE;
 795 
 796         return bp->cmd_tbl.enable_spread_spectrum_on_ppll(
 797                         bp, bp_params, enable);
 798 
 799 }
 800 
 801 static enum bp_result bios_parser_program_crtc_timing(
 802         struct dc_bios *dcb,
 803         struct bp_hw_crtc_timing_parameters *bp_params)
 804 {
 805         struct bios_parser *bp = BP_FROM_DCB(dcb);
 806 
 807         if (!bp->cmd_tbl.set_crtc_timing)
 808                 return BP_RESULT_FAILURE;
 809 
 810         return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
 811 }
 812 
 813 static enum bp_result bios_parser_program_display_engine_pll(
 814         struct dc_bios *dcb,
 815         struct bp_pixel_clock_parameters *bp_params)
 816 {
 817         struct bios_parser *bp = BP_FROM_DCB(dcb);
 818 
 819         if (!bp->cmd_tbl.program_clock)
 820                 return BP_RESULT_FAILURE;
 821 
 822         return bp->cmd_tbl.program_clock(bp, bp_params);
 823 
 824 }
 825 
 826 
 827 static enum bp_result bios_parser_enable_crtc(
 828         struct dc_bios *dcb,
 829         enum controller_id id,
 830         bool enable)
 831 {
 832         struct bios_parser *bp = BP_FROM_DCB(dcb);
 833 
 834         if (!bp->cmd_tbl.enable_crtc)
 835                 return BP_RESULT_FAILURE;
 836 
 837         return bp->cmd_tbl.enable_crtc(bp, id, enable);
 838 }
 839 
 840 static enum bp_result bios_parser_enable_disp_power_gating(
 841         struct dc_bios *dcb,
 842         enum controller_id controller_id,
 843         enum bp_pipe_control_action action)
 844 {
 845         struct bios_parser *bp = BP_FROM_DCB(dcb);
 846 
 847         if (!bp->cmd_tbl.enable_disp_power_gating)
 848                 return BP_RESULT_FAILURE;
 849 
 850         return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
 851                 action);
 852 }
 853 
 854 static bool bios_parser_is_device_id_supported(
 855         struct dc_bios *dcb,
 856         struct device_id id)
 857 {
 858         struct bios_parser *bp = BP_FROM_DCB(dcb);
 859 
 860         uint32_t mask = get_support_mask_for_device_id(id);
 861 
 862         return (le16_to_cpu(bp->object_info_tbl.v1_1->usDeviceSupport) & mask) != 0;
 863 }
 864 
 865 static ATOM_HPD_INT_RECORD *get_hpd_record(struct bios_parser *bp,
 866         ATOM_OBJECT *object)
 867 {
 868         ATOM_COMMON_RECORD_HEADER *header;
 869         uint32_t offset;
 870 
 871         if (!object) {
 872                 BREAK_TO_DEBUGGER(); /* Invalid object */
 873                 return NULL;
 874         }
 875 
 876         offset = le16_to_cpu(object->usRecordOffset)
 877                         + bp->object_info_tbl_offset;
 878 
 879         for (;;) {
 880                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
 881 
 882                 if (!header)
 883                         return NULL;
 884 
 885                 if (LAST_RECORD_TYPE == header->ucRecordType ||
 886                         !header->ucRecordSize)
 887                         break;
 888 
 889                 if (ATOM_HPD_INT_RECORD_TYPE == header->ucRecordType
 890                         && sizeof(ATOM_HPD_INT_RECORD) <= header->ucRecordSize)
 891                         return (ATOM_HPD_INT_RECORD *) header;
 892 
 893                 offset += header->ucRecordSize;
 894         }
 895 
 896         return NULL;
 897 }
 898 
 899 static enum bp_result get_ss_info_from_ss_info_table(
 900         struct bios_parser *bp,
 901         uint32_t id,
 902         struct spread_spectrum_info *ss_info);
 903 static enum bp_result get_ss_info_from_tbl(
 904         struct bios_parser *bp,
 905         uint32_t id,
 906         struct spread_spectrum_info *ss_info);
 907 /**
 908  * bios_parser_get_spread_spectrum_info
 909  * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
 910  * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
 911  * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info ver 3.1,
 912  * there is only one entry for each signal /ss id.  However, there is
 913  * no planning of supporting multiple spread Sprectum entry for EverGreen
 914  * @param [in] this
 915  * @param [in] signal, ASSignalType to be converted to info index
 916  * @param [in] index, number of entries that match the converted info index
 917  * @param [out] ss_info, sprectrum information structure,
 918  * @return Bios parser result code
 919  */
 920 static enum bp_result bios_parser_get_spread_spectrum_info(
 921         struct dc_bios *dcb,
 922         enum as_signal_type signal,
 923         uint32_t index,
 924         struct spread_spectrum_info *ss_info)
 925 {
 926         struct bios_parser *bp = BP_FROM_DCB(dcb);
 927         enum bp_result result = BP_RESULT_UNSUPPORTED;
 928         uint32_t clk_id_ss = 0;
 929         ATOM_COMMON_TABLE_HEADER *header;
 930         struct atom_data_revision tbl_revision;
 931 
 932         if (!ss_info) /* check for bad input */
 933                 return BP_RESULT_BADINPUT;
 934         /* signal translation */
 935         clk_id_ss = signal_to_ss_id(signal);
 936 
 937         if (!DATA_TABLES(ASIC_InternalSS_Info))
 938                 if (!index)
 939                         return get_ss_info_from_ss_info_table(bp, clk_id_ss,
 940                                 ss_info);
 941 
 942         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
 943                 DATA_TABLES(ASIC_InternalSS_Info));
 944         get_atom_data_table_revision(header, &tbl_revision);
 945 
 946         switch (tbl_revision.major) {
 947         case 2:
 948                 switch (tbl_revision.minor) {
 949                 case 1:
 950                         /* there can not be more then one entry for Internal
 951                          * SS Info table version 2.1 */
 952                         if (!index)
 953                                 return get_ss_info_from_tbl(bp, clk_id_ss,
 954                                                 ss_info);
 955                         break;
 956                 default:
 957                         break;
 958                 }
 959                 break;
 960 
 961         case 3:
 962                 switch (tbl_revision.minor) {
 963                 case 1:
 964                         return get_ss_info_v3_1(bp, clk_id_ss, index, ss_info);
 965                 default:
 966                         break;
 967                 }
 968                 break;
 969         default:
 970                 break;
 971         }
 972         /* there can not be more then one entry for SS Info table */
 973         return result;
 974 }
 975 
 976 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
 977         struct bios_parser *bp,
 978         uint32_t id,
 979         struct spread_spectrum_info *info);
 980 
 981 /**
 982  * get_ss_info_from_table
 983  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
 984  * SS_Info table from the VBIOS
 985  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
 986  * SS_Info.
 987  *
 988  * @param this
 989  * @param id, spread sprectrum info index
 990  * @param pSSinfo, sprectrum information structure,
 991  * @return Bios parser result code
 992  */
 993 static enum bp_result get_ss_info_from_tbl(
 994         struct bios_parser *bp,
 995         uint32_t id,
 996         struct spread_spectrum_info *ss_info)
 997 {
 998         if (!ss_info) /* check for bad input, if ss_info is not NULL */
 999                 return BP_RESULT_BADINPUT;
1000         /* for SS_Info table only support DP and LVDS */
1001         if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1002                 return get_ss_info_from_ss_info_table(bp, id, ss_info);
1003         else
1004                 return get_ss_info_from_internal_ss_info_tbl_V2_1(bp, id,
1005                         ss_info);
1006 }
1007 
1008 /**
1009  * get_ss_info_from_internal_ss_info_tbl_V2_1
1010  * Get spread sprectrum information from the ASIC_InternalSS_Info table Ver 2.1
1011  * from the VBIOS
1012  * There will not be multiple entry for Ver 2.1
1013  *
1014  * @param id, spread sprectrum info index
1015  * @param pSSinfo, sprectrum information structure,
1016  * @return Bios parser result code
1017  */
1018 static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
1019         struct bios_parser *bp,
1020         uint32_t id,
1021         struct spread_spectrum_info *info)
1022 {
1023         enum bp_result result = BP_RESULT_UNSUPPORTED;
1024         ATOM_ASIC_INTERNAL_SS_INFO_V2 *header;
1025         ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1026         uint32_t tbl_size, i;
1027 
1028         if (!DATA_TABLES(ASIC_InternalSS_Info))
1029                 return result;
1030 
1031         header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1032                 DATA_TABLES(ASIC_InternalSS_Info));
1033 
1034         memset(info, 0, sizeof(struct spread_spectrum_info));
1035 
1036         tbl_size = (le16_to_cpu(header->sHeader.usStructureSize)
1037                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1038                                         / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1039 
1040         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1041                                         &(header->asSpreadSpectrum[0]);
1042         for (i = 0; i < tbl_size; i++) {
1043                 result = BP_RESULT_NORECORD;
1044 
1045                 if (tbl[i].ucClockIndication != (uint8_t)id)
1046                         continue;
1047 
1048                 if (ATOM_EXTERNAL_SS_MASK
1049                         & tbl[i].ucSpreadSpectrumMode) {
1050                         info->type.EXTERNAL = true;
1051                 }
1052                 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK
1053                         & tbl[i].ucSpreadSpectrumMode) {
1054                         info->type.CENTER_MODE = true;
1055                 }
1056                 info->type.STEP_AND_DELAY_INFO = false;
1057                 /* convert [10KHz] into [KHz] */
1058                 info->target_clock_range =
1059                         le32_to_cpu(tbl[i].ulTargetClockRange) * 10;
1060                 info->spread_spectrum_percentage =
1061                         (uint32_t)le16_to_cpu(tbl[i].usSpreadSpectrumPercentage);
1062                 info->spread_spectrum_range =
1063                         (uint32_t)(le16_to_cpu(tbl[i].usSpreadRateIn10Hz) * 10);
1064                 result = BP_RESULT_OK;
1065                 break;
1066         }
1067 
1068         return result;
1069 
1070 }
1071 
1072 /**
1073  * get_ss_info_from_ss_info_table
1074  * Get spread sprectrum information from the SS_Info table from the VBIOS
1075  * if the pointer to info is NULL, indicate the caller what to know the number
1076  * of entries that matches the id
1077  * for, the SS_Info table, there should not be more than 1 entry match.
1078  *
1079  * @param [in] id, spread sprectrum id
1080  * @param [out] pSSinfo, sprectrum information structure,
1081  * @return Bios parser result code
1082  */
1083 static enum bp_result get_ss_info_from_ss_info_table(
1084         struct bios_parser *bp,
1085         uint32_t id,
1086         struct spread_spectrum_info *ss_info)
1087 {
1088         enum bp_result result = BP_RESULT_UNSUPPORTED;
1089         ATOM_SPREAD_SPECTRUM_INFO *tbl;
1090         ATOM_COMMON_TABLE_HEADER *header;
1091         uint32_t table_size;
1092         uint32_t i;
1093         uint32_t id_local = SS_ID_UNKNOWN;
1094         struct atom_data_revision revision;
1095 
1096         /* exist of the SS_Info table */
1097         /* check for bad input, pSSinfo can not be NULL */
1098         if (!DATA_TABLES(SS_Info) || !ss_info)
1099                 return result;
1100 
1101         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(SS_Info));
1102         get_atom_data_table_revision(header, &revision);
1103 
1104         tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO, DATA_TABLES(SS_Info));
1105 
1106         if (1 != revision.major || 2 > revision.minor)
1107                 return result;
1108 
1109         /* have to convert from Internal_SS format to SS_Info format */
1110         switch (id) {
1111         case ASIC_INTERNAL_SS_ON_DP:
1112                 id_local = SS_ID_DP1;
1113                 break;
1114         case ASIC_INTERNAL_SS_ON_LVDS:
1115         {
1116                 struct embedded_panel_info panel_info;
1117 
1118                 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1119                                 == BP_RESULT_OK)
1120                         id_local = panel_info.ss_id;
1121                 break;
1122         }
1123         default:
1124                 break;
1125         }
1126 
1127         if (id_local == SS_ID_UNKNOWN)
1128                 return result;
1129 
1130         table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1131                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
1132                                         sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1133 
1134         for (i = 0; i < table_size; i++) {
1135                 if (id_local != (uint32_t)tbl->asSS_Info[i].ucSS_Id)
1136                         continue;
1137 
1138                 memset(ss_info, 0, sizeof(struct spread_spectrum_info));
1139 
1140                 if (ATOM_EXTERNAL_SS_MASK &
1141                                 tbl->asSS_Info[i].ucSpreadSpectrumType)
1142                         ss_info->type.EXTERNAL = true;
1143 
1144                 if (ATOM_SS_CENTRE_SPREAD_MODE_MASK &
1145                                 tbl->asSS_Info[i].ucSpreadSpectrumType)
1146                         ss_info->type.CENTER_MODE = true;
1147 
1148                 ss_info->type.STEP_AND_DELAY_INFO = true;
1149                 ss_info->spread_spectrum_percentage =
1150                         (uint32_t)le16_to_cpu(tbl->asSS_Info[i].usSpreadSpectrumPercentage);
1151                 ss_info->step_and_delay_info.step = tbl->asSS_Info[i].ucSS_Step;
1152                 ss_info->step_and_delay_info.delay =
1153                         tbl->asSS_Info[i].ucSS_Delay;
1154                 ss_info->step_and_delay_info.recommended_ref_div =
1155                         tbl->asSS_Info[i].ucRecommendedRef_Div;
1156                 ss_info->spread_spectrum_range =
1157                         (uint32_t)tbl->asSS_Info[i].ucSS_Range * 10000;
1158 
1159                 /* there will be only one entry for each display type in SS_info
1160                  * table */
1161                 result = BP_RESULT_OK;
1162                 break;
1163         }
1164 
1165         return result;
1166 }
1167 static enum bp_result get_embedded_panel_info_v1_2(
1168         struct bios_parser *bp,
1169         struct embedded_panel_info *info);
1170 static enum bp_result get_embedded_panel_info_v1_3(
1171         struct bios_parser *bp,
1172         struct embedded_panel_info *info);
1173 
1174 static enum bp_result bios_parser_get_embedded_panel_info(
1175         struct dc_bios *dcb,
1176         struct embedded_panel_info *info)
1177 {
1178         struct bios_parser *bp = BP_FROM_DCB(dcb);
1179         ATOM_COMMON_TABLE_HEADER *hdr;
1180 
1181         if (!DATA_TABLES(LCD_Info))
1182                 return BP_RESULT_FAILURE;
1183 
1184         hdr = GET_IMAGE(ATOM_COMMON_TABLE_HEADER, DATA_TABLES(LCD_Info));
1185 
1186         if (!hdr)
1187                 return BP_RESULT_BADBIOSTABLE;
1188 
1189         switch (hdr->ucTableFormatRevision) {
1190         case 1:
1191                 switch (hdr->ucTableContentRevision) {
1192                 case 0:
1193                 case 1:
1194                 case 2:
1195                         return get_embedded_panel_info_v1_2(bp, info);
1196                 case 3:
1197                         return get_embedded_panel_info_v1_3(bp, info);
1198                 default:
1199                         break;
1200                 }
1201         default:
1202                 break;
1203         }
1204 
1205         return BP_RESULT_FAILURE;
1206 }
1207 
1208 static enum bp_result get_embedded_panel_info_v1_2(
1209         struct bios_parser *bp,
1210         struct embedded_panel_info *info)
1211 {
1212         ATOM_LVDS_INFO_V12 *lvds;
1213 
1214         if (!info)
1215                 return BP_RESULT_BADINPUT;
1216 
1217         if (!DATA_TABLES(LVDS_Info))
1218                 return BP_RESULT_UNSUPPORTED;
1219 
1220         lvds =
1221                 GET_IMAGE(ATOM_LVDS_INFO_V12, DATA_TABLES(LVDS_Info));
1222 
1223         if (!lvds)
1224                 return BP_RESULT_BADBIOSTABLE;
1225 
1226         if (1 != lvds->sHeader.ucTableFormatRevision
1227                 || 2 > lvds->sHeader.ucTableContentRevision)
1228                 return BP_RESULT_UNSUPPORTED;
1229 
1230         memset(info, 0, sizeof(struct embedded_panel_info));
1231 
1232         /* We need to convert from 10KHz units into KHz units*/
1233         info->lcd_timing.pixel_clk =
1234                 le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1235         /* usHActive does not include borders, according to VBIOS team*/
1236         info->lcd_timing.horizontal_addressable =
1237                 le16_to_cpu(lvds->sLCDTiming.usHActive);
1238         /* usHBlanking_Time includes borders, so we should really be subtracting
1239          * borders duing this translation, but LVDS generally*/
1240         /* doesn't have borders, so we should be okay leaving this as is for
1241          * now.  May need to revisit if we ever have LVDS with borders*/
1242         info->lcd_timing.horizontal_blanking_time =
1243                         le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1244         /* usVActive does not include borders, according to VBIOS team*/
1245         info->lcd_timing.vertical_addressable =
1246                         le16_to_cpu(lvds->sLCDTiming.usVActive);
1247         /* usVBlanking_Time includes borders, so we should really be subtracting
1248          * borders duing this translation, but LVDS generally*/
1249         /* doesn't have borders, so we should be okay leaving this as is for
1250          * now. May need to revisit if we ever have LVDS with borders*/
1251         info->lcd_timing.vertical_blanking_time =
1252                 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1253         info->lcd_timing.horizontal_sync_offset =
1254                 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1255         info->lcd_timing.horizontal_sync_width =
1256                 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1257         info->lcd_timing.vertical_sync_offset =
1258                 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1259         info->lcd_timing.vertical_sync_width =
1260                 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1261         info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1262         info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1263         info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1264                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1265         info->lcd_timing.misc_info.H_SYNC_POLARITY =
1266                 ~(uint32_t)
1267                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1268         info->lcd_timing.misc_info.V_SYNC_POLARITY =
1269                 ~(uint32_t)
1270                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1271         info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1272                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1273         info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1274                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1275         info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1276                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1277         info->lcd_timing.misc_info.COMPOSITE_SYNC =
1278                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1279         info->lcd_timing.misc_info.INTERLACE =
1280                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1281         info->lcd_timing.misc_info.DOUBLE_CLOCK =
1282                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1283         info->ss_id = lvds->ucSS_Id;
1284 
1285         {
1286                 uint8_t rr = le16_to_cpu(lvds->usSupportedRefreshRate);
1287                 /* Get minimum supported refresh rate*/
1288                 if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1289                         info->supported_rr.REFRESH_RATE_30HZ = 1;
1290                 else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1291                         info->supported_rr.REFRESH_RATE_40HZ = 1;
1292                 else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1293                         info->supported_rr.REFRESH_RATE_48HZ = 1;
1294                 else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1295                         info->supported_rr.REFRESH_RATE_50HZ = 1;
1296                 else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1297                         info->supported_rr.REFRESH_RATE_60HZ = 1;
1298         }
1299 
1300         /*Drr panel support can be reported by VBIOS*/
1301         if (LCDPANEL_CAP_DRR_SUPPORTED
1302                         & lvds->ucLCDPanel_SpecialHandlingCap)
1303                 info->drr_enabled = 1;
1304 
1305         if (ATOM_PANEL_MISC_DUAL & lvds->ucLVDS_Misc)
1306                 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1307 
1308         if (ATOM_PANEL_MISC_888RGB & lvds->ucLVDS_Misc)
1309                 info->lcd_timing.misc_info.RGB888 = true;
1310 
1311         info->lcd_timing.misc_info.GREY_LEVEL =
1312                 (uint32_t) (ATOM_PANEL_MISC_GREY_LEVEL &
1313                         lvds->ucLVDS_Misc) >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT;
1314 
1315         if (ATOM_PANEL_MISC_SPATIAL & lvds->ucLVDS_Misc)
1316                 info->lcd_timing.misc_info.SPATIAL = true;
1317 
1318         if (ATOM_PANEL_MISC_TEMPORAL & lvds->ucLVDS_Misc)
1319                 info->lcd_timing.misc_info.TEMPORAL = true;
1320 
1321         if (ATOM_PANEL_MISC_API_ENABLED & lvds->ucLVDS_Misc)
1322                 info->lcd_timing.misc_info.API_ENABLED = true;
1323 
1324         return BP_RESULT_OK;
1325 }
1326 
1327 static enum bp_result get_embedded_panel_info_v1_3(
1328         struct bios_parser *bp,
1329         struct embedded_panel_info *info)
1330 {
1331         ATOM_LCD_INFO_V13 *lvds;
1332 
1333         if (!info)
1334                 return BP_RESULT_BADINPUT;
1335 
1336         if (!DATA_TABLES(LCD_Info))
1337                 return BP_RESULT_UNSUPPORTED;
1338 
1339         lvds = GET_IMAGE(ATOM_LCD_INFO_V13, DATA_TABLES(LCD_Info));
1340 
1341         if (!lvds)
1342                 return BP_RESULT_BADBIOSTABLE;
1343 
1344         if (!((1 == lvds->sHeader.ucTableFormatRevision)
1345                         && (3 <= lvds->sHeader.ucTableContentRevision)))
1346                 return BP_RESULT_UNSUPPORTED;
1347 
1348         memset(info, 0, sizeof(struct embedded_panel_info));
1349 
1350         /* We need to convert from 10KHz units into KHz units */
1351         info->lcd_timing.pixel_clk =
1352                         le16_to_cpu(lvds->sLCDTiming.usPixClk) * 10;
1353         /* usHActive does not include borders, according to VBIOS team */
1354         info->lcd_timing.horizontal_addressable =
1355                         le16_to_cpu(lvds->sLCDTiming.usHActive);
1356         /* usHBlanking_Time includes borders, so we should really be subtracting
1357          * borders duing this translation, but LVDS generally*/
1358         /* doesn't have borders, so we should be okay leaving this as is for
1359          * now.  May need to revisit if we ever have LVDS with borders*/
1360         info->lcd_timing.horizontal_blanking_time =
1361                 le16_to_cpu(lvds->sLCDTiming.usHBlanking_Time);
1362         /* usVActive does not include borders, according to VBIOS team*/
1363         info->lcd_timing.vertical_addressable =
1364                 le16_to_cpu(lvds->sLCDTiming.usVActive);
1365         /* usVBlanking_Time includes borders, so we should really be subtracting
1366          * borders duing this translation, but LVDS generally*/
1367         /* doesn't have borders, so we should be okay leaving this as is for
1368          * now. May need to revisit if we ever have LVDS with borders*/
1369         info->lcd_timing.vertical_blanking_time =
1370                 le16_to_cpu(lvds->sLCDTiming.usVBlanking_Time);
1371         info->lcd_timing.horizontal_sync_offset =
1372                 le16_to_cpu(lvds->sLCDTiming.usHSyncOffset);
1373         info->lcd_timing.horizontal_sync_width =
1374                 le16_to_cpu(lvds->sLCDTiming.usHSyncWidth);
1375         info->lcd_timing.vertical_sync_offset =
1376                 le16_to_cpu(lvds->sLCDTiming.usVSyncOffset);
1377         info->lcd_timing.vertical_sync_width =
1378                 le16_to_cpu(lvds->sLCDTiming.usVSyncWidth);
1379         info->lcd_timing.horizontal_border = lvds->sLCDTiming.ucHBorder;
1380         info->lcd_timing.vertical_border = lvds->sLCDTiming.ucVBorder;
1381         info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF =
1382                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HorizontalCutOff;
1383         info->lcd_timing.misc_info.H_SYNC_POLARITY =
1384                 ~(uint32_t)
1385                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.HSyncPolarity;
1386         info->lcd_timing.misc_info.V_SYNC_POLARITY =
1387                 ~(uint32_t)
1388                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VSyncPolarity;
1389         info->lcd_timing.misc_info.VERTICAL_CUT_OFF =
1390                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.VerticalCutOff;
1391         info->lcd_timing.misc_info.H_REPLICATION_BY2 =
1392                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.H_ReplicationBy2;
1393         info->lcd_timing.misc_info.V_REPLICATION_BY2 =
1394                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.V_ReplicationBy2;
1395         info->lcd_timing.misc_info.COMPOSITE_SYNC =
1396                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.CompositeSync;
1397         info->lcd_timing.misc_info.INTERLACE =
1398                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.Interlace;
1399         info->lcd_timing.misc_info.DOUBLE_CLOCK =
1400                 lvds->sLCDTiming.susModeMiscInfo.sbfAccess.DoubleClock;
1401         info->ss_id = lvds->ucSS_Id;
1402 
1403         /* Drr panel support can be reported by VBIOS*/
1404         if (LCDPANEL_CAP_V13_DRR_SUPPORTED
1405                         & lvds->ucLCDPanel_SpecialHandlingCap)
1406                 info->drr_enabled = 1;
1407 
1408         /* Get supported refresh rate*/
1409         if (info->drr_enabled == 1) {
1410                 uint8_t min_rr =
1411                                 lvds->sRefreshRateSupport.ucMinRefreshRateForDRR;
1412                 uint8_t rr = lvds->sRefreshRateSupport.ucSupportedRefreshRate;
1413 
1414                 if (min_rr != 0) {
1415                         if (SUPPORTED_LCD_REFRESHRATE_30Hz & min_rr)
1416                                 info->supported_rr.REFRESH_RATE_30HZ = 1;
1417                         else if (SUPPORTED_LCD_REFRESHRATE_40Hz & min_rr)
1418                                 info->supported_rr.REFRESH_RATE_40HZ = 1;
1419                         else if (SUPPORTED_LCD_REFRESHRATE_48Hz & min_rr)
1420                                 info->supported_rr.REFRESH_RATE_48HZ = 1;
1421                         else if (SUPPORTED_LCD_REFRESHRATE_50Hz & min_rr)
1422                                 info->supported_rr.REFRESH_RATE_50HZ = 1;
1423                         else if (SUPPORTED_LCD_REFRESHRATE_60Hz & min_rr)
1424                                 info->supported_rr.REFRESH_RATE_60HZ = 1;
1425                 } else {
1426                         if (SUPPORTED_LCD_REFRESHRATE_30Hz & rr)
1427                                 info->supported_rr.REFRESH_RATE_30HZ = 1;
1428                         else if (SUPPORTED_LCD_REFRESHRATE_40Hz & rr)
1429                                 info->supported_rr.REFRESH_RATE_40HZ = 1;
1430                         else if (SUPPORTED_LCD_REFRESHRATE_48Hz & rr)
1431                                 info->supported_rr.REFRESH_RATE_48HZ = 1;
1432                         else if (SUPPORTED_LCD_REFRESHRATE_50Hz & rr)
1433                                 info->supported_rr.REFRESH_RATE_50HZ = 1;
1434                         else if (SUPPORTED_LCD_REFRESHRATE_60Hz & rr)
1435                                 info->supported_rr.REFRESH_RATE_60HZ = 1;
1436                 }
1437         }
1438 
1439         if (ATOM_PANEL_MISC_V13_DUAL & lvds->ucLCD_Misc)
1440                 info->lcd_timing.misc_info.DOUBLE_CLOCK = true;
1441 
1442         if (ATOM_PANEL_MISC_V13_8BIT_PER_COLOR & lvds->ucLCD_Misc)
1443                 info->lcd_timing.misc_info.RGB888 = true;
1444 
1445         info->lcd_timing.misc_info.GREY_LEVEL =
1446                         (uint32_t) (ATOM_PANEL_MISC_V13_GREY_LEVEL &
1447                                 lvds->ucLCD_Misc) >> ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT;
1448 
1449         return BP_RESULT_OK;
1450 }
1451 
1452 /**
1453  * bios_parser_get_encoder_cap_info
1454  *
1455  * @brief
1456  *  Get encoder capability information of input object id
1457  *
1458  * @param object_id, Object id
1459  * @param object_id, encoder cap information structure
1460  *
1461  * @return Bios parser result code
1462  *
1463  */
1464 static enum bp_result bios_parser_get_encoder_cap_info(
1465         struct dc_bios *dcb,
1466         struct graphics_object_id object_id,
1467         struct bp_encoder_cap_info *info)
1468 {
1469         struct bios_parser *bp = BP_FROM_DCB(dcb);
1470         ATOM_OBJECT *object;
1471         ATOM_ENCODER_CAP_RECORD_V2 *record = NULL;
1472 
1473         if (!info)
1474                 return BP_RESULT_BADINPUT;
1475 
1476         object = get_bios_object(bp, object_id);
1477 
1478         if (!object)
1479                 return BP_RESULT_BADINPUT;
1480 
1481         record = get_encoder_cap_record(bp, object);
1482         if (!record)
1483                 return BP_RESULT_NORECORD;
1484 
1485         info->DP_HBR2_EN = record->usHBR2En;
1486         info->DP_HBR3_EN = record->usHBR3En;
1487         info->HDMI_6GB_EN = record->usHDMI6GEn;
1488         return BP_RESULT_OK;
1489 }
1490 
1491 /**
1492  * get_encoder_cap_record
1493  *
1494  * @brief
1495  *  Get encoder cap record for the object
1496  *
1497  * @param object, ATOM object
1498  *
1499  * @return atom encoder cap record
1500  *
1501  * @note
1502  *  search all records to find the ATOM_ENCODER_CAP_RECORD_V2 record
1503  */
1504 static ATOM_ENCODER_CAP_RECORD_V2 *get_encoder_cap_record(
1505         struct bios_parser *bp,
1506         ATOM_OBJECT *object)
1507 {
1508         ATOM_COMMON_RECORD_HEADER *header;
1509         uint32_t offset;
1510 
1511         if (!object) {
1512                 BREAK_TO_DEBUGGER(); /* Invalid object */
1513                 return NULL;
1514         }
1515 
1516         offset = le16_to_cpu(object->usRecordOffset)
1517                                         + bp->object_info_tbl_offset;
1518 
1519         for (;;) {
1520                 header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, offset);
1521 
1522                 if (!header)
1523                         return NULL;
1524 
1525                 offset += header->ucRecordSize;
1526 
1527                 if (LAST_RECORD_TYPE == header->ucRecordType ||
1528                                 !header->ucRecordSize)
1529                         break;
1530 
1531                 if (ATOM_ENCODER_CAP_RECORD_TYPE != header->ucRecordType)
1532                         continue;
1533 
1534                 if (sizeof(ATOM_ENCODER_CAP_RECORD_V2) <= header->ucRecordSize)
1535                         return (ATOM_ENCODER_CAP_RECORD_V2 *)header;
1536         }
1537 
1538         return NULL;
1539 }
1540 
1541 static uint32_t get_ss_entry_number(
1542         struct bios_parser *bp,
1543         uint32_t id);
1544 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1545         struct bios_parser *bp,
1546         uint32_t id);
1547 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1548         struct bios_parser *bp,
1549         uint32_t id);
1550 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1551         struct bios_parser *bp,
1552         uint32_t id);
1553 
1554 /**
1555  * BiosParserObject::GetNumberofSpreadSpectrumEntry
1556  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table from
1557  * the VBIOS that match the SSid (to be converted from signal)
1558  *
1559  * @param[in] signal, ASSignalType to be converted to SSid
1560  * @return number of SS Entry that match the signal
1561  */
1562 static uint32_t bios_parser_get_ss_entry_number(
1563         struct dc_bios *dcb,
1564         enum as_signal_type signal)
1565 {
1566         struct bios_parser *bp = BP_FROM_DCB(dcb);
1567         uint32_t ss_id = 0;
1568         ATOM_COMMON_TABLE_HEADER *header;
1569         struct atom_data_revision revision;
1570 
1571         ss_id = signal_to_ss_id(signal);
1572 
1573         if (!DATA_TABLES(ASIC_InternalSS_Info))
1574                 return get_ss_entry_number_from_ss_info_tbl(bp, ss_id);
1575 
1576         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1577                         DATA_TABLES(ASIC_InternalSS_Info));
1578         get_atom_data_table_revision(header, &revision);
1579 
1580         switch (revision.major) {
1581         case 2:
1582                 switch (revision.minor) {
1583                 case 1:
1584                         return get_ss_entry_number(bp, ss_id);
1585                 default:
1586                         break;
1587                 }
1588                 break;
1589         case 3:
1590                 switch (revision.minor) {
1591                 case 1:
1592                         return
1593                                 get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1594                                                 bp, ss_id);
1595                 default:
1596                         break;
1597                 }
1598                 break;
1599         default:
1600                 break;
1601         }
1602 
1603         return 0;
1604 }
1605 
1606 /**
1607  * get_ss_entry_number_from_ss_info_tbl
1608  * Get Number of spread spectrum entry from the SS_Info table from the VBIOS.
1609  *
1610  * @note There can only be one entry for each id for SS_Info Table
1611  *
1612  * @param [in] id, spread spectrum id
1613  * @return number of SS Entry that match the id
1614  */
1615 static uint32_t get_ss_entry_number_from_ss_info_tbl(
1616         struct bios_parser *bp,
1617         uint32_t id)
1618 {
1619         ATOM_SPREAD_SPECTRUM_INFO *tbl;
1620         ATOM_COMMON_TABLE_HEADER *header;
1621         uint32_t table_size;
1622         uint32_t i;
1623         uint32_t number = 0;
1624         uint32_t id_local = SS_ID_UNKNOWN;
1625         struct atom_data_revision revision;
1626 
1627         /* SS_Info table exist */
1628         if (!DATA_TABLES(SS_Info))
1629                 return number;
1630 
1631         header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
1632                         DATA_TABLES(SS_Info));
1633         get_atom_data_table_revision(header, &revision);
1634 
1635         tbl = GET_IMAGE(ATOM_SPREAD_SPECTRUM_INFO,
1636                         DATA_TABLES(SS_Info));
1637 
1638         if (1 != revision.major || 2 > revision.minor)
1639                 return number;
1640 
1641         /* have to convert from Internal_SS format to SS_Info format */
1642         switch (id) {
1643         case ASIC_INTERNAL_SS_ON_DP:
1644                 id_local = SS_ID_DP1;
1645                 break;
1646         case ASIC_INTERNAL_SS_ON_LVDS: {
1647                 struct embedded_panel_info panel_info;
1648 
1649                 if (bios_parser_get_embedded_panel_info(&bp->base, &panel_info)
1650                                 == BP_RESULT_OK)
1651                         id_local = panel_info.ss_id;
1652                 break;
1653         }
1654         default:
1655                 break;
1656         }
1657 
1658         if (id_local == SS_ID_UNKNOWN)
1659                 return number;
1660 
1661         table_size = (le16_to_cpu(tbl->sHeader.usStructureSize) -
1662                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
1663                                         sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
1664 
1665         for (i = 0; i < table_size; i++)
1666                 if (id_local == (uint32_t)tbl->asSS_Info[i].ucSS_Id) {
1667                         number = 1;
1668                         break;
1669                 }
1670 
1671         return number;
1672 }
1673 
1674 /**
1675  * get_ss_entry_number
1676  * Get spread sprectrum information from the ASIC_InternalSS_Info Ver 2.1 or
1677  * SS_Info table from the VBIOS
1678  * There can not be more than 1 entry for  ASIC_InternalSS_Info Ver 2.1 or
1679  * SS_Info.
1680  *
1681  * @param id, spread sprectrum info index
1682  * @return Bios parser result code
1683  */
1684 static uint32_t get_ss_entry_number(struct bios_parser *bp, uint32_t id)
1685 {
1686         if (id == ASIC_INTERNAL_SS_ON_DP || id == ASIC_INTERNAL_SS_ON_LVDS)
1687                 return get_ss_entry_number_from_ss_info_tbl(bp, id);
1688 
1689         return get_ss_entry_number_from_internal_ss_info_tbl_v2_1(bp, id);
1690 }
1691 
1692 /**
1693  * get_ss_entry_number_from_internal_ss_info_tbl_v2_1
1694  * Get NUmber of spread sprectrum entry from the ASIC_InternalSS_Info table
1695  * Ver 2.1 from the VBIOS
1696  * There will not be multiple entry for Ver 2.1
1697  *
1698  * @param id, spread sprectrum info index
1699  * @return number of SS Entry that match the id
1700  */
1701 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
1702         struct bios_parser *bp,
1703         uint32_t id)
1704 {
1705         ATOM_ASIC_INTERNAL_SS_INFO_V2 *header_include;
1706         ATOM_ASIC_SS_ASSIGNMENT_V2 *tbl;
1707         uint32_t size;
1708         uint32_t i;
1709 
1710         if (!DATA_TABLES(ASIC_InternalSS_Info))
1711                 return 0;
1712 
1713         header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
1714                         DATA_TABLES(ASIC_InternalSS_Info));
1715 
1716         size = (le16_to_cpu(header_include->sHeader.usStructureSize)
1717                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1718                                                 / sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
1719 
1720         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V2 *)
1721                                 &header_include->asSpreadSpectrum[0];
1722         for (i = 0; i < size; i++)
1723                 if (tbl[i].ucClockIndication == (uint8_t)id)
1724                         return 1;
1725 
1726         return 0;
1727 }
1728 /**
1729  * get_ss_entry_number_from_internal_ss_info_table_V3_1
1730  * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of
1731  * the VBIOS that matches id
1732  *
1733  * @param[in]  id, spread sprectrum id
1734  * @return number of SS Entry that match the id
1735  */
1736 static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
1737         struct bios_parser *bp,
1738         uint32_t id)
1739 {
1740         uint32_t number = 0;
1741         ATOM_ASIC_INTERNAL_SS_INFO_V3 *header_include;
1742         ATOM_ASIC_SS_ASSIGNMENT_V3 *tbl;
1743         uint32_t size;
1744         uint32_t i;
1745 
1746         if (!DATA_TABLES(ASIC_InternalSS_Info))
1747                 return number;
1748 
1749         header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
1750                         DATA_TABLES(ASIC_InternalSS_Info));
1751         size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
1752                         sizeof(ATOM_COMMON_TABLE_HEADER)) /
1753                                         sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
1754 
1755         tbl = (ATOM_ASIC_SS_ASSIGNMENT_V3 *)
1756                                 &header_include->asSpreadSpectrum[0];
1757 
1758         for (i = 0; i < size; i++)
1759                 if (tbl[i].ucClockIndication == (uint8_t)id)
1760                         number++;
1761 
1762         return number;
1763 }
1764 
1765 /**
1766  * bios_parser_get_gpio_pin_info
1767  * Get GpioPin information of input gpio id
1768  *
1769  * @param gpio_id, GPIO ID
1770  * @param info, GpioPin information structure
1771  * @return Bios parser result code
1772  * @note
1773  *  to get the GPIO PIN INFO, we need:
1774  *  1. get the GPIO_ID from other object table, see GetHPDInfo()
1775  *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records, to get the registerA
1776  *  offset/mask
1777  */
1778 static enum bp_result bios_parser_get_gpio_pin_info(
1779         struct dc_bios *dcb,
1780         uint32_t gpio_id,
1781         struct gpio_pin_info *info)
1782 {
1783         struct bios_parser *bp = BP_FROM_DCB(dcb);
1784         ATOM_GPIO_PIN_LUT *header;
1785         uint32_t count = 0;
1786         uint32_t i = 0;
1787 
1788         if (!DATA_TABLES(GPIO_Pin_LUT))
1789                 return BP_RESULT_BADBIOSTABLE;
1790 
1791         header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
1792         if (!header)
1793                 return BP_RESULT_BADBIOSTABLE;
1794 
1795         if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
1796                         > le16_to_cpu(header->sHeader.usStructureSize))
1797                 return BP_RESULT_BADBIOSTABLE;
1798 
1799         if (1 != header->sHeader.ucTableContentRevision)
1800                 return BP_RESULT_UNSUPPORTED;
1801 
1802         count = (le16_to_cpu(header->sHeader.usStructureSize)
1803                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1804                                 / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
1805         for (i = 0; i < count; ++i) {
1806                 if (header->asGPIO_Pin[i].ucGPIO_ID != gpio_id)
1807                         continue;
1808 
1809                 info->offset =
1810                         (uint32_t) le16_to_cpu(header->asGPIO_Pin[i].usGpioPin_AIndex);
1811                 info->offset_y = info->offset + 2;
1812                 info->offset_en = info->offset + 1;
1813                 info->offset_mask = info->offset - 1;
1814 
1815                 info->mask = (uint32_t) (1 <<
1816                         header->asGPIO_Pin[i].ucGpioPinBitShift);
1817                 info->mask_y = info->mask + 2;
1818                 info->mask_en = info->mask + 1;
1819                 info->mask_mask = info->mask - 1;
1820 
1821                 return BP_RESULT_OK;
1822         }
1823 
1824         return BP_RESULT_NORECORD;
1825 }
1826 
1827 static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
1828         ATOM_I2C_RECORD *record,
1829         struct graphics_object_i2c_info *info)
1830 {
1831         ATOM_GPIO_I2C_INFO *header;
1832         uint32_t count = 0;
1833 
1834         if (!info)
1835                 return BP_RESULT_BADINPUT;
1836 
1837         /* get the GPIO_I2C info */
1838         if (!DATA_TABLES(GPIO_I2C_Info))
1839                 return BP_RESULT_BADBIOSTABLE;
1840 
1841         header = GET_IMAGE(ATOM_GPIO_I2C_INFO, DATA_TABLES(GPIO_I2C_Info));
1842         if (!header)
1843                 return BP_RESULT_BADBIOSTABLE;
1844 
1845         if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_I2C_ASSIGMENT)
1846                         > le16_to_cpu(header->sHeader.usStructureSize))
1847                 return BP_RESULT_BADBIOSTABLE;
1848 
1849         if (1 != header->sHeader.ucTableContentRevision)
1850                 return BP_RESULT_UNSUPPORTED;
1851 
1852         /* get data count */
1853         count = (le16_to_cpu(header->sHeader.usStructureSize)
1854                         - sizeof(ATOM_COMMON_TABLE_HEADER))
1855                                 / sizeof(ATOM_GPIO_I2C_ASSIGMENT);
1856         if (count < record->sucI2cId.bfI2C_LineMux)
1857                 return BP_RESULT_BADBIOSTABLE;
1858 
1859         /* get the GPIO_I2C_INFO */
1860         info->i2c_hw_assist = record->sucI2cId.bfHW_Capable;
1861         info->i2c_line = record->sucI2cId.bfI2C_LineMux;
1862         info->i2c_engine_id = record->sucI2cId.bfHW_EngineID;
1863         info->i2c_slave_address = record->ucI2CAddr;
1864 
1865         info->gpio_info.clk_mask_register_index =
1866                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkMaskRegisterIndex);
1867         info->gpio_info.clk_en_register_index =
1868                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkEnRegisterIndex);
1869         info->gpio_info.clk_y_register_index =
1870                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkY_RegisterIndex);
1871         info->gpio_info.clk_a_register_index =
1872                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usClkA_RegisterIndex);
1873         info->gpio_info.data_mask_register_index =
1874                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataMaskRegisterIndex);
1875         info->gpio_info.data_en_register_index =
1876                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataEnRegisterIndex);
1877         info->gpio_info.data_y_register_index =
1878                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataY_RegisterIndex);
1879         info->gpio_info.data_a_register_index =
1880                         le16_to_cpu(header->asGPIO_Info[info->i2c_line].usDataA_RegisterIndex);
1881 
1882         info->gpio_info.clk_mask_shift =
1883                         header->asGPIO_Info[info->i2c_line].ucClkMaskShift;
1884         info->gpio_info.clk_en_shift =
1885                         header->asGPIO_Info[info->i2c_line].ucClkEnShift;
1886         info->gpio_info.clk_y_shift =
1887                         header->asGPIO_Info[info->i2c_line].ucClkY_Shift;
1888         info->gpio_info.clk_a_shift =
1889                         header->asGPIO_Info[info->i2c_line].ucClkA_Shift;
1890         info->gpio_info.data_mask_shift =
1891                         header->asGPIO_Info[info->i2c_line].ucDataMaskShift;
1892         info->gpio_info.data_en_shift =
1893                         header->asGPIO_Info[info->i2c_line].ucDataEnShift;
1894         info->gpio_info.data_y_shift =
1895                         header->asGPIO_Info[info->i2c_line].ucDataY_Shift;
1896         info->gpio_info.data_a_shift =
1897                         header->asGPIO_Info[info->i2c_line].ucDataA_Shift;
1898 
1899         return BP_RESULT_OK;
1900 }
1901 
1902 static bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
1903 {
1904         bool rc = true;
1905 
1906         switch (id.type) {
1907         case OBJECT_TYPE_UNKNOWN:
1908                 rc = false;
1909                 break;
1910         case OBJECT_TYPE_GPU:
1911         case OBJECT_TYPE_ENGINE:
1912                 /* do NOT check for id.id == 0 */
1913                 if (id.enum_id == ENUM_ID_UNKNOWN)
1914                         rc = false;
1915                 break;
1916         default:
1917                 if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
1918                         rc = false;
1919                 break;
1920         }
1921 
1922         return rc;
1923 }
1924 
1925 static bool dal_graphics_object_id_is_equal(
1926         struct graphics_object_id id1,
1927         struct graphics_object_id id2)
1928 {
1929         if (false == dal_graphics_object_id_is_valid(id1)) {
1930                 dm_output_to_console(
1931                 "%s: Warning: comparing invalid object 'id1'!\n", __func__);
1932                 return false;
1933         }
1934 
1935         if (false == dal_graphics_object_id_is_valid(id2)) {
1936                 dm_output_to_console(
1937                 "%s: Warning: comparing invalid object 'id2'!\n", __func__);
1938                 return false;
1939         }
1940 
1941         if (id1.id == id2.id && id1.enum_id == id2.enum_id
1942                 && id1.type == id2.type)
1943                 return true;
1944 
1945         return false;
1946 }
1947 
1948 static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
1949         struct graphics_object_id id)
1950 {
1951         uint32_t offset;
1952         ATOM_OBJECT_TABLE *tbl;
1953         uint32_t i;
1954 
1955         switch (id.type) {
1956         case OBJECT_TYPE_ENCODER:
1957                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usEncoderObjectTableOffset);
1958                 break;
1959 
1960         case OBJECT_TYPE_CONNECTOR:
1961                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
1962                 break;
1963 
1964         case OBJECT_TYPE_ROUTER:
1965                 offset = le16_to_cpu(bp->object_info_tbl.v1_1->usRouterObjectTableOffset);
1966                 break;
1967 
1968         case OBJECT_TYPE_GENERIC:
1969                 if (bp->object_info_tbl.revision.minor < 3)
1970                         return NULL;
1971                 offset = le16_to_cpu(bp->object_info_tbl.v1_3->usMiscObjectTableOffset);
1972                 break;
1973 
1974         default:
1975                 return NULL;
1976         }
1977 
1978         offset += bp->object_info_tbl_offset;
1979 
1980         tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
1981         if (!tbl)
1982                 return NULL;
1983 
1984         for (i = 0; i < tbl->ucNumberOfObjects; i++)
1985                 if (dal_graphics_object_id_is_equal(id,
1986                                 object_id_from_bios_object_id(
1987                                                 le16_to_cpu(tbl->asObjects[i].usObjectID))))
1988                         return &tbl->asObjects[i];
1989 
1990         return NULL;
1991 }
1992 
1993 static uint32_t get_src_obj_list(struct bios_parser *bp, ATOM_OBJECT *object,
1994         uint16_t **id_list)
1995 {
1996         uint32_t offset;
1997         uint8_t *number;
1998 
1999         if (!object) {
2000                 BREAK_TO_DEBUGGER(); /* Invalid object id */
2001                 return 0;
2002         }
2003 
2004         offset = le16_to_cpu(object->usSrcDstTableOffset)
2005                                         + bp->object_info_tbl_offset;
2006 
2007         number = GET_IMAGE(uint8_t, offset);
2008         if (!number)
2009                 return 0;
2010 
2011         offset += sizeof(uint8_t);
2012         *id_list = (uint16_t *)bios_get_image(&bp->base, offset, *number * sizeof(uint16_t));
2013 
2014         if (!*id_list)
2015                 return 0;
2016 
2017         return *number;
2018 }
2019 
2020 static struct device_id device_type_from_device_id(uint16_t device_id)
2021 {
2022 
2023         struct device_id result_device_id = {0};
2024 
2025         switch (device_id) {
2026         case ATOM_DEVICE_LCD1_SUPPORT:
2027                 result_device_id.device_type = DEVICE_TYPE_LCD;
2028                 result_device_id.enum_id = 1;
2029                 break;
2030 
2031         case ATOM_DEVICE_LCD2_SUPPORT:
2032                 result_device_id.device_type = DEVICE_TYPE_LCD;
2033                 result_device_id.enum_id = 2;
2034                 break;
2035 
2036         case ATOM_DEVICE_CRT1_SUPPORT:
2037                 result_device_id.device_type = DEVICE_TYPE_CRT;
2038                 result_device_id.enum_id = 1;
2039                 break;
2040 
2041         case ATOM_DEVICE_CRT2_SUPPORT:
2042                 result_device_id.device_type = DEVICE_TYPE_CRT;
2043                 result_device_id.enum_id = 2;
2044                 break;
2045 
2046         case ATOM_DEVICE_DFP1_SUPPORT:
2047                 result_device_id.device_type = DEVICE_TYPE_DFP;
2048                 result_device_id.enum_id = 1;
2049                 break;
2050 
2051         case ATOM_DEVICE_DFP2_SUPPORT:
2052                 result_device_id.device_type = DEVICE_TYPE_DFP;
2053                 result_device_id.enum_id = 2;
2054                 break;
2055 
2056         case ATOM_DEVICE_DFP3_SUPPORT:
2057                 result_device_id.device_type = DEVICE_TYPE_DFP;
2058                 result_device_id.enum_id = 3;
2059                 break;
2060 
2061         case ATOM_DEVICE_DFP4_SUPPORT:
2062                 result_device_id.device_type = DEVICE_TYPE_DFP;
2063                 result_device_id.enum_id = 4;
2064                 break;
2065 
2066         case ATOM_DEVICE_DFP5_SUPPORT:
2067                 result_device_id.device_type = DEVICE_TYPE_DFP;
2068                 result_device_id.enum_id = 5;
2069                 break;
2070 
2071         case ATOM_DEVICE_DFP6_SUPPORT:
2072                 result_device_id.device_type = DEVICE_TYPE_DFP;
2073                 result_device_id.enum_id = 6;
2074                 break;
2075 
2076         default:
2077                 BREAK_TO_DEBUGGER(); /* Invalid device Id */
2078                 result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
2079                 result_device_id.enum_id = 0;
2080         }
2081         return result_device_id;
2082 }
2083 
2084 static void get_atom_data_table_revision(
2085         ATOM_COMMON_TABLE_HEADER *atom_data_tbl,
2086         struct atom_data_revision *tbl_revision)
2087 {
2088         if (!tbl_revision)
2089                 return;
2090 
2091         /* initialize the revision to 0 which is invalid revision */
2092         tbl_revision->major = 0;
2093         tbl_revision->minor = 0;
2094 
2095         if (!atom_data_tbl)
2096                 return;
2097 
2098         tbl_revision->major =
2099                         (uint32_t) GET_DATA_TABLE_MAJOR_REVISION(atom_data_tbl);
2100         tbl_revision->minor =
2101                         (uint32_t) GET_DATA_TABLE_MINOR_REVISION(atom_data_tbl);
2102 }
2103 
2104 static uint32_t signal_to_ss_id(enum as_signal_type signal)
2105 {
2106         uint32_t clk_id_ss = 0;
2107 
2108         switch (signal) {
2109         case AS_SIGNAL_TYPE_DVI:
2110                 clk_id_ss = ASIC_INTERNAL_SS_ON_TMDS;
2111                 break;
2112         case AS_SIGNAL_TYPE_HDMI:
2113                 clk_id_ss = ASIC_INTERNAL_SS_ON_HDMI;
2114                 break;
2115         case AS_SIGNAL_TYPE_LVDS:
2116                 clk_id_ss = ASIC_INTERNAL_SS_ON_LVDS;
2117                 break;
2118         case AS_SIGNAL_TYPE_DISPLAY_PORT:
2119                 clk_id_ss = ASIC_INTERNAL_SS_ON_DP;
2120                 break;
2121         case AS_SIGNAL_TYPE_GPU_PLL:
2122                 clk_id_ss = ASIC_INTERNAL_GPUPLL_SS;
2123                 break;
2124         default:
2125                 break;
2126         }
2127         return clk_id_ss;
2128 }
2129 
2130 static uint32_t get_support_mask_for_device_id(struct device_id device_id)
2131 {
2132         enum dal_device_type device_type = device_id.device_type;
2133         uint32_t enum_id = device_id.enum_id;
2134 
2135         switch (device_type) {
2136         case DEVICE_TYPE_LCD:
2137                 switch (enum_id) {
2138                 case 1:
2139                         return ATOM_DEVICE_LCD1_SUPPORT;
2140                 case 2:
2141                         return ATOM_DEVICE_LCD2_SUPPORT;
2142                 default:
2143                         break;
2144                 }
2145                 break;
2146         case DEVICE_TYPE_CRT:
2147                 switch (enum_id) {
2148                 case 1:
2149                         return ATOM_DEVICE_CRT1_SUPPORT;
2150                 case 2:
2151                         return ATOM_DEVICE_CRT2_SUPPORT;
2152                 default:
2153                         break;
2154                 }
2155                 break;
2156         case DEVICE_TYPE_DFP:
2157                 switch (enum_id) {
2158                 case 1:
2159                         return ATOM_DEVICE_DFP1_SUPPORT;
2160                 case 2:
2161                         return ATOM_DEVICE_DFP2_SUPPORT;
2162                 case 3:
2163                         return ATOM_DEVICE_DFP3_SUPPORT;
2164                 case 4:
2165                         return ATOM_DEVICE_DFP4_SUPPORT;
2166                 case 5:
2167                         return ATOM_DEVICE_DFP5_SUPPORT;
2168                 case 6:
2169                         return ATOM_DEVICE_DFP6_SUPPORT;
2170                 default:
2171                         break;
2172                 }
2173                 break;
2174         case DEVICE_TYPE_CV:
2175                 switch (enum_id) {
2176                 case 1:
2177                         return ATOM_DEVICE_CV_SUPPORT;
2178                 default:
2179                         break;
2180                 }
2181                 break;
2182         case DEVICE_TYPE_TV:
2183                 switch (enum_id) {
2184                 case 1:
2185                         return ATOM_DEVICE_TV1_SUPPORT;
2186                 default:
2187                         break;
2188                 }
2189                 break;
2190         default:
2191                 break;
2192         };
2193 
2194         /* Unidentified device ID, return empty support mask. */
2195         return 0;
2196 }
2197 
2198 /**
2199  * bios_parser_set_scratch_critical_state
2200  *
2201  * @brief
2202  *  update critical state bit in VBIOS scratch register
2203  *
2204  * @param
2205  *  bool - to set or reset state
2206  */
2207 static void bios_parser_set_scratch_critical_state(
2208         struct dc_bios *dcb,
2209         bool state)
2210 {
2211         bios_set_scratch_critical_state(dcb, state);
2212 }
2213 
2214 /*
2215  * get_integrated_info_v8
2216  *
2217  * @brief
2218  * Get V8 integrated BIOS information
2219  *
2220  * @param
2221  * bios_parser *bp - [in]BIOS parser handler to get master data table
2222  * integrated_info *info - [out] store and output integrated info
2223  *
2224  * @return
2225  * enum bp_result - BP_RESULT_OK if information is available,
2226  *                  BP_RESULT_BADBIOSTABLE otherwise.
2227  */
2228 static enum bp_result get_integrated_info_v8(
2229         struct bios_parser *bp,
2230         struct integrated_info *info)
2231 {
2232         ATOM_INTEGRATED_SYSTEM_INFO_V1_8 *info_v8;
2233         uint32_t i;
2234 
2235         info_v8 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_8,
2236                         bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2237 
2238         if (info_v8 == NULL)
2239                 return BP_RESULT_BADBIOSTABLE;
2240         info->boot_up_engine_clock = le32_to_cpu(info_v8->ulBootUpEngineClock) * 10;
2241         info->dentist_vco_freq = le32_to_cpu(info_v8->ulDentistVCOFreq) * 10;
2242         info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
2243 
2244         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2245                 /* Convert [10KHz] into [KHz] */
2246                 info->disp_clk_voltage[i].max_supported_clk =
2247                         le32_to_cpu(info_v8->sDISPCLK_Voltage[i].
2248                                     ulMaximumSupportedCLK) * 10;
2249                 info->disp_clk_voltage[i].voltage_index =
2250                         le32_to_cpu(info_v8->sDISPCLK_Voltage[i].ulVoltageIndex);
2251         }
2252 
2253         info->boot_up_req_display_vector =
2254                 le32_to_cpu(info_v8->ulBootUpReqDisplayVector);
2255         info->gpu_cap_info =
2256                 le32_to_cpu(info_v8->ulGPUCapInfo);
2257 
2258         /*
2259          * system_config: Bit[0] = 0 : PCIE power gating disabled
2260          *                       = 1 : PCIE power gating enabled
2261          *                Bit[1] = 0 : DDR-PLL shut down disabled
2262          *                       = 1 : DDR-PLL shut down enabled
2263          *                Bit[2] = 0 : DDR-PLL power down disabled
2264          *                       = 1 : DDR-PLL power down enabled
2265          */
2266         info->system_config = le32_to_cpu(info_v8->ulSystemConfig);
2267         info->cpu_cap_info = le32_to_cpu(info_v8->ulCPUCapInfo);
2268         info->boot_up_nb_voltage =
2269                 le16_to_cpu(info_v8->usBootUpNBVoltage);
2270         info->ext_disp_conn_info_offset =
2271                 le16_to_cpu(info_v8->usExtDispConnInfoOffset);
2272         info->memory_type = info_v8->ucMemoryType;
2273         info->ma_channel_number = info_v8->ucUMAChannelNumber;
2274         info->gmc_restore_reset_time =
2275                 le32_to_cpu(info_v8->ulGMCRestoreResetTime);
2276 
2277         info->minimum_n_clk =
2278                 le32_to_cpu(info_v8->ulNbpStateNClkFreq[0]);
2279         for (i = 1; i < 4; ++i)
2280                 info->minimum_n_clk =
2281                         info->minimum_n_clk < le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]) ?
2282                         info->minimum_n_clk : le32_to_cpu(info_v8->ulNbpStateNClkFreq[i]);
2283 
2284         info->idle_n_clk = le32_to_cpu(info_v8->ulIdleNClk);
2285         info->ddr_dll_power_up_time =
2286                 le32_to_cpu(info_v8->ulDDR_DLL_PowerUpTime);
2287         info->ddr_pll_power_up_time =
2288                 le32_to_cpu(info_v8->ulDDR_PLL_PowerUpTime);
2289         info->pcie_clk_ss_type = le16_to_cpu(info_v8->usPCIEClkSSType);
2290         info->lvds_ss_percentage =
2291                 le16_to_cpu(info_v8->usLvdsSSPercentage);
2292         info->lvds_sspread_rate_in_10hz =
2293                 le16_to_cpu(info_v8->usLvdsSSpreadRateIn10Hz);
2294         info->hdmi_ss_percentage =
2295                 le16_to_cpu(info_v8->usHDMISSPercentage);
2296         info->hdmi_sspread_rate_in_10hz =
2297                 le16_to_cpu(info_v8->usHDMISSpreadRateIn10Hz);
2298         info->dvi_ss_percentage =
2299                 le16_to_cpu(info_v8->usDVISSPercentage);
2300         info->dvi_sspread_rate_in_10_hz =
2301                 le16_to_cpu(info_v8->usDVISSpreadRateIn10Hz);
2302 
2303         info->max_lvds_pclk_freq_in_single_link =
2304                 le16_to_cpu(info_v8->usMaxLVDSPclkFreqInSingleLink);
2305         info->lvds_misc = info_v8->ucLvdsMisc;
2306         info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2307                 info_v8->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2308         info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2309                 info_v8->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2310         info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2311                 info_v8->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2312         info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2313                 info_v8->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2314         info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2315                 info_v8->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2316         info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2317                 info_v8->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2318         info->lvds_off_to_on_delay_in_4ms =
2319                 info_v8->ucLVDSOffToOnDelay_in4Ms;
2320         info->lvds_bit_depth_control_val =
2321                 le32_to_cpu(info_v8->ulLCDBitDepthControlVal);
2322 
2323         for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2324                 /* Convert [10KHz] into [KHz] */
2325                 info->avail_s_clk[i].supported_s_clk =
2326                         le32_to_cpu(info_v8->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2327                 info->avail_s_clk[i].voltage_index =
2328                         le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageIndex);
2329                 info->avail_s_clk[i].voltage_id =
2330                         le16_to_cpu(info_v8->sAvail_SCLK[i].usVoltageID);
2331         }
2332 
2333         for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2334                 info->ext_disp_conn_info.gu_id[i] =
2335                         info_v8->sExtDispConnInfo.ucGuid[i];
2336         }
2337 
2338         for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2339                 info->ext_disp_conn_info.path[i].device_connector_id =
2340                         object_id_from_bios_object_id(
2341                                 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceConnector));
2342 
2343                 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2344                         object_id_from_bios_object_id(
2345                                 le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2346 
2347                 info->ext_disp_conn_info.path[i].device_tag =
2348                         le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceTag);
2349                 info->ext_disp_conn_info.path[i].device_acpi_enum =
2350                         le16_to_cpu(info_v8->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2351                 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2352                         info_v8->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2353                 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2354                         info_v8->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2355                 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2356                         info_v8->sExtDispConnInfo.sPath[i].ucChannelMapping;
2357         }
2358         info->ext_disp_conn_info.checksum =
2359                 info_v8->sExtDispConnInfo.ucChecksum;
2360 
2361         return BP_RESULT_OK;
2362 }
2363 
2364 /*
2365  * get_integrated_info_v8
2366  *
2367  * @brief
2368  * Get V8 integrated BIOS information
2369  *
2370  * @param
2371  * bios_parser *bp - [in]BIOS parser handler to get master data table
2372  * integrated_info *info - [out] store and output integrated info
2373  *
2374  * @return
2375  * enum bp_result - BP_RESULT_OK if information is available,
2376  *                  BP_RESULT_BADBIOSTABLE otherwise.
2377  */
2378 static enum bp_result get_integrated_info_v9(
2379         struct bios_parser *bp,
2380         struct integrated_info *info)
2381 {
2382         ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info_v9;
2383         uint32_t i;
2384 
2385         info_v9 = GET_IMAGE(ATOM_INTEGRATED_SYSTEM_INFO_V1_9,
2386                         bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2387 
2388         if (!info_v9)
2389                 return BP_RESULT_BADBIOSTABLE;
2390 
2391         info->boot_up_engine_clock = le32_to_cpu(info_v9->ulBootUpEngineClock) * 10;
2392         info->dentist_vco_freq = le32_to_cpu(info_v9->ulDentistVCOFreq) * 10;
2393         info->boot_up_uma_clock = le32_to_cpu(info_v9->ulBootUpUMAClock) * 10;
2394 
2395         for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2396                 /* Convert [10KHz] into [KHz] */
2397                 info->disp_clk_voltage[i].max_supported_clk =
2398                         le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulMaximumSupportedCLK) * 10;
2399                 info->disp_clk_voltage[i].voltage_index =
2400                         le32_to_cpu(info_v9->sDISPCLK_Voltage[i].ulVoltageIndex);
2401         }
2402 
2403         info->boot_up_req_display_vector =
2404                 le32_to_cpu(info_v9->ulBootUpReqDisplayVector);
2405         info->gpu_cap_info = le32_to_cpu(info_v9->ulGPUCapInfo);
2406 
2407         /*
2408          * system_config: Bit[0] = 0 : PCIE power gating disabled
2409          *                       = 1 : PCIE power gating enabled
2410          *                Bit[1] = 0 : DDR-PLL shut down disabled
2411          *                       = 1 : DDR-PLL shut down enabled
2412          *                Bit[2] = 0 : DDR-PLL power down disabled
2413          *                       = 1 : DDR-PLL power down enabled
2414          */
2415         info->system_config = le32_to_cpu(info_v9->ulSystemConfig);
2416         info->cpu_cap_info = le32_to_cpu(info_v9->ulCPUCapInfo);
2417         info->boot_up_nb_voltage = le16_to_cpu(info_v9->usBootUpNBVoltage);
2418         info->ext_disp_conn_info_offset = le16_to_cpu(info_v9->usExtDispConnInfoOffset);
2419         info->memory_type = info_v9->ucMemoryType;
2420         info->ma_channel_number = info_v9->ucUMAChannelNumber;
2421         info->gmc_restore_reset_time = le32_to_cpu(info_v9->ulGMCRestoreResetTime);
2422 
2423         info->minimum_n_clk = le32_to_cpu(info_v9->ulNbpStateNClkFreq[0]);
2424         for (i = 1; i < 4; ++i)
2425                 info->minimum_n_clk =
2426                         info->minimum_n_clk < le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]) ?
2427                         info->minimum_n_clk : le32_to_cpu(info_v9->ulNbpStateNClkFreq[i]);
2428 
2429         info->idle_n_clk = le32_to_cpu(info_v9->ulIdleNClk);
2430         info->ddr_dll_power_up_time = le32_to_cpu(info_v9->ulDDR_DLL_PowerUpTime);
2431         info->ddr_pll_power_up_time = le32_to_cpu(info_v9->ulDDR_PLL_PowerUpTime);
2432         info->pcie_clk_ss_type = le16_to_cpu(info_v9->usPCIEClkSSType);
2433         info->lvds_ss_percentage = le16_to_cpu(info_v9->usLvdsSSPercentage);
2434         info->lvds_sspread_rate_in_10hz = le16_to_cpu(info_v9->usLvdsSSpreadRateIn10Hz);
2435         info->hdmi_ss_percentage = le16_to_cpu(info_v9->usHDMISSPercentage);
2436         info->hdmi_sspread_rate_in_10hz = le16_to_cpu(info_v9->usHDMISSpreadRateIn10Hz);
2437         info->dvi_ss_percentage = le16_to_cpu(info_v9->usDVISSPercentage);
2438         info->dvi_sspread_rate_in_10_hz = le16_to_cpu(info_v9->usDVISSpreadRateIn10Hz);
2439 
2440         info->max_lvds_pclk_freq_in_single_link =
2441                 le16_to_cpu(info_v9->usMaxLVDSPclkFreqInSingleLink);
2442         info->lvds_misc = info_v9->ucLvdsMisc;
2443         info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
2444                 info_v9->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
2445         info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
2446                 info_v9->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
2447         info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
2448                 info_v9->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
2449         info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
2450                 info_v9->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
2451         info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
2452                 info_v9->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
2453         info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
2454                 info_v9->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
2455         info->lvds_off_to_on_delay_in_4ms =
2456                 info_v9->ucLVDSOffToOnDelay_in4Ms;
2457         info->lvds_bit_depth_control_val =
2458                 le32_to_cpu(info_v9->ulLCDBitDepthControlVal);
2459 
2460         for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
2461                 /* Convert [10KHz] into [KHz] */
2462                 info->avail_s_clk[i].supported_s_clk =
2463                         le32_to_cpu(info_v9->sAvail_SCLK[i].ulSupportedSCLK) * 10;
2464                 info->avail_s_clk[i].voltage_index =
2465                         le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageIndex);
2466                 info->avail_s_clk[i].voltage_id =
2467                         le16_to_cpu(info_v9->sAvail_SCLK[i].usVoltageID);
2468         }
2469 
2470         for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
2471                 info->ext_disp_conn_info.gu_id[i] =
2472                         info_v9->sExtDispConnInfo.ucGuid[i];
2473         }
2474 
2475         for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
2476                 info->ext_disp_conn_info.path[i].device_connector_id =
2477                         object_id_from_bios_object_id(
2478                                 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceConnector));
2479 
2480                 info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
2481                         object_id_from_bios_object_id(
2482                                 le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usExtEncoderObjId));
2483 
2484                 info->ext_disp_conn_info.path[i].device_tag =
2485                         le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceTag);
2486                 info->ext_disp_conn_info.path[i].device_acpi_enum =
2487                         le16_to_cpu(info_v9->sExtDispConnInfo.sPath[i].usDeviceACPIEnum);
2488                 info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
2489                         info_v9->sExtDispConnInfo.sPath[i].ucExtAUXDDCLutIndex;
2490                 info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
2491                         info_v9->sExtDispConnInfo.sPath[i].ucExtHPDPINLutIndex;
2492                 info->ext_disp_conn_info.path[i].channel_mapping.raw =
2493                         info_v9->sExtDispConnInfo.sPath[i].ucChannelMapping;
2494         }
2495         info->ext_disp_conn_info.checksum =
2496                 info_v9->sExtDispConnInfo.ucChecksum;
2497 
2498         return BP_RESULT_OK;
2499 }
2500 
2501 /*
2502  * construct_integrated_info
2503  *
2504  * @brief
2505  * Get integrated BIOS information based on table revision
2506  *
2507  * @param
2508  * bios_parser *bp - [in]BIOS parser handler to get master data table
2509  * integrated_info *info - [out] store and output integrated info
2510  *
2511  * @return
2512  * enum bp_result - BP_RESULT_OK if information is available,
2513  *                  BP_RESULT_BADBIOSTABLE otherwise.
2514  */
2515 static enum bp_result construct_integrated_info(
2516         struct bios_parser *bp,
2517         struct integrated_info *info)
2518 {
2519         enum bp_result result = BP_RESULT_BADBIOSTABLE;
2520 
2521         ATOM_COMMON_TABLE_HEADER *header;
2522         struct atom_data_revision revision;
2523 
2524         if (bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo) {
2525                 header = GET_IMAGE(ATOM_COMMON_TABLE_HEADER,
2526                                 bp->master_data_tbl->ListOfDataTables.IntegratedSystemInfo);
2527 
2528                 get_atom_data_table_revision(header, &revision);
2529 
2530                 /* Don't need to check major revision as they are all 1 */
2531                 switch (revision.minor) {
2532                 case 8:
2533                         result = get_integrated_info_v8(bp, info);
2534                         break;
2535                 case 9:
2536                         result = get_integrated_info_v9(bp, info);
2537                         break;
2538                 default:
2539                         return result;
2540 
2541                 }
2542         }
2543 
2544         /* Sort voltage table from low to high*/
2545         if (result == BP_RESULT_OK) {
2546                 struct clock_voltage_caps temp = {0, 0};
2547                 uint32_t i;
2548                 uint32_t j;
2549 
2550                 for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
2551                         for (j = i; j > 0; --j) {
2552                                 if (
2553                                                 info->disp_clk_voltage[j].max_supported_clk <
2554                                                 info->disp_clk_voltage[j-1].max_supported_clk) {
2555                                         /* swap j and j - 1*/
2556                                         temp = info->disp_clk_voltage[j-1];
2557                                         info->disp_clk_voltage[j-1] =
2558                                                         info->disp_clk_voltage[j];
2559                                         info->disp_clk_voltage[j] = temp;
2560                                 }
2561                         }
2562                 }
2563 
2564         }
2565 
2566         return result;
2567 }
2568 
2569 static struct integrated_info *bios_parser_create_integrated_info(
2570         struct dc_bios *dcb)
2571 {
2572         struct bios_parser *bp = BP_FROM_DCB(dcb);
2573         struct integrated_info *info = NULL;
2574 
2575         info = kzalloc(sizeof(struct integrated_info), GFP_KERNEL);
2576 
2577         if (info == NULL) {
2578                 ASSERT_CRITICAL(0);
2579                 return NULL;
2580         }
2581 
2582         if (construct_integrated_info(bp, info) == BP_RESULT_OK)
2583                 return info;
2584 
2585         kfree(info);
2586 
2587         return NULL;
2588 }
2589 
2590 enum bp_result update_slot_layout_info(
2591         struct dc_bios *dcb,
2592         unsigned int i,
2593         struct slot_layout_info *slot_layout_info,
2594         unsigned int record_offset)
2595 {
2596         unsigned int j;
2597         struct bios_parser *bp;
2598         ATOM_BRACKET_LAYOUT_RECORD *record;
2599         ATOM_COMMON_RECORD_HEADER *record_header;
2600         enum bp_result result = BP_RESULT_NORECORD;
2601 
2602         bp = BP_FROM_DCB(dcb);
2603         record = NULL;
2604         record_header = NULL;
2605 
2606         for (;;) {
2607 
2608                 record_header = (ATOM_COMMON_RECORD_HEADER *)
2609                         GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
2610                 if (record_header == NULL) {
2611                         result = BP_RESULT_BADBIOSTABLE;
2612                         break;
2613                 }
2614 
2615                 /* the end of the list */
2616                 if (record_header->ucRecordType == 0xff ||
2617                         record_header->ucRecordSize == 0)       {
2618                         break;
2619                 }
2620 
2621                 if (record_header->ucRecordType ==
2622                         ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
2623                         sizeof(ATOM_BRACKET_LAYOUT_RECORD)
2624                         <= record_header->ucRecordSize) {
2625                         record = (ATOM_BRACKET_LAYOUT_RECORD *)
2626                                 (record_header);
2627                         result = BP_RESULT_OK;
2628                         break;
2629                 }
2630 
2631                 record_offset += record_header->ucRecordSize;
2632         }
2633 
2634         /* return if the record not found */
2635         if (result != BP_RESULT_OK)
2636                 return result;
2637 
2638         /* get slot sizes */
2639         slot_layout_info->length = record->ucLength;
2640         slot_layout_info->width = record->ucWidth;
2641 
2642         /* get info for each connector in the slot */
2643         slot_layout_info->num_of_connectors = record->ucConnNum;
2644         for (j = 0; j < slot_layout_info->num_of_connectors; ++j) {
2645                 slot_layout_info->connectors[j].connector_type =
2646                         (enum connector_layout_type)
2647                         (record->asConnInfo[j].ucConnectorType);
2648                 switch (record->asConnInfo[j].ucConnectorType) {
2649                 case CONNECTOR_TYPE_DVI_D:
2650                         slot_layout_info->connectors[j].connector_type =
2651                                 CONNECTOR_LAYOUT_TYPE_DVI_D;
2652                         slot_layout_info->connectors[j].length =
2653                                 CONNECTOR_SIZE_DVI;
2654                         break;
2655 
2656                 case CONNECTOR_TYPE_HDMI:
2657                         slot_layout_info->connectors[j].connector_type =
2658                                 CONNECTOR_LAYOUT_TYPE_HDMI;
2659                         slot_layout_info->connectors[j].length =
2660                                 CONNECTOR_SIZE_HDMI;
2661                         break;
2662 
2663                 case CONNECTOR_TYPE_DISPLAY_PORT:
2664                         slot_layout_info->connectors[j].connector_type =
2665                                 CONNECTOR_LAYOUT_TYPE_DP;
2666                         slot_layout_info->connectors[j].length =
2667                                 CONNECTOR_SIZE_DP;
2668                         break;
2669 
2670                 case CONNECTOR_TYPE_MINI_DISPLAY_PORT:
2671                         slot_layout_info->connectors[j].connector_type =
2672                                 CONNECTOR_LAYOUT_TYPE_MINI_DP;
2673                         slot_layout_info->connectors[j].length =
2674                                 CONNECTOR_SIZE_MINI_DP;
2675                         break;
2676 
2677                 default:
2678                         slot_layout_info->connectors[j].connector_type =
2679                                 CONNECTOR_LAYOUT_TYPE_UNKNOWN;
2680                         slot_layout_info->connectors[j].length =
2681                                 CONNECTOR_SIZE_UNKNOWN;
2682                 }
2683 
2684                 slot_layout_info->connectors[j].position =
2685                         record->asConnInfo[j].ucPosition;
2686                 slot_layout_info->connectors[j].connector_id =
2687                         object_id_from_bios_object_id(
2688                                 record->asConnInfo[j].usConnectorObjectId);
2689         }
2690         return result;
2691 }
2692 
2693 
2694 enum bp_result get_bracket_layout_record(
2695         struct dc_bios *dcb,
2696         unsigned int bracket_layout_id,
2697         struct slot_layout_info *slot_layout_info)
2698 {
2699         unsigned int i;
2700         unsigned int record_offset;
2701         struct bios_parser *bp;
2702         enum bp_result result;
2703         ATOM_OBJECT *object;
2704         ATOM_OBJECT_TABLE *object_table;
2705         unsigned int genericTableOffset;
2706 
2707         bp = BP_FROM_DCB(dcb);
2708         object = NULL;
2709         if (slot_layout_info == NULL) {
2710                 DC_LOG_DETECTION_EDID_PARSER("Invalid slot_layout_info\n");
2711                 return BP_RESULT_BADINPUT;
2712         }
2713 
2714 
2715         genericTableOffset = bp->object_info_tbl_offset +
2716                 bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
2717         object_table = (ATOM_OBJECT_TABLE *)
2718                 GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset);
2719         if (!object_table)
2720                 return BP_RESULT_FAILURE;
2721 
2722         result = BP_RESULT_NORECORD;
2723         for (i = 0; i < object_table->ucNumberOfObjects; ++i) {
2724 
2725                 if (bracket_layout_id ==
2726                         object_table->asObjects[i].usObjectID) {
2727 
2728                         object = &object_table->asObjects[i];
2729                         record_offset = object->usRecordOffset +
2730                                 bp->object_info_tbl_offset;
2731 
2732                         result = update_slot_layout_info(dcb, i,
2733                                 slot_layout_info, record_offset);
2734                         break;
2735                 }
2736         }
2737         return result;
2738 }
2739 
2740 static enum bp_result bios_get_board_layout_info(
2741         struct dc_bios *dcb,
2742         struct board_layout_info *board_layout_info)
2743 {
2744         unsigned int i;
2745         struct bios_parser *bp;
2746         enum bp_result record_result;
2747 
2748         const unsigned int slot_index_to_vbios_id[MAX_BOARD_SLOTS] = {
2749                 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID1,
2750                 GENERICOBJECT_BRACKET_LAYOUT_ENUM_ID2,
2751                 0, 0
2752         };
2753 
2754         bp = BP_FROM_DCB(dcb);
2755         if (board_layout_info == NULL) {
2756                 DC_LOG_DETECTION_EDID_PARSER("Invalid board_layout_info\n");
2757                 return BP_RESULT_BADINPUT;
2758         }
2759 
2760         board_layout_info->num_of_slots = 0;
2761 
2762         for (i = 0; i < MAX_BOARD_SLOTS; ++i) {
2763                 record_result = get_bracket_layout_record(dcb,
2764                         slot_index_to_vbios_id[i],
2765                         &board_layout_info->slots[i]);
2766 
2767                 if (record_result == BP_RESULT_NORECORD && i > 0)
2768                         break; /* no more slots present in bios */
2769                 else if (record_result != BP_RESULT_OK)
2770                         return record_result;  /* fail */
2771 
2772                 ++board_layout_info->num_of_slots;
2773         }
2774 
2775         /* all data is valid */
2776         board_layout_info->is_number_of_slots_valid = 1;
2777         board_layout_info->is_slots_size_valid = 1;
2778         board_layout_info->is_connector_offsets_valid = 1;
2779         board_layout_info->is_connector_lengths_valid = 1;
2780 
2781         return BP_RESULT_OK;
2782 }
2783 
2784 /******************************************************************************/
2785 
2786 static const struct dc_vbios_funcs vbios_funcs = {
2787         .get_connectors_number = bios_parser_get_connectors_number,
2788 
2789         .get_connector_id = bios_parser_get_connector_id,
2790 
2791         .get_src_obj = bios_parser_get_src_obj,
2792 
2793         .get_i2c_info = bios_parser_get_i2c_info,
2794 
2795         .get_hpd_info = bios_parser_get_hpd_info,
2796 
2797         .get_device_tag = bios_parser_get_device_tag,
2798 
2799         .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
2800 
2801         .get_ss_entry_number = bios_parser_get_ss_entry_number,
2802 
2803         .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
2804 
2805         .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
2806 
2807         .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
2808 
2809         /* bios scratch register communication */
2810         .is_accelerated_mode = bios_is_accelerated_mode,
2811 
2812         .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
2813 
2814         .is_device_id_supported = bios_parser_is_device_id_supported,
2815 
2816         /* COMMANDS */
2817         .encoder_control = bios_parser_encoder_control,
2818 
2819         .transmitter_control = bios_parser_transmitter_control,
2820 
2821         .enable_crtc = bios_parser_enable_crtc,
2822 
2823         .adjust_pixel_clock = bios_parser_adjust_pixel_clock,
2824 
2825         .set_pixel_clock = bios_parser_set_pixel_clock,
2826 
2827         .set_dce_clock = bios_parser_set_dce_clock,
2828 
2829         .enable_spread_spectrum_on_ppll = bios_parser_enable_spread_spectrum_on_ppll,
2830 
2831         .program_crtc_timing = bios_parser_program_crtc_timing, /* still use.  should probably retire and program directly */
2832 
2833         .program_display_engine_pll = bios_parser_program_display_engine_pll,
2834 
2835         .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
2836 
2837         /* SW init and patch */
2838 
2839         .bios_parser_destroy = bios_parser_destroy,
2840 
2841         .get_board_layout_info = bios_get_board_layout_info,
2842 };
2843 
2844 static bool bios_parser_construct(
2845         struct bios_parser *bp,
2846         struct bp_init_data *init,
2847         enum dce_version dce_version)
2848 {
2849         uint16_t *rom_header_offset = NULL;
2850         ATOM_ROM_HEADER *rom_header = NULL;
2851         ATOM_OBJECT_HEADER *object_info_tbl;
2852         struct atom_data_revision tbl_rev = {0};
2853 
2854         if (!init)
2855                 return false;
2856 
2857         if (!init->bios)
2858                 return false;
2859 
2860         bp->base.funcs = &vbios_funcs;
2861         bp->base.bios = init->bios;
2862         bp->base.bios_size = bp->base.bios[BIOS_IMAGE_SIZE_OFFSET] * BIOS_IMAGE_SIZE_UNIT;
2863 
2864         bp->base.ctx = init->ctx;
2865         bp->base.bios_local_image = NULL;
2866 
2867         rom_header_offset =
2868         GET_IMAGE(uint16_t, OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER);
2869 
2870         if (!rom_header_offset)
2871                 return false;
2872 
2873         rom_header = GET_IMAGE(ATOM_ROM_HEADER, *rom_header_offset);
2874 
2875         if (!rom_header)
2876                 return false;
2877 
2878         get_atom_data_table_revision(&rom_header->sHeader, &tbl_rev);
2879         if (tbl_rev.major >= 2 && tbl_rev.minor >= 2)
2880                 return false;
2881 
2882         bp->master_data_tbl =
2883         GET_IMAGE(ATOM_MASTER_DATA_TABLE,
2884                 rom_header->usMasterDataTableOffset);
2885 
2886         if (!bp->master_data_tbl)
2887                 return false;
2888 
2889         bp->object_info_tbl_offset = DATA_TABLES(Object_Header);
2890 
2891         if (!bp->object_info_tbl_offset)
2892                 return false;
2893 
2894         object_info_tbl =
2895         GET_IMAGE(ATOM_OBJECT_HEADER, bp->object_info_tbl_offset);
2896 
2897         if (!object_info_tbl)
2898                 return false;
2899 
2900         get_atom_data_table_revision(&object_info_tbl->sHeader,
2901                 &bp->object_info_tbl.revision);
2902 
2903         if (bp->object_info_tbl.revision.major == 1
2904                 && bp->object_info_tbl.revision.minor >= 3) {
2905                 ATOM_OBJECT_HEADER_V3 *tbl_v3;
2906 
2907                 tbl_v3 = GET_IMAGE(ATOM_OBJECT_HEADER_V3,
2908                         bp->object_info_tbl_offset);
2909                 if (!tbl_v3)
2910                         return false;
2911 
2912                 bp->object_info_tbl.v1_3 = tbl_v3;
2913         } else if (bp->object_info_tbl.revision.major == 1
2914                 && bp->object_info_tbl.revision.minor >= 1)
2915                 bp->object_info_tbl.v1_1 = object_info_tbl;
2916         else
2917                 return false;
2918 
2919         dal_bios_parser_init_cmd_tbl(bp);
2920         dal_bios_parser_init_cmd_tbl_helper(&bp->cmd_helper, dce_version);
2921 
2922         bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
2923         bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK;
2924 
2925         return true;
2926 }
2927 
2928 /******************************************************************************/

/* [<][>][^][v][top][bottom][index][help] */