OSDN Git Service

drm/amd/display: Add DCE12 bios parser support
authorHarry Wentland <harry.wentland@amd.com>
Mon, 6 Mar 2017 19:29:52 +0000 (14:29 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 21:19:04 +0000 (17:19 -0400)
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/command_table2.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/command_table2.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h [new file with mode: 0644]

diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
new file mode 100644 (file)
index 0000000..f6e77da
--- /dev/null
@@ -0,0 +1,2085 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#define _BIOS_PARSER_2_
+
+#include "ObjectID.h"
+#include "atomfirmware.h"
+#include "atomfirmwareid.h"
+
+#include "dc_bios_types.h"
+#include "include/grph_object_ctrl_defs.h"
+#include "include/bios_parser_interface.h"
+#include "include/i2caux_interface.h"
+#include "include/logger_interface.h"
+
+#include "command_table2.h"
+
+#include "bios_parser_helper.h"
+#include "command_table_helper2.h"
+#include "bios_parser2.h"
+#include "bios_parser_types_internal2.h"
+#include "bios_parser_interface.h"
+
+#define LAST_RECORD_TYPE 0xff
+
+
+struct i2c_id_config_access {
+       uint8_t bfI2C_LineMux:4;
+       uint8_t bfHW_EngineID:3;
+       uint8_t bfHW_Capable:1;
+       uint8_t ucAccess;
+};
+
+static enum object_type object_type_from_bios_object_id(
+       uint32_t bios_object_id);
+
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id);
+
+static struct graphics_object_id object_id_from_bios_object_id(
+       uint32_t bios_object_id);
+
+static uint32_t id_from_bios_object_id(enum object_type type,
+       uint32_t bios_object_id);
+
+static uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id);
+
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id);
+
+static enum connector_id connector_id_from_bios_object_id(
+                                               uint32_t bios_object_id);
+
+static enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id);
+
+static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
+       struct atom_i2c_record *record,
+       struct graphics_object_i2c_info *info);
+
+static enum bp_result bios_parser_get_firmware_info(
+       struct dc_bios *dcb,
+       struct firmware_info *info);
+
+static enum bp_result bios_parser_get_encoder_cap_info(
+       struct dc_bios *dcb,
+       struct graphics_object_id object_id,
+       struct bp_encoder_cap_info *info);
+
+static enum bp_result get_firmware_info_v3_1(
+       struct bios_parser *bp,
+       struct firmware_info *info);
+
+static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
+               struct atom_display_object_path_v2 *object);
+
+static struct atom_encoder_caps_record *get_encoder_cap_record(
+       struct bios_parser *bp,
+       struct atom_display_object_path_v2 *object);
+
+#define BIOS_IMAGE_SIZE_OFFSET 2
+#define BIOS_IMAGE_SIZE_UNIT 512
+
+#define DATA_TABLES(table) (bp->master_data_tbl->listOfdatatables.table)
+
+
+static void destruct(struct bios_parser *bp)
+{
+       if (bp->base.bios_local_image)
+               dm_free(bp->base.bios_local_image);
+
+       if (bp->base.integrated_info)
+               dm_free(bp->base.integrated_info);
+}
+
+static void firmware_parser_destroy(struct dc_bios **dcb)
+{
+       struct bios_parser *bp = BP_FROM_DCB(*dcb);
+
+       if (!bp) {
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       destruct(bp);
+
+       dm_free(bp);
+       *dcb = NULL;
+}
+
+static void get_atom_data_table_revision(
+       struct atom_common_table_header *atom_data_tbl,
+       struct atom_data_revision *tbl_revision)
+{
+       if (!tbl_revision)
+               return;
+
+       /* initialize the revision to 0 which is invalid revision */
+       tbl_revision->major = 0;
+       tbl_revision->minor = 0;
+
+       if (!atom_data_tbl)
+               return;
+
+       tbl_revision->major =
+                       (uint32_t) atom_data_tbl->format_revision & 0x3f;
+       tbl_revision->minor =
+                       (uint32_t) atom_data_tbl->content_revision & 0x3f;
+}
+
+static struct graphics_object_id object_id_from_bios_object_id(
+       uint32_t bios_object_id)
+{
+       enum object_type type;
+       enum object_enum_id enum_id;
+       struct graphics_object_id go_id = { 0 };
+
+       type = object_type_from_bios_object_id(bios_object_id);
+
+       if (type == OBJECT_TYPE_UNKNOWN)
+               return go_id;
+
+       enum_id = enum_id_from_bios_object_id(bios_object_id);
+
+       if (enum_id == ENUM_ID_UNKNOWN)
+               return go_id;
+
+       go_id = dal_graphics_object_id_init(
+                       id_from_bios_object_id(type, bios_object_id),
+                                                               enum_id, type);
+
+       return go_id;
+}
+
+static enum object_type object_type_from_bios_object_id(uint32_t bios_object_id)
+{
+       uint32_t bios_object_type = (bios_object_id & OBJECT_TYPE_MASK)
+                               >> OBJECT_TYPE_SHIFT;
+       enum object_type object_type;
+
+       switch (bios_object_type) {
+       case GRAPH_OBJECT_TYPE_GPU:
+               object_type = OBJECT_TYPE_GPU;
+               break;
+       case GRAPH_OBJECT_TYPE_ENCODER:
+               object_type = OBJECT_TYPE_ENCODER;
+               break;
+       case GRAPH_OBJECT_TYPE_CONNECTOR:
+               object_type = OBJECT_TYPE_CONNECTOR;
+               break;
+       case GRAPH_OBJECT_TYPE_ROUTER:
+               object_type = OBJECT_TYPE_ROUTER;
+               break;
+       case GRAPH_OBJECT_TYPE_GENERIC:
+               object_type = OBJECT_TYPE_GENERIC;
+               break;
+       default:
+               object_type = OBJECT_TYPE_UNKNOWN;
+               break;
+       }
+
+       return object_type;
+}
+
+static enum object_enum_id enum_id_from_bios_object_id(uint32_t bios_object_id)
+{
+       uint32_t bios_enum_id =
+                       (bios_object_id & ENUM_ID_MASK) >> ENUM_ID_SHIFT;
+       enum object_enum_id id;
+
+       switch (bios_enum_id) {
+       case GRAPH_OBJECT_ENUM_ID1:
+               id = ENUM_ID_1;
+               break;
+       case GRAPH_OBJECT_ENUM_ID2:
+               id = ENUM_ID_2;
+               break;
+       case GRAPH_OBJECT_ENUM_ID3:
+               id = ENUM_ID_3;
+               break;
+       case GRAPH_OBJECT_ENUM_ID4:
+               id = ENUM_ID_4;
+               break;
+       case GRAPH_OBJECT_ENUM_ID5:
+               id = ENUM_ID_5;
+               break;
+       case GRAPH_OBJECT_ENUM_ID6:
+               id = ENUM_ID_6;
+               break;
+       case GRAPH_OBJECT_ENUM_ID7:
+               id = ENUM_ID_7;
+               break;
+       default:
+               id = ENUM_ID_UNKNOWN;
+               break;
+       }
+
+       return id;
+}
+
+static uint32_t id_from_bios_object_id(enum object_type type,
+       uint32_t bios_object_id)
+{
+       switch (type) {
+       case OBJECT_TYPE_GPU:
+               return gpu_id_from_bios_object_id(bios_object_id);
+       case OBJECT_TYPE_ENCODER:
+               return (uint32_t)encoder_id_from_bios_object_id(bios_object_id);
+       case OBJECT_TYPE_CONNECTOR:
+               return (uint32_t)connector_id_from_bios_object_id(
+                               bios_object_id);
+       case OBJECT_TYPE_GENERIC:
+               return generic_id_from_bios_object_id(bios_object_id);
+       default:
+               return 0;
+       }
+}
+
+uint32_t gpu_id_from_bios_object_id(uint32_t bios_object_id)
+{
+       return (bios_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
+}
+
+static enum encoder_id encoder_id_from_bios_object_id(uint32_t bios_object_id)
+{
+       uint32_t bios_encoder_id = gpu_id_from_bios_object_id(bios_object_id);
+       enum encoder_id id;
+
+       switch (bios_encoder_id) {
+       case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+               id = ENCODER_ID_INTERNAL_LVDS;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
+               id = ENCODER_ID_INTERNAL_TMDS1;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_TMDS2:
+               id = ENCODER_ID_INTERNAL_TMDS2;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC1:
+               id = ENCODER_ID_INTERNAL_DAC1;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DAC2:
+               id = ENCODER_ID_INTERNAL_DAC2;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+               id = ENCODER_ID_INTERNAL_LVTM1;
+               break;
+       case ENCODER_OBJECT_ID_HDMI_INTERNAL:
+               id = ENCODER_ID_INTERNAL_HDMI;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+               id = ENCODER_ID_INTERNAL_KLDSCP_TMDS1;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
+               id = ENCODER_ID_INTERNAL_KLDSCP_DAC1;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
+               id = ENCODER_ID_INTERNAL_KLDSCP_DAC2;
+               break;
+       case ENCODER_OBJECT_ID_MVPU_FPGA:
+               id = ENCODER_ID_EXTERNAL_MVPU_FPGA;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_DDI:
+               id = ENCODER_ID_INTERNAL_DDI;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+               id = ENCODER_ID_INTERNAL_UNIPHY;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+               id = ENCODER_ID_INTERNAL_KLDSCP_LVTMA;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+               id = ENCODER_ID_INTERNAL_UNIPHY1;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+               id = ENCODER_ID_INTERNAL_UNIPHY2;
+               break;
+       case ENCODER_OBJECT_ID_ALMOND: /* ENCODER_OBJECT_ID_NUTMEG */
+               id = ENCODER_ID_EXTERNAL_NUTMEG;
+               break;
+       case ENCODER_OBJECT_ID_TRAVIS:
+               id = ENCODER_ID_EXTERNAL_TRAVIS;
+               break;
+       case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
+               id = ENCODER_ID_INTERNAL_UNIPHY3;
+               break;
+       default:
+               id = ENCODER_ID_UNKNOWN;
+               ASSERT(0);
+               break;
+       }
+
+       return id;
+}
+
+static enum connector_id connector_id_from_bios_object_id(
+       uint32_t bios_object_id)
+{
+       uint32_t bios_connector_id = gpu_id_from_bios_object_id(bios_object_id);
+
+       enum connector_id id;
+
+       switch (bios_connector_id) {
+       case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
+               id = CONNECTOR_ID_SINGLE_LINK_DVII;
+               break;
+       case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
+               id = CONNECTOR_ID_DUAL_LINK_DVII;
+               break;
+       case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
+               id = CONNECTOR_ID_SINGLE_LINK_DVID;
+               break;
+       case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
+               id = CONNECTOR_ID_DUAL_LINK_DVID;
+               break;
+       case CONNECTOR_OBJECT_ID_VGA:
+               id = CONNECTOR_ID_VGA;
+               break;
+       case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
+               id = CONNECTOR_ID_HDMI_TYPE_A;
+               break;
+       case CONNECTOR_OBJECT_ID_LVDS:
+               id = CONNECTOR_ID_LVDS;
+               break;
+       case CONNECTOR_OBJECT_ID_PCIE_CONNECTOR:
+               id = CONNECTOR_ID_PCIE;
+               break;
+       case CONNECTOR_OBJECT_ID_HARDCODE_DVI:
+               id = CONNECTOR_ID_HARDCODE_DVI;
+               break;
+       case CONNECTOR_OBJECT_ID_DISPLAYPORT:
+               id = CONNECTOR_ID_DISPLAY_PORT;
+               break;
+       case CONNECTOR_OBJECT_ID_eDP:
+               id = CONNECTOR_ID_EDP;
+               break;
+       case CONNECTOR_OBJECT_ID_MXM:
+               id = CONNECTOR_ID_MXM;
+               break;
+       default:
+               id = CONNECTOR_ID_UNKNOWN;
+               break;
+       }
+
+       return id;
+}
+
+enum generic_id generic_id_from_bios_object_id(uint32_t bios_object_id)
+{
+       uint32_t bios_generic_id = gpu_id_from_bios_object_id(bios_object_id);
+
+       enum generic_id id;
+
+       switch (bios_generic_id) {
+       case GENERIC_OBJECT_ID_MXM_OPM:
+               id = GENERIC_ID_MXM_OPM;
+               break;
+       case GENERIC_OBJECT_ID_GLSYNC:
+               id = GENERIC_ID_GLSYNC;
+               break;
+       case GENERIC_OBJECT_ID_STEREO_PIN:
+               id = GENERIC_ID_STEREO;
+               break;
+       default:
+               id = GENERIC_ID_UNKNOWN;
+               break;
+       }
+
+       return id;
+}
+
+static uint8_t bios_parser_get_connectors_number(struct dc_bios *dcb)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       unsigned int count = 0;
+       unsigned int i;
+
+       for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
+               if (bp->object_info_tbl.v1_4->display_path[i].encoderobjid != 0
+                               &&
+               bp->object_info_tbl.v1_4->display_path[i].display_objid != 0)
+                       count++;
+       }
+       return count;
+}
+
+static struct graphics_object_id bios_parser_get_encoder_id(
+       struct dc_bios *dcb,
+       uint32_t i)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct graphics_object_id object_id = dal_graphics_object_id_init(
+               0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+
+       if (bp->object_info_tbl.v1_4->number_of_path > i)
+               object_id = object_id_from_bios_object_id(
+               bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
+
+       return object_id;
+}
+
+static struct graphics_object_id bios_parser_get_connector_id(
+       struct dc_bios *dcb,
+       uint8_t i)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct graphics_object_id object_id = dal_graphics_object_id_init(
+               0, ENUM_ID_UNKNOWN, OBJECT_TYPE_UNKNOWN);
+       struct object_info_table *tbl = &bp->object_info_tbl;
+       struct display_object_info_table_v1_4 *v1_4 = tbl->v1_4;
+
+       if (v1_4->number_of_path > i) {
+               /* If display_objid is generic object id,  the encoderObj
+                * /extencoderobjId should be 0
+                */
+               if (v1_4->display_path[i].encoderobjid != 0 &&
+                               v1_4->display_path[i].display_objid != 0)
+                       object_id = object_id_from_bios_object_id(
+                                       v1_4->display_path[i].display_objid);
+       }
+
+       return object_id;
+}
+
+
+/*  TODO:  GetNumberOfSrc*/
+
+static uint32_t bios_parser_get_dst_number(struct dc_bios *dcb,
+       struct graphics_object_id id)
+{
+       /* connector has 1 Dest, encoder has 0 Dest */
+       switch (id.type) {
+       case OBJECT_TYPE_ENCODER:
+               return 0;
+       case OBJECT_TYPE_CONNECTOR:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/*  removed getSrcObjList, getDestObjList*/
+
+
+static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
+       struct graphics_object_id object_id, uint32_t index,
+       struct graphics_object_id *src_object_id)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       unsigned int i;
+       enum bp_result  bp_result = BP_RESULT_BADINPUT;
+       struct graphics_object_id obj_id = {0};
+       struct object_info_table *tbl = &bp->object_info_tbl;
+
+       if (!src_object_id)
+               return bp_result;
+
+       switch (object_id.type) {
+       /* Encoder's Source is GPU.  BIOS does not provide GPU, since all
+        * displaypaths point to same GPU (0x1100).  Hardcode GPU object type
+        */
+       case OBJECT_TYPE_ENCODER:
+               /* TODO: since num of src must be less than 2.
+                * If found in for loop, should break.
+                * DAL2 implementation may be changed too
+                */
+               for (i = 0; i < tbl->v1_4->number_of_path; i++) {
+                       obj_id = object_id_from_bios_object_id(
+                       tbl->v1_4->display_path[i].encoderobjid);
+                       if (object_id.type == obj_id.type &&
+                                       object_id.id == obj_id.id &&
+                                               object_id.enum_id ==
+                                                       obj_id.enum_id) {
+                               *src_object_id =
+                               object_id_from_bios_object_id(0x1100);
+                               /* break; */
+                       }
+               }
+               bp_result = BP_RESULT_OK;
+               break;
+       case OBJECT_TYPE_CONNECTOR:
+               for (i = 0; i < tbl->v1_4->number_of_path; i++) {
+                       obj_id = object_id_from_bios_object_id(
+                               tbl->v1_4->display_path[i].display_objid);
+
+                       if (object_id.type == obj_id.type &&
+                               object_id.id == obj_id.id &&
+                                       object_id.enum_id == obj_id.enum_id) {
+                               *src_object_id =
+                               object_id_from_bios_object_id(
+                               tbl->v1_4->display_path[i].encoderobjid);
+                               /* break; */
+                       }
+               }
+               bp_result = BP_RESULT_OK;
+               break;
+       default:
+               break;
+       }
+
+       return bp_result;
+}
+
+static enum bp_result bios_parser_get_dst_obj(struct dc_bios *dcb,
+       struct graphics_object_id object_id, uint32_t index,
+       struct graphics_object_id *dest_object_id)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       unsigned int i;
+       enum bp_result  bp_result = BP_RESULT_BADINPUT;
+       struct graphics_object_id obj_id = {0};
+       struct object_info_table *tbl = &bp->object_info_tbl;
+
+       if (!dest_object_id)
+               return BP_RESULT_BADINPUT;
+
+       switch (object_id.type) {
+       case OBJECT_TYPE_ENCODER:
+               /* TODO: since num of src must be less than 2.
+                * If found in for loop, should break.
+                * DAL2 implementation may be changed too
+                */
+               for (i = 0; i < tbl->v1_4->number_of_path; i++) {
+                       obj_id = object_id_from_bios_object_id(
+                               tbl->v1_4->display_path[i].encoderobjid);
+                       if (object_id.type == obj_id.type &&
+                                       object_id.id == obj_id.id &&
+                                               object_id.enum_id ==
+                                                       obj_id.enum_id) {
+                               *dest_object_id =
+                                       object_id_from_bios_object_id(
+                               tbl->v1_4->display_path[i].display_objid);
+                               /* break; */
+                       }
+               }
+               bp_result = BP_RESULT_OK;
+               break;
+       default:
+               break;
+       }
+
+       return bp_result;
+}
+
+
+/* from graphics_object_id, find display path which includes the object_id */
+static struct atom_display_object_path_v2 *get_bios_object(
+       struct bios_parser *bp,
+       struct graphics_object_id id)
+{
+       unsigned int i;
+       struct graphics_object_id obj_id = {0};
+
+       switch (id.type) {
+       case OBJECT_TYPE_ENCODER:
+               for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
+                       obj_id = object_id_from_bios_object_id(
+                       bp->object_info_tbl.v1_4->display_path[i].encoderobjid);
+                       if (id.type == obj_id.type &&
+                                       id.id == obj_id.id &&
+                                               id.enum_id == obj_id.enum_id)
+                               return
+                               &bp->object_info_tbl.v1_4->display_path[i];
+               }
+       case OBJECT_TYPE_CONNECTOR:
+       case OBJECT_TYPE_GENERIC:
+               /* Both Generic and Connector Object ID
+                * will be stored on display_objid
+               */
+               for (i = 0; i < bp->object_info_tbl.v1_4->number_of_path; i++) {
+                       obj_id = object_id_from_bios_object_id(
+                       bp->object_info_tbl.v1_4->display_path[i].display_objid
+                       );
+                       if (id.type == obj_id.type &&
+                                       id.id == obj_id.id &&
+                                               id.enum_id == obj_id.enum_id)
+                               return
+                               &bp->object_info_tbl.v1_4->display_path[i];
+               }
+       default:
+               return NULL;
+       }
+}
+
+static enum bp_result bios_parser_get_i2c_info(struct dc_bios *dcb,
+       struct graphics_object_id id,
+       struct graphics_object_i2c_info *info)
+{
+       uint32_t offset;
+       struct atom_display_object_path_v2 *object;
+       struct atom_common_record_header *header;
+       struct atom_i2c_record *record;
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       object = get_bios_object(bp, id);
+
+       if (!object)
+               return BP_RESULT_BADINPUT;
+
+       offset = object->disp_recordoffset + bp->object_info_tbl_offset;
+
+       for (;;) {
+               header = GET_IMAGE(struct atom_common_record_header, offset);
+
+               if (!header)
+                       return BP_RESULT_BADBIOSTABLE;
+
+               if (header->record_type == LAST_RECORD_TYPE ||
+                       !header->record_size)
+                       break;
+
+               if (header->record_type == ATOM_I2C_RECORD_TYPE
+                       && sizeof(struct atom_i2c_record) <=
+                                                       header->record_size) {
+                       /* get the I2C info */
+                       record = (struct atom_i2c_record *) header;
+
+                       if (get_gpio_i2c_info(bp, record, info) ==
+                                                               BP_RESULT_OK)
+                               return BP_RESULT_OK;
+               }
+
+               offset += header->record_size;
+       }
+
+       return BP_RESULT_NORECORD;
+}
+
+static enum bp_result get_gpio_i2c_info(
+       struct bios_parser *bp,
+       struct atom_i2c_record *record,
+       struct graphics_object_i2c_info *info)
+{
+       struct atom_gpio_pin_lut_v2_1 *header;
+       uint32_t count = 0;
+       unsigned int table_index = 0;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       /* get the GPIO_I2C info */
+       if (!DATA_TABLES(gpio_pin_lut))
+               return BP_RESULT_BADBIOSTABLE;
+
+       header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
+                                       DATA_TABLES(gpio_pin_lut));
+       if (!header)
+               return BP_RESULT_BADBIOSTABLE;
+
+       if (sizeof(struct atom_common_table_header) +
+                       sizeof(struct atom_gpio_pin_assignment) >
+                       le16_to_cpu(header->table_header.structuresize))
+               return BP_RESULT_BADBIOSTABLE;
+
+       /* TODO: is version change? */
+       if (header->table_header.content_revision != 1)
+               return BP_RESULT_UNSUPPORTED;
+
+       /* get data count */
+       count = (le16_to_cpu(header->table_header.structuresize)
+                       - sizeof(struct atom_common_table_header))
+                               / sizeof(struct atom_gpio_pin_assignment);
+
+       table_index = record->i2c_id  & I2C_HW_LANE_MUX;
+
+       if (count < table_index) {
+               bool find_valid = false;
+
+               for (table_index = 0; table_index < count; table_index++) {
+                       if (((record->i2c_id & I2C_HW_CAP) == (
+                       header->gpio_pin[table_index].gpio_id &
+                                                       I2C_HW_CAP)) &&
+                       ((record->i2c_id & I2C_HW_ENGINE_ID_MASK)  ==
+                       (header->gpio_pin[table_index].gpio_id &
+                                               I2C_HW_ENGINE_ID_MASK)) &&
+                       ((record->i2c_id & I2C_HW_LANE_MUX) ==
+                       (header->gpio_pin[table_index].gpio_id &
+                                                       I2C_HW_LANE_MUX))) {
+                               /* still valid */
+                               find_valid = true;
+                               break;
+                       }
+               }
+               /* If we don't find the entry that we are looking for then
+                *  we will return BP_Result_BadBiosTable.
+                */
+               if (find_valid == false)
+                       return BP_RESULT_BADBIOSTABLE;
+       }
+
+       /* get the GPIO_I2C_INFO */
+       info->i2c_hw_assist = (record->i2c_id & I2C_HW_CAP) ? true : false;
+       info->i2c_line = record->i2c_id & I2C_HW_LANE_MUX;
+       info->i2c_engine_id = (record->i2c_id & I2C_HW_ENGINE_ID_MASK) >> 4;
+       info->i2c_slave_address = record->i2c_slave_addr;
+
+       /* TODO: check how to get register offset for en, Y, etc. */
+       info->gpio_info.clk_a_register_index =
+                       le16_to_cpu(
+                       header->gpio_pin[table_index].data_a_reg_index);
+       info->gpio_info.clk_a_shift =
+                       header->gpio_pin[table_index].gpio_bitshift;
+
+       return BP_RESULT_OK;
+}
+
+static enum bp_result get_voltage_ddc_info_v4(
+       uint8_t *i2c_line,
+       uint32_t index,
+       struct atom_common_table_header *header,
+       uint8_t *address)
+{
+       enum bp_result result = BP_RESULT_NORECORD;
+       struct atom_voltage_objects_info_v4_1 *info =
+               (struct atom_voltage_objects_info_v4_1 *) address;
+
+       uint8_t *voltage_current_object =
+               (uint8_t *) (&(info->voltage_object[0]));
+
+       while ((address + le16_to_cpu(header->structuresize)) >
+                                               voltage_current_object) {
+               struct atom_i2c_voltage_object_v4 *object =
+                       (struct atom_i2c_voltage_object_v4 *)
+                                               voltage_current_object;
+
+               if (object->header.voltage_mode ==
+                       ATOM_INIT_VOLTAGE_REGULATOR) {
+                       if (object->header.voltage_type == index) {
+                               *i2c_line = object->i2c_id ^ 0x90;
+                               result = BP_RESULT_OK;
+                               break;
+                       }
+               }
+
+               voltage_current_object +=
+                               le16_to_cpu(object->header.object_size);
+       }
+       return result;
+}
+
+static enum bp_result bios_parser_get_thermal_ddc_info(
+       struct dc_bios *dcb,
+       uint32_t i2c_channel_id,
+       struct graphics_object_i2c_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct i2c_id_config_access *config;
+       struct atom_i2c_record record;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       config = (struct i2c_id_config_access *) &i2c_channel_id;
+
+       record.i2c_id = config->bfHW_Capable;
+       record.i2c_id |= config->bfI2C_LineMux;
+       record.i2c_id |= config->bfHW_EngineID;
+
+       return get_gpio_i2c_info(bp, &record, info);
+}
+
+static enum bp_result bios_parser_get_voltage_ddc_info(struct dc_bios *dcb,
+       uint32_t index,
+       struct graphics_object_i2c_info *info)
+{
+       uint8_t i2c_line = 0;
+       enum bp_result result = BP_RESULT_NORECORD;
+       uint8_t *voltage_info_address;
+       struct atom_common_table_header *header;
+       struct atom_data_revision revision = {0};
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!DATA_TABLES(voltageobject_info))
+               return result;
+
+       voltage_info_address = get_image(&bp->base,
+                       DATA_TABLES(voltageobject_info),
+                       sizeof(struct atom_common_table_header));
+
+       header = (struct atom_common_table_header *) voltage_info_address;
+
+       get_atom_data_table_revision(header, &revision);
+
+       switch (revision.major) {
+       case 4:
+               if (revision.minor != 1)
+                       break;
+               result = get_voltage_ddc_info_v4(&i2c_line, index, header,
+                       voltage_info_address);
+               break;
+       }
+
+       if (result == BP_RESULT_OK)
+               result = bios_parser_get_thermal_ddc_info(dcb,
+                       i2c_line, info);
+
+       return result;
+}
+
+static enum bp_result bios_parser_get_hpd_info(
+       struct dc_bios *dcb,
+       struct graphics_object_id id,
+       struct graphics_object_hpd_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct atom_display_object_path_v2 *object;
+       struct atom_hpd_int_record *record = NULL;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       object = get_bios_object(bp, id);
+
+       if (!object)
+               return BP_RESULT_BADINPUT;
+
+       record = get_hpd_record(bp, object);
+
+       if (record != NULL) {
+               info->hpd_int_gpio_uid = record->pin_id;
+               info->hpd_active = record->plugin_pin_state;
+               return BP_RESULT_OK;
+       }
+
+       return BP_RESULT_NORECORD;
+}
+
+static struct atom_hpd_int_record *get_hpd_record(
+       struct bios_parser *bp,
+       struct atom_display_object_path_v2 *object)
+{
+       struct atom_common_record_header *header;
+       uint32_t offset;
+
+       if (!object) {
+               BREAK_TO_DEBUGGER(); /* Invalid object */
+               return NULL;
+       }
+
+       offset = le16_to_cpu(object->disp_recordoffset)
+                       + bp->object_info_tbl_offset;
+
+       for (;;) {
+               header = GET_IMAGE(struct atom_common_record_header, offset);
+
+               if (!header)
+                       return NULL;
+
+               if (header->record_type == LAST_RECORD_TYPE ||
+                       !header->record_size)
+                       break;
+
+               if (header->record_type == ATOM_HPD_INT_RECORD_TYPE
+                       && sizeof(struct atom_hpd_int_record) <=
+                                                       header->record_size)
+                       return (struct atom_hpd_int_record *) header;
+
+               offset += header->record_size;
+       }
+
+       return NULL;
+}
+
+/**
+ * bios_parser_get_gpio_pin_info
+ * Get GpioPin information of input gpio id
+ *
+ * @param gpio_id, GPIO ID
+ * @param info, GpioPin information structure
+ * @return Bios parser result code
+ * @note
+ *  to get the GPIO PIN INFO, we need:
+ *  1. get the GPIO_ID from other object table, see GetHPDInfo()
+ *  2. in DATA_TABLE.GPIO_Pin_LUT, search all records,
+ *     to get the registerA  offset/mask
+ */
+static enum bp_result bios_parser_get_gpio_pin_info(
+       struct dc_bios *dcb,
+       uint32_t gpio_id,
+       struct gpio_pin_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct atom_gpio_pin_lut_v2_1 *header;
+       uint32_t count = 0;
+       uint32_t i = 0;
+
+       if (!DATA_TABLES(gpio_pin_lut))
+               return BP_RESULT_BADBIOSTABLE;
+
+       header = GET_IMAGE(struct atom_gpio_pin_lut_v2_1,
+                                               DATA_TABLES(gpio_pin_lut));
+       if (!header)
+               return BP_RESULT_BADBIOSTABLE;
+
+       if (sizeof(struct atom_common_table_header) +
+                       sizeof(struct atom_gpio_pin_lut_v2_1)
+                       > le16_to_cpu(header->table_header.structuresize))
+               return BP_RESULT_BADBIOSTABLE;
+
+       if (header->table_header.content_revision != 1)
+               return BP_RESULT_UNSUPPORTED;
+
+       /* Temporary hard code gpio pin info */
+#if defined(FOR_SIMNOW_BOOT)
+       {
+               struct  atom_gpio_pin_assignment  gpio_pin[8] = {
+                               {0x5db5, 0, 0, 1, 0},
+                               {0x5db5, 8, 8, 2, 0},
+                               {0x5db5, 0x10, 0x10, 3, 0},
+                               {0x5db5, 0x18, 0x14, 4, 0},
+                               {0x5db5, 0x1A, 0x18, 5, 0},
+                               {0x5db5, 0x1C, 0x1C, 6, 0},
+               };
+
+               count = 6;
+               memmove(header->gpio_pin, gpio_pin, sizeof(gpio_pin));
+       }
+#else
+       count = (le16_to_cpu(header->table_header.structuresize)
+                       - sizeof(struct atom_common_table_header))
+                               / sizeof(struct atom_gpio_pin_assignment);
+#endif
+       for (i = 0; i < count; ++i) {
+               if (header->gpio_pin[i].gpio_id != gpio_id)
+                       continue;
+
+               info->offset =
+                       (uint32_t) le16_to_cpu(
+                                       header->gpio_pin[i].data_a_reg_index);
+               info->offset_y = info->offset + 2;
+               info->offset_en = info->offset + 1;
+               info->offset_mask = info->offset - 1;
+
+               info->mask = (uint32_t) (1 <<
+                       header->gpio_pin[i].gpio_bitshift);
+               info->mask_y = info->mask + 2;
+               info->mask_en = info->mask + 1;
+               info->mask_mask = info->mask - 1;
+
+               return BP_RESULT_OK;
+       }
+
+       return BP_RESULT_NORECORD;
+}
+
+static struct device_id device_type_from_device_id(uint16_t device_id)
+{
+
+       struct device_id result_device_id;
+
+       switch (device_id) {
+       case ATOM_DISPLAY_LCD1_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_LCD;
+               result_device_id.enum_id = 1;
+               break;
+
+       case ATOM_DISPLAY_DFP1_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_DFP;
+               result_device_id.enum_id = 1;
+               break;
+
+       case ATOM_DISPLAY_DFP2_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_DFP;
+               result_device_id.enum_id = 2;
+               break;
+
+       case ATOM_DISPLAY_DFP3_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_DFP;
+               result_device_id.enum_id = 3;
+               break;
+
+       case ATOM_DISPLAY_DFP4_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_DFP;
+               result_device_id.enum_id = 4;
+               break;
+
+       case ATOM_DISPLAY_DFP5_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_DFP;
+               result_device_id.enum_id = 5;
+               break;
+
+       case ATOM_DISPLAY_DFP6_SUPPORT:
+               result_device_id.device_type = DEVICE_TYPE_DFP;
+               result_device_id.enum_id = 6;
+               break;
+
+       default:
+               BREAK_TO_DEBUGGER(); /* Invalid device Id */
+               result_device_id.device_type = DEVICE_TYPE_UNKNOWN;
+               result_device_id.enum_id = 0;
+       }
+       return result_device_id;
+}
+
+static enum bp_result bios_parser_get_device_tag(
+       struct dc_bios *dcb,
+       struct graphics_object_id connector_object_id,
+       uint32_t device_tag_index,
+       struct connector_device_tag_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct atom_display_object_path_v2 *object;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       /* getBiosObject will return MXM object */
+       object = get_bios_object(bp, connector_object_id);
+
+       if (!object) {
+               BREAK_TO_DEBUGGER(); /* Invalid object id */
+               return BP_RESULT_BADINPUT;
+       }
+
+       info->acpi_device = 0; /* BIOS no longer provides this */
+       info->dev_id = device_type_from_device_id(object->device_tag);
+
+       return BP_RESULT_OK;
+}
+
+static enum bp_result get_ss_info_v4_1(
+       struct bios_parser *bp,
+       uint32_t id,
+       uint32_t index,
+       struct spread_spectrum_info *ss_info)
+{
+       enum bp_result result = BP_RESULT_OK;
+       struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
+       struct atom_smu_info_v3_1 *smu_tbl = NULL;
+
+       if (!ss_info)
+               return BP_RESULT_BADINPUT;
+
+       if (!DATA_TABLES(dce_info))
+               return BP_RESULT_BADBIOSTABLE;
+
+       if (!DATA_TABLES(smu_info))
+               return BP_RESULT_BADBIOSTABLE;
+
+       disp_cntl_tbl =  GET_IMAGE(struct atom_display_controller_info_v4_1,
+                                                       DATA_TABLES(dce_info));
+       if (!disp_cntl_tbl)
+               return BP_RESULT_BADBIOSTABLE;
+
+       smu_tbl =  GET_IMAGE(struct atom_smu_info_v3_1, DATA_TABLES(smu_info));
+       if (!smu_tbl)
+               return BP_RESULT_BADBIOSTABLE;
+
+
+       ss_info->type.STEP_AND_DELAY_INFO = false;
+       ss_info->spread_percentage_divider = 1000;
+       /* BIOS no longer uses target clock.  Always enable for now */
+       ss_info->target_clock_range = 0xffffffff;
+
+       switch (id) {
+       case AS_SIGNAL_TYPE_DVI:
+               ss_info->spread_spectrum_percentage =
+                               disp_cntl_tbl->dvi_ss_percentage;
+               ss_info->spread_spectrum_range =
+                               disp_cntl_tbl->dvi_ss_rate_10hz * 10;
+               if (disp_cntl_tbl->dvi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+                       ss_info->type.CENTER_MODE = true;
+               break;
+       case AS_SIGNAL_TYPE_HDMI:
+               ss_info->spread_spectrum_percentage =
+                               disp_cntl_tbl->hdmi_ss_percentage;
+               ss_info->spread_spectrum_range =
+                               disp_cntl_tbl->hdmi_ss_rate_10hz * 10;
+               if (disp_cntl_tbl->hdmi_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+                       ss_info->type.CENTER_MODE = true;
+               break;
+       /* TODO LVDS not support anymore? */
+       case AS_SIGNAL_TYPE_DISPLAY_PORT:
+               ss_info->spread_spectrum_percentage =
+                               disp_cntl_tbl->dp_ss_percentage;
+               ss_info->spread_spectrum_range =
+                               disp_cntl_tbl->dp_ss_rate_10hz * 10;
+               if (disp_cntl_tbl->dp_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+                       ss_info->type.CENTER_MODE = true;
+               break;
+       case AS_SIGNAL_TYPE_GPU_PLL:
+               ss_info->spread_spectrum_percentage =
+                               smu_tbl->gpuclk_ss_percentage;
+               ss_info->spread_spectrum_range =
+                               smu_tbl->gpuclk_ss_rate_10hz * 10;
+               if (smu_tbl->gpuclk_ss_mode & ATOM_SS_CENTRE_SPREAD_MODE)
+                       ss_info->type.CENTER_MODE = true;
+               break;
+       default:
+               result = BP_RESULT_UNSUPPORTED;
+       }
+
+       return result;
+}
+
+/**
+ * bios_parser_get_spread_spectrum_info
+ * Get spread spectrum information from the ASIC_InternalSS_Info(ver 2.1 or
+ * ver 3.1) or SS_Info table from the VBIOS. Currently ASIC_InternalSS_Info
+ * ver 2.1 can co-exist with SS_Info table. Expect ASIC_InternalSS_Info
+ * ver 3.1,
+ * there is only one entry for each signal /ss id.  However, there is
+ * no planning of supporting multiple spread Sprectum entry for EverGreen
+ * @param [in] this
+ * @param [in] signal, ASSignalType to be converted to info index
+ * @param [in] index, number of entries that match the converted info index
+ * @param [out] ss_info, sprectrum information structure,
+ * @return Bios parser result code
+ */
+static enum bp_result bios_parser_get_spread_spectrum_info(
+       struct dc_bios *dcb,
+       enum as_signal_type signal,
+       uint32_t index,
+       struct spread_spectrum_info *ss_info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       enum bp_result result = BP_RESULT_UNSUPPORTED;
+       struct atom_common_table_header *header;
+       struct atom_data_revision tbl_revision;
+
+       if (!ss_info) /* check for bad input */
+               return BP_RESULT_BADINPUT;
+
+       if (!DATA_TABLES(dce_info))
+               return BP_RESULT_UNSUPPORTED;
+
+       header = GET_IMAGE(struct atom_common_table_header,
+                                               DATA_TABLES(dce_info));
+       get_atom_data_table_revision(header, &tbl_revision);
+
+       switch (tbl_revision.major) {
+       case 4:
+               switch (tbl_revision.minor) {
+               case 1:
+                       return get_ss_info_v4_1(bp, signal, index, ss_info);
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+       /* there can not be more then one entry for SS Info table */
+       return result;
+}
+
+static enum bp_result get_embedded_panel_info_v2_1(
+       struct bios_parser *bp,
+       struct embedded_panel_info *info)
+{
+       struct lcd_info_v2_1 *lvds;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       if (!DATA_TABLES(lcd_info))
+               return BP_RESULT_UNSUPPORTED;
+
+       lvds = GET_IMAGE(struct lcd_info_v2_1, DATA_TABLES(lcd_info));
+
+       if (!lvds)
+               return BP_RESULT_BADBIOSTABLE;
+
+       /* TODO: previous vv1_3, should v2_1 */
+       if (!((lvds->table_header.format_revision == 2)
+                       && (lvds->table_header.content_revision >= 1)))
+               return BP_RESULT_UNSUPPORTED;
+
+       memset(info, 0, sizeof(struct embedded_panel_info));
+
+       /* We need to convert from 10KHz units into KHz units */
+       info->lcd_timing.pixel_clk =
+                       le16_to_cpu(lvds->lcd_timing.pixclk) * 10;
+       /* usHActive does not include borders, according to VBIOS team */
+       info->lcd_timing.horizontal_addressable =
+                       le16_to_cpu(lvds->lcd_timing.h_active);
+       /* usHBlanking_Time includes borders, so we should really be
+        * subtractingborders duing this translation, but LVDS generally
+        * doesn't have borders, so we should be okay leaving this as is for
+        * now.  May need to revisit if we ever have LVDS with borders
+        */
+       info->lcd_timing.horizontal_blanking_time =
+               le16_to_cpu(lvds->lcd_timing.h_blanking_time);
+       /* usVActive does not include borders, according to VBIOS team*/
+       info->lcd_timing.vertical_addressable =
+               le16_to_cpu(lvds->lcd_timing.v_active);
+       /* usVBlanking_Time includes borders, so we should really be
+        * subtracting borders duing this translation, but LVDS generally
+        * doesn't have borders, so we should be okay leaving this as is for
+        * now. May need to revisit if we ever have LVDS with borders
+        */
+       info->lcd_timing.vertical_blanking_time =
+               le16_to_cpu(lvds->lcd_timing.v_blanking_time);
+       info->lcd_timing.horizontal_sync_offset =
+               le16_to_cpu(lvds->lcd_timing.h_sync_offset);
+       info->lcd_timing.horizontal_sync_width =
+               le16_to_cpu(lvds->lcd_timing.h_sync_width);
+       info->lcd_timing.vertical_sync_offset =
+               le16_to_cpu(lvds->lcd_timing.v_sync_offset);
+       info->lcd_timing.vertical_sync_width =
+               le16_to_cpu(lvds->lcd_timing.v_syncwidth);
+       info->lcd_timing.horizontal_border = lvds->lcd_timing.h_border;
+       info->lcd_timing.vertical_border = lvds->lcd_timing.v_border;
+
+       /* not provided by VBIOS */
+       info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0;
+
+       info->lcd_timing.misc_info.H_SYNC_POLARITY =
+               ~(uint32_t)
+               (lvds->lcd_timing.miscinfo & ATOM_HSYNC_POLARITY);
+       info->lcd_timing.misc_info.V_SYNC_POLARITY =
+               ~(uint32_t)
+               (lvds->lcd_timing.miscinfo & ATOM_VSYNC_POLARITY);
+
+       /* not provided by VBIOS */
+       info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
+
+       info->lcd_timing.misc_info.H_REPLICATION_BY2 =
+               lvds->lcd_timing.miscinfo & ATOM_H_REPLICATIONBY2;
+       info->lcd_timing.misc_info.V_REPLICATION_BY2 =
+               lvds->lcd_timing.miscinfo & ATOM_V_REPLICATIONBY2;
+       info->lcd_timing.misc_info.COMPOSITE_SYNC =
+               lvds->lcd_timing.miscinfo & ATOM_COMPOSITESYNC;
+       info->lcd_timing.misc_info.INTERLACE =
+               lvds->lcd_timing.miscinfo & ATOM_INTERLACE;
+
+       /* not provided by VBIOS*/
+       info->lcd_timing.misc_info.DOUBLE_CLOCK = 0;
+       /* not provided by VBIOS*/
+       info->ss_id = 0;
+
+       info->realtek_eDPToLVDS =
+                       (lvds->dplvdsrxid == eDP_TO_LVDS_REALTEK_ID ? 1:0);
+
+       return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_embedded_panel_info(
+       struct dc_bios *dcb,
+       struct embedded_panel_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct atom_common_table_header *header;
+       struct atom_data_revision tbl_revision;
+
+       if (!DATA_TABLES(lcd_info))
+               return BP_RESULT_FAILURE;
+
+       header = GET_IMAGE(struct atom_common_table_header,
+                                       DATA_TABLES(lcd_info));
+
+       if (!header)
+               return BP_RESULT_BADBIOSTABLE;
+
+       get_atom_data_table_revision(header, &tbl_revision);
+
+
+       switch (tbl_revision.major) {
+       case 2:
+               switch (tbl_revision.minor) {
+               case 1:
+                       return get_embedded_panel_info_v2_1(bp, info);
+               default:
+                       break;
+               }
+       default:
+               break;
+       }
+
+       return BP_RESULT_FAILURE;
+}
+
+static uint32_t get_support_mask_for_device_id(struct device_id device_id)
+{
+       enum dal_device_type device_type = device_id.device_type;
+       uint32_t enum_id = device_id.enum_id;
+
+       switch (device_type) {
+       case DEVICE_TYPE_LCD:
+               switch (enum_id) {
+               case 1:
+                       return ATOM_DISPLAY_LCD1_SUPPORT;
+               default:
+                       break;
+               }
+               break;
+       case DEVICE_TYPE_DFP:
+               switch (enum_id) {
+               case 1:
+                       return ATOM_DISPLAY_DFP1_SUPPORT;
+               case 2:
+                       return ATOM_DISPLAY_DFP2_SUPPORT;
+               case 3:
+                       return ATOM_DISPLAY_DFP3_SUPPORT;
+               case 4:
+                       return ATOM_DISPLAY_DFP4_SUPPORT;
+               case 5:
+                       return ATOM_DISPLAY_DFP5_SUPPORT;
+               case 6:
+                       return ATOM_DISPLAY_DFP6_SUPPORT;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       };
+
+       /* Unidentified device ID, return empty support mask. */
+       return 0;
+}
+
+static bool bios_parser_is_device_id_supported(
+       struct dc_bios *dcb,
+       struct device_id id)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       uint32_t mask = get_support_mask_for_device_id(id);
+
+       return (le16_to_cpu(bp->object_info_tbl.v1_4->supporteddevices) &
+                                                               mask) != 0;
+}
+
+static void bios_parser_post_init(
+       struct dc_bios *dcb)
+{
+       /* TODO for OPM module. Need implement later */
+}
+
+static uint32_t bios_parser_get_ss_entry_number(
+       struct dc_bios *dcb,
+       enum as_signal_type signal)
+{
+       /* TODO: DAL2 atomfirmware implementation does not need this.
+        * why DAL3 need this?
+        */
+       return 1;
+}
+
+static enum bp_result bios_parser_transmitter_control(
+       struct dc_bios *dcb,
+       struct bp_transmitter_control *cntl)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.transmitter_control)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.transmitter_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_encoder_control(
+       struct dc_bios *dcb,
+       struct bp_encoder_control *cntl)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.dig_encoder_control)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.dig_encoder_control(bp, cntl);
+}
+
+static enum bp_result bios_parser_set_pixel_clock(
+       struct dc_bios *dcb,
+       struct bp_pixel_clock_parameters *bp_params)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.set_pixel_clock)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.set_pixel_clock(bp, bp_params);
+}
+
+static enum bp_result bios_parser_set_dce_clock(
+       struct dc_bios *dcb,
+       struct bp_set_dce_clock_parameters *bp_params)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.set_dce_clock)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.set_dce_clock(bp, bp_params);
+}
+
+static unsigned int bios_parser_get_smu_clock_info(
+       struct dc_bios *dcb)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.get_smu_clock_info)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.get_smu_clock_info(bp);
+}
+
+static enum bp_result bios_parser_program_crtc_timing(
+       struct dc_bios *dcb,
+       struct bp_hw_crtc_timing_parameters *bp_params)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.set_crtc_timing)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.set_crtc_timing(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_crtc(
+       struct dc_bios *dcb,
+       enum controller_id id,
+       bool enable)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.enable_crtc)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.enable_crtc(bp, id, enable);
+}
+
+static enum bp_result bios_parser_crtc_source_select(
+       struct dc_bios *dcb,
+       struct bp_crtc_source_select *bp_params)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.select_crtc_source)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.select_crtc_source(bp, bp_params);
+}
+
+static enum bp_result bios_parser_enable_disp_power_gating(
+       struct dc_bios *dcb,
+       enum controller_id controller_id,
+       enum bp_pipe_control_action action)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+       if (!bp->cmd_tbl.enable_disp_power_gating)
+               return BP_RESULT_FAILURE;
+
+       return bp->cmd_tbl.enable_disp_power_gating(bp, controller_id,
+               action);
+}
+
+static bool bios_parser_is_accelerated_mode(
+       struct dc_bios *dcb)
+{
+       return bios_is_accelerated_mode(dcb);
+}
+
+
+/**
+ * bios_parser_set_scratch_critical_state
+ *
+ * @brief
+ *  update critical state bit in VBIOS scratch register
+ *
+ * @param
+ *  bool - to set or reset state
+ */
+static void bios_parser_set_scratch_critical_state(
+       struct dc_bios *dcb,
+       bool state)
+{
+       bios_set_scratch_critical_state(dcb, state);
+}
+
+static enum bp_result bios_parser_get_firmware_info(
+       struct dc_bios *dcb,
+       struct firmware_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       enum bp_result result = BP_RESULT_BADBIOSTABLE;
+       struct atom_common_table_header *header;
+
+       struct atom_data_revision revision;
+
+       if (info && DATA_TABLES(firmwareinfo)) {
+               header = GET_IMAGE(struct atom_common_table_header,
+                               DATA_TABLES(firmwareinfo));
+               get_atom_data_table_revision(header, &revision);
+               switch (revision.major) {
+               case 3:
+                       switch (revision.minor) {
+                       case 1:
+                               result = get_firmware_info_v3_1(bp, info);
+                               break;
+                       default:
+                               break;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return result;
+}
+
+static enum bp_result get_firmware_info_v3_1(
+       struct bios_parser *bp,
+       struct firmware_info *info)
+{
+       struct atom_firmware_info_v3_1 *firmware_info;
+       struct atom_display_controller_info_v4_1 *dce_info = NULL;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       firmware_info = GET_IMAGE(struct atom_firmware_info_v3_1,
+                       DATA_TABLES(firmwareinfo));
+
+       dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
+                       DATA_TABLES(dce_info));
+
+       if (!firmware_info || !dce_info)
+               return BP_RESULT_BADBIOSTABLE;
+
+       memset(info, 0, sizeof(*info));
+
+       /* Pixel clock pll information. */
+        /* We need to convert from 10KHz units into KHz units */
+       info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
+       info->default_engine_clk = firmware_info->bootup_sclk_in10khz * 10;
+
+        /* 27MHz for Vega10: */
+       info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
+
+       /* Hardcode frequency if BIOS gives no DCE Ref Clk */
+       if (info->pll_info.crystal_frequency == 0)
+               info->pll_info.crystal_frequency = 27000;
+
+       info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
+       info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
+
+       /* Get GPU PLL VCO Clock */
+
+       if (bp->cmd_tbl.get_smu_clock_info != NULL) {
+               /* VBIOS gives in 10KHz */
+               info->smu_gpu_pll_output_freq =
+                               bp->cmd_tbl.get_smu_clock_info(bp) * 10;
+       }
+
+        return BP_RESULT_OK;
+}
+
+static enum bp_result bios_parser_get_encoder_cap_info(
+       struct dc_bios *dcb,
+       struct graphics_object_id object_id,
+       struct bp_encoder_cap_info *info)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct atom_display_object_path_v2 *object;
+       struct atom_encoder_caps_record *record = NULL;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       object = get_bios_object(bp, object_id);
+
+       if (!object)
+               return BP_RESULT_BADINPUT;
+
+       record = get_encoder_cap_record(bp, object);
+       if (!record)
+               return BP_RESULT_NORECORD;
+
+       info->DP_HBR2_CAP = (record->encodercaps &
+                       ATOM_ENCODER_CAP_RECORD_HBR2) ? 1 : 0;
+       info->DP_HBR2_EN = (record->encodercaps &
+                       ATOM_ENCODER_CAP_RECORD_HBR2_EN) ? 1 : 0;
+       info->DP_HBR3_EN = (record->encodercaps &
+                       ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0;
+       info->HDMI_6GB_EN = (record->encodercaps &
+                       ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0;
+
+       return BP_RESULT_OK;
+}
+
+
+static struct atom_encoder_caps_record *get_encoder_cap_record(
+       struct bios_parser *bp,
+       struct atom_display_object_path_v2 *object)
+{
+       struct atom_common_record_header *header;
+       uint32_t offset;
+
+       if (!object) {
+               BREAK_TO_DEBUGGER(); /* Invalid object */
+               return NULL;
+       }
+
+       offset = object->encoder_recordoffset + bp->object_info_tbl_offset;
+
+       for (;;) {
+               header = GET_IMAGE(struct atom_common_record_header, offset);
+
+               if (!header)
+                       return NULL;
+
+               offset += header->record_size;
+
+               if (header->record_type == LAST_RECORD_TYPE ||
+                               !header->record_size)
+                       break;
+
+               if (header->record_type != ATOM_ENCODER_CAP_RECORD_TYPE)
+                       continue;
+
+               if (sizeof(struct atom_encoder_caps_record) <=
+                                                       header->record_size)
+                       return (struct atom_encoder_caps_record *)header;
+       }
+
+       return NULL;
+}
+
+/*
+ * get_integrated_info_v11
+ *
+ * @brief
+ * Get V8 integrated BIOS information
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result get_integrated_info_v11(
+       struct bios_parser *bp,
+       struct integrated_info *info)
+{
+       struct atom_integrated_system_info_v1_11 *info_v11;
+       uint32_t i;
+
+       info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
+                                       DATA_TABLES(integratedsysteminfo));
+
+       if (info_v11 == NULL)
+       return BP_RESULT_BADBIOSTABLE;
+
+       info->gpu_cap_info =
+       le32_to_cpu(info_v11->gpucapinfo);
+       /*
+       * system_config: Bit[0] = 0 : PCIE power gating disabled
+       *                       = 1 : PCIE power gating enabled
+       *                Bit[1] = 0 : DDR-PLL shut down disabled
+       *                       = 1 : DDR-PLL shut down enabled
+       *                Bit[2] = 0 : DDR-PLL power down disabled
+       *                       = 1 : DDR-PLL power down enabled
+       */
+       info->system_config = le32_to_cpu(info_v11->system_config);
+       info->cpu_cap_info = le32_to_cpu(info_v11->cpucapinfo);
+       info->memory_type = info_v11->memorytype;
+       info->ma_channel_number = info_v11->umachannelnumber;
+       info->lvds_ss_percentage =
+       le16_to_cpu(info_v11->lvds_ss_percentage);
+       info->lvds_sspread_rate_in_10hz =
+       le16_to_cpu(info_v11->lvds_ss_rate_10hz);
+       info->hdmi_ss_percentage =
+       le16_to_cpu(info_v11->hdmi_ss_percentage);
+       info->hdmi_sspread_rate_in_10hz =
+       le16_to_cpu(info_v11->hdmi_ss_rate_10hz);
+       info->dvi_ss_percentage =
+       le16_to_cpu(info_v11->dvi_ss_percentage);
+       info->dvi_sspread_rate_in_10_hz =
+       le16_to_cpu(info_v11->dvi_ss_rate_10hz);
+       info->lvds_misc = info_v11->lvds_misc;
+       for (i = 0; i < NUMBER_OF_UCHAR_FOR_GUID; ++i) {
+               info->ext_disp_conn_info.gu_id[i] =
+                               info_v11->extdispconninfo.guid[i];
+       }
+
+       for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH; ++i) {
+               info->ext_disp_conn_info.path[i].device_connector_id =
+               object_id_from_bios_object_id(
+               le16_to_cpu(info_v11->extdispconninfo.path[i].connectorobjid));
+
+               info->ext_disp_conn_info.path[i].ext_encoder_obj_id =
+               object_id_from_bios_object_id(
+                       le16_to_cpu(
+                       info_v11->extdispconninfo.path[i].ext_encoder_objid));
+
+               info->ext_disp_conn_info.path[i].device_tag =
+                       le16_to_cpu(
+                               info_v11->extdispconninfo.path[i].device_tag);
+               info->ext_disp_conn_info.path[i].device_acpi_enum =
+               le16_to_cpu(
+                       info_v11->extdispconninfo.path[i].device_acpi_enum);
+               info->ext_disp_conn_info.path[i].ext_aux_ddc_lut_index =
+                       info_v11->extdispconninfo.path[i].auxddclut_index;
+               info->ext_disp_conn_info.path[i].ext_hpd_pin_lut_index =
+                       info_v11->extdispconninfo.path[i].hpdlut_index;
+               info->ext_disp_conn_info.path[i].channel_mapping.raw =
+                       info_v11->extdispconninfo.path[i].channelmapping;
+       }
+       info->ext_disp_conn_info.checksum =
+       info_v11->extdispconninfo.checksum;
+
+       /** TODO - review **/
+       #if 0
+       info->boot_up_engine_clock = le32_to_cpu(info_v11->ulBootUpEngineClock)
+                                                                       * 10;
+       info->dentist_vco_freq = le32_to_cpu(info_v11->ulDentistVCOFreq) * 10;
+       info->boot_up_uma_clock = le32_to_cpu(info_v8->ulBootUpUMAClock) * 10;
+
+       for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+               /* Convert [10KHz] into [KHz] */
+               info->disp_clk_voltage[i].max_supported_clk =
+               le32_to_cpu(info_v11->sDISPCLK_Voltage[i].
+                       ulMaximumSupportedCLK) * 10;
+               info->disp_clk_voltage[i].voltage_index =
+               le32_to_cpu(info_v11->sDISPCLK_Voltage[i].ulVoltageIndex);
+       }
+
+       info->boot_up_req_display_vector =
+                       le32_to_cpu(info_v11->ulBootUpReqDisplayVector);
+       info->boot_up_nb_voltage =
+                       le16_to_cpu(info_v11->usBootUpNBVoltage);
+       info->ext_disp_conn_info_offset =
+                       le16_to_cpu(info_v11->usExtDispConnInfoOffset);
+       info->gmc_restore_reset_time =
+                       le32_to_cpu(info_v11->ulGMCRestoreResetTime);
+       info->minimum_n_clk =
+                       le32_to_cpu(info_v11->ulNbpStateNClkFreq[0]);
+       for (i = 1; i < 4; ++i)
+               info->minimum_n_clk =
+                               info->minimum_n_clk <
+                               le32_to_cpu(info_v11->ulNbpStateNClkFreq[i]) ?
+                               info->minimum_n_clk : le32_to_cpu(
+                                       info_v11->ulNbpStateNClkFreq[i]);
+
+       info->idle_n_clk = le32_to_cpu(info_v11->ulIdleNClk);
+       info->ddr_dll_power_up_time =
+           le32_to_cpu(info_v11->ulDDR_DLL_PowerUpTime);
+       info->ddr_pll_power_up_time =
+               le32_to_cpu(info_v11->ulDDR_PLL_PowerUpTime);
+       info->pcie_clk_ss_type = le16_to_cpu(info_v11->usPCIEClkSSType);
+       info->max_lvds_pclk_freq_in_single_link =
+               le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
+       info->max_lvds_pclk_freq_in_single_link =
+               le16_to_cpu(info_v11->usMaxLVDSPclkFreqInSingleLink);
+       info->lvds_pwr_on_seq_dig_on_to_de_in_4ms =
+               info_v11->ucLVDSPwrOnSeqDIGONtoDE_in4Ms;
+       info->lvds_pwr_on_seq_de_to_vary_bl_in_4ms =
+               info_v11->ucLVDSPwrOnSeqDEtoVARY_BL_in4Ms;
+       info->lvds_pwr_on_seq_vary_bl_to_blon_in_4ms =
+               info_v11->ucLVDSPwrOnSeqVARY_BLtoBLON_in4Ms;
+       info->lvds_pwr_off_seq_vary_bl_to_de_in4ms =
+               info_v11->ucLVDSPwrOffSeqVARY_BLtoDE_in4Ms;
+       info->lvds_pwr_off_seq_de_to_dig_on_in4ms =
+               info_v11->ucLVDSPwrOffSeqDEtoDIGON_in4Ms;
+       info->lvds_pwr_off_seq_blon_to_vary_bl_in_4ms =
+               info_v11->ucLVDSPwrOffSeqBLONtoVARY_BL_in4Ms;
+       info->lvds_off_to_on_delay_in_4ms =
+               info_v11->ucLVDSOffToOnDelay_in4Ms;
+       info->lvds_bit_depth_control_val =
+               le32_to_cpu(info_v11->ulLCDBitDepthControlVal);
+
+       for (i = 0; i < NUMBER_OF_AVAILABLE_SCLK; ++i) {
+               /* Convert [10KHz] into [KHz] */
+               info->avail_s_clk[i].supported_s_clk =
+                       le32_to_cpu(info_v11->sAvail_SCLK[i].ulSupportedSCLK)
+                                                                       * 10;
+               info->avail_s_clk[i].voltage_index =
+                       le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageIndex);
+               info->avail_s_clk[i].voltage_id =
+                       le16_to_cpu(info_v11->sAvail_SCLK[i].usVoltageID);
+       }
+       #endif /* TODO*/
+
+       return BP_RESULT_OK;
+}
+
+
+/*
+ * construct_integrated_info
+ *
+ * @brief
+ * Get integrated BIOS information based on table revision
+ *
+ * @param
+ * bios_parser *bp - [in]BIOS parser handler to get master data table
+ * integrated_info *info - [out] store and output integrated info
+ *
+ * @return
+ * enum bp_result - BP_RESULT_OK if information is available,
+ *                  BP_RESULT_BADBIOSTABLE otherwise.
+ */
+static enum bp_result construct_integrated_info(
+       struct bios_parser *bp,
+       struct integrated_info *info)
+{
+       enum bp_result result = BP_RESULT_BADBIOSTABLE;
+
+       struct atom_common_table_header *header;
+       struct atom_data_revision revision;
+
+       struct clock_voltage_caps temp = {0, 0};
+       uint32_t i;
+       uint32_t j;
+
+       if (info && DATA_TABLES(integratedsysteminfo)) {
+               header = GET_IMAGE(struct atom_common_table_header,
+                                       DATA_TABLES(integratedsysteminfo));
+
+               get_atom_data_table_revision(header, &revision);
+
+               /* Don't need to check major revision as they are all 1 */
+               switch (revision.minor) {
+               case 11:
+                       result = get_integrated_info_v11(bp, info);
+                       break;
+               default:
+                       return result;
+               }
+       }
+
+       if (result != BP_RESULT_OK)
+               return result;
+
+       /* Sort voltage table from low to high*/
+       for (i = 1; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
+               for (j = i; j > 0; --j) {
+                       if (info->disp_clk_voltage[j].max_supported_clk <
+                               info->disp_clk_voltage[j-1].max_supported_clk
+                               ) {
+                               /* swap j and j - 1*/
+                               temp = info->disp_clk_voltage[j-1];
+                               info->disp_clk_voltage[j-1] =
+                                       info->disp_clk_voltage[j];
+                               info->disp_clk_voltage[j] = temp;
+                       }
+               }
+       }
+
+       return result;
+}
+
+static struct integrated_info *bios_parser_create_integrated_info(
+       struct dc_bios *dcb)
+{
+       struct bios_parser *bp = BP_FROM_DCB(dcb);
+       struct integrated_info *info = NULL;
+
+       info = dm_alloc(sizeof(struct integrated_info));
+
+       if (info == NULL) {
+               ASSERT_CRITICAL(0);
+               return NULL;
+       }
+
+       if (construct_integrated_info(bp, info) == BP_RESULT_OK)
+       return info;
+
+       dm_free(info);
+
+       return NULL;
+}
+
+static const struct dc_vbios_funcs vbios_funcs = {
+       .get_connectors_number = bios_parser_get_connectors_number,
+
+       .get_encoder_id = bios_parser_get_encoder_id,
+
+       .get_connector_id = bios_parser_get_connector_id,
+
+       .get_dst_number = bios_parser_get_dst_number,
+
+       .get_src_obj = bios_parser_get_src_obj,
+
+       .get_dst_obj = bios_parser_get_dst_obj,
+
+       .get_i2c_info = bios_parser_get_i2c_info,
+
+       .get_voltage_ddc_info = bios_parser_get_voltage_ddc_info,
+
+       .get_thermal_ddc_info = bios_parser_get_thermal_ddc_info,
+
+       .get_hpd_info = bios_parser_get_hpd_info,
+
+       .get_device_tag = bios_parser_get_device_tag,
+
+       .get_firmware_info = bios_parser_get_firmware_info,
+
+       .get_spread_spectrum_info = bios_parser_get_spread_spectrum_info,
+
+       .get_ss_entry_number = bios_parser_get_ss_entry_number,
+
+       .get_embedded_panel_info = bios_parser_get_embedded_panel_info,
+
+       .get_gpio_pin_info = bios_parser_get_gpio_pin_info,
+
+       .get_encoder_cap_info = bios_parser_get_encoder_cap_info,
+
+       .is_device_id_supported = bios_parser_is_device_id_supported,
+
+
+
+       .is_accelerated_mode = bios_parser_is_accelerated_mode,
+
+       .set_scratch_critical_state = bios_parser_set_scratch_critical_state,
+
+
+/*      COMMANDS */
+       .encoder_control = bios_parser_encoder_control,
+
+       .transmitter_control = bios_parser_transmitter_control,
+
+       .enable_crtc = bios_parser_enable_crtc,
+
+       .set_pixel_clock = bios_parser_set_pixel_clock,
+
+       .set_dce_clock = bios_parser_set_dce_clock,
+
+       .program_crtc_timing = bios_parser_program_crtc_timing,
+
+       /* .blank_crtc = bios_parser_blank_crtc, */
+
+       .crtc_source_select = bios_parser_crtc_source_select,
+
+       /* .external_encoder_control = bios_parser_external_encoder_control, */
+
+       .enable_disp_power_gating = bios_parser_enable_disp_power_gating,
+
+       .post_init = bios_parser_post_init,
+
+       .bios_parser_destroy = firmware_parser_destroy,
+
+       .get_smu_clock_info = bios_parser_get_smu_clock_info,
+};
+
+static bool bios_parser_construct(
+       struct bios_parser *bp,
+       struct bp_init_data *init,
+       enum dce_version dce_version)
+{
+       uint16_t *rom_header_offset = NULL;
+       struct atom_rom_header_v2_2 *rom_header = NULL;
+       struct display_object_info_table_v1_4 *object_info_tbl;
+       struct atom_data_revision tbl_rev = {0};
+
+       if (!init)
+               return false;
+
+       if (!init->bios)
+               return false;
+
+       bp->base.funcs = &vbios_funcs;
+       bp->base.bios = init->bios;
+       bp->base.bios_size = bp->base.bios[OFFSET_TO_ATOM_ROM_IMAGE_SIZE] * BIOS_IMAGE_SIZE_UNIT;
+
+       bp->base.ctx = init->ctx;
+
+       bp->base.bios_local_image = NULL;
+
+       rom_header_offset =
+                       GET_IMAGE(uint16_t, OFFSET_TO_ATOM_ROM_HEADER_POINTER);
+
+       if (!rom_header_offset)
+               return false;
+
+       rom_header = GET_IMAGE(struct atom_rom_header_v2_2, *rom_header_offset);
+
+       if (!rom_header)
+               return false;
+
+       get_atom_data_table_revision(&rom_header->table_header, &tbl_rev);
+       if (!(tbl_rev.major >= 2 && tbl_rev.minor >= 2))
+               return false;
+
+       bp->master_data_tbl =
+               GET_IMAGE(struct atom_master_data_table_v2_1,
+                               rom_header->masterdatatable_offset);
+
+       if (!bp->master_data_tbl)
+               return false;
+
+       bp->object_info_tbl_offset = DATA_TABLES(displayobjectinfo);
+
+       if (!bp->object_info_tbl_offset)
+               return false;
+
+       object_info_tbl =
+                       GET_IMAGE(struct display_object_info_table_v1_4,
+                                               bp->object_info_tbl_offset);
+
+       if (!object_info_tbl)
+               return false;
+
+       get_atom_data_table_revision(&object_info_tbl->table_header,
+               &bp->object_info_tbl.revision);
+
+       if (bp->object_info_tbl.revision.major == 1
+               && bp->object_info_tbl.revision.minor >= 4) {
+               struct display_object_info_table_v1_4 *tbl_v1_4;
+
+               tbl_v1_4 = GET_IMAGE(struct display_object_info_table_v1_4,
+                       bp->object_info_tbl_offset);
+               if (!tbl_v1_4)
+                       return false;
+
+               bp->object_info_tbl.v1_4 = tbl_v1_4;
+       } else
+               return false;
+
+       dal_firmware_parser_init_cmd_tbl(bp);
+       dal_bios_parser_init_cmd_tbl_helper2(&bp->cmd_helper, dce_version);
+
+       bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base);
+
+       return true;
+}
+
+struct dc_bios *firmware_parser_create(
+       struct bp_init_data *init,
+       enum dce_version dce_version)
+{
+       struct bios_parser *bp = NULL;
+
+       bp = dm_alloc(sizeof(struct bios_parser));
+       if (!bp)
+               return NULL;
+
+       if (bios_parser_construct(bp, init, dce_version))
+               return &bp->base;
+
+       dm_free(bp);
+       return NULL;
+}
+
+
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h
new file mode 100644 (file)
index 0000000..cb40546
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER2_H__
+#define __DAL_BIOS_PARSER2_H__
+
+struct dc_bios *firmware_parser_create(
+       struct bp_init_data *init,
+       enum dce_version dce_version);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h
new file mode 100644 (file)
index 0000000..bf1f5c8
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_BIOS_PARSER_TYPES_BIOS2_H__
+#define __DAL_BIOS_PARSER_TYPES_BIOS2_H__
+
+#include "dc_bios_types.h"
+#include "bios_parser_helper.h"
+
+/* use atomfirmware_bringup.h only. Not atombios.h anymore */
+
+struct atom_data_revision {
+       uint32_t major;
+       uint32_t minor;
+};
+
+struct object_info_table {
+       struct atom_data_revision revision;
+       union {
+               struct display_object_info_table_v1_4 *v1_4;
+       };
+};
+
+enum spread_spectrum_id {
+       SS_ID_UNKNOWN = 0,
+       SS_ID_DP1 = 0xf1,
+       SS_ID_DP2 = 0xf2,
+       SS_ID_LVLINK_2700MHZ = 0xf3,
+       SS_ID_LVLINK_1620MHZ = 0xf4
+};
+
+struct bios_parser {
+       struct dc_bios base;
+
+       struct object_info_table object_info_tbl;
+       uint32_t object_info_tbl_offset;
+       struct atom_master_data_table_v2_1 *master_data_tbl;
+
+
+       const struct bios_parser_helper *bios_helper;
+
+       const struct command_table_helper *cmd_helper;
+       struct cmd_tbl cmd_tbl;
+
+       bool remap_device_tags;
+};
+
+/* Bios Parser from DC Bios */
+#define BP_FROM_DCB(dc_bios) \
+       container_of(dc_bios, struct bios_parser, base)
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
new file mode 100644 (file)
index 0000000..36d1582
--- /dev/null
@@ -0,0 +1,813 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "ObjectID.h"
+#include "atomfirmware.h"
+#include "atomfirmwareid.h"
+
+#include "include/bios_parser_interface.h"
+
+#include "command_table2.h"
+#include "command_table_helper2.h"
+#include "bios_parser_helper.h"
+#include "bios_parser_types_internal2.h"
+
+#define GET_INDEX_INTO_MASTER_TABLE(MasterOrData, FieldName)\
+       (((char *)(&((\
+               struct atom_master_list_of_##MasterOrData##_functions_v2_1 *)0)\
+               ->FieldName)-(char *)0)/sizeof(uint16_t))
+
+#define EXEC_BIOS_CMD_TABLE(fname, params)\
+       (cgs_atom_exec_cmd_table(bp->base.ctx->cgs_device, \
+               GET_INDEX_INTO_MASTER_TABLE(command, fname), \
+               &params) == 0)
+
+#define BIOS_CMD_TABLE_REVISION(fname, frev, crev)\
+       cgs_atom_get_cmd_table_revs(bp->base.ctx->cgs_device, \
+               GET_INDEX_INTO_MASTER_TABLE(command, fname), &frev, &crev)
+
+#define BIOS_CMD_TABLE_PARA_REVISION(fname)\
+       bios_cmd_table_para_revision(bp->base.ctx->cgs_device, \
+                       GET_INDEX_INTO_MASTER_TABLE(command, fname))
+
+static void init_dig_encoder_control(struct bios_parser *bp);
+static void init_transmitter_control(struct bios_parser *bp);
+static void init_set_pixel_clock(struct bios_parser *bp);
+
+static void init_set_crtc_timing(struct bios_parser *bp);
+
+static void init_select_crtc_source(struct bios_parser *bp);
+static void init_enable_crtc(struct bios_parser *bp);
+
+static void init_external_encoder_control(struct bios_parser *bp);
+static void init_enable_disp_power_gating(struct bios_parser *bp);
+static void init_set_dce_clock(struct bios_parser *bp);
+static void init_get_smu_clock_info(struct bios_parser *bp);
+
+void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp)
+{
+       init_dig_encoder_control(bp);
+       init_transmitter_control(bp);
+       init_set_pixel_clock(bp);
+
+       init_set_crtc_timing(bp);
+
+       init_select_crtc_source(bp);
+       init_enable_crtc(bp);
+
+       init_external_encoder_control(bp);
+       init_enable_disp_power_gating(bp);
+       init_set_dce_clock(bp);
+       init_get_smu_clock_info(bp);
+}
+
+static uint32_t bios_cmd_table_para_revision(void *cgs_device,
+                                            uint32_t index)
+{
+       uint8_t frev, crev;
+
+       if (cgs_atom_get_cmd_table_revs(cgs_device,
+                                       index,
+                                       &frev, &crev) != 0)
+               return 0;
+       return crev;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  D I G E N C O D E R C O N T R O L
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result encoder_control_digx_v1_5(
+       struct bios_parser *bp,
+       struct bp_encoder_control *cntl);
+
+static void init_dig_encoder_control(struct bios_parser *bp)
+{
+       uint32_t version =
+               BIOS_CMD_TABLE_PARA_REVISION(digxencodercontrol);
+
+       switch (version) {
+       case 5:
+               bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v1_5;
+               break;
+       default:
+               bp->cmd_tbl.dig_encoder_control = NULL;
+               break;
+       }
+}
+
+static enum bp_result encoder_control_digx_v1_5(
+       struct bios_parser *bp,
+       struct bp_encoder_control *cntl)
+{
+       enum bp_result result = BP_RESULT_FAILURE;
+       struct dig_encoder_stream_setup_parameters_v1_5 params = {0};
+
+       params.digid = (uint8_t)(cntl->engine_id);
+       params.action = bp->cmd_helper->encoder_action_to_atom(cntl->action);
+
+       params.pclk_10khz = cntl->pixel_clock / 10;
+       params.digmode =
+                       (uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(
+                                       cntl->signal,
+                                       cntl->enable_dp_audio));
+       params.lanenum = (uint8_t)(cntl->lanes_number);
+
+       switch (cntl->color_depth) {
+       case COLOR_DEPTH_888:
+               params.bitpercolor = PANEL_8BIT_PER_COLOR;
+               break;
+       case COLOR_DEPTH_101010:
+               params.bitpercolor = PANEL_10BIT_PER_COLOR;
+               break;
+       case COLOR_DEPTH_121212:
+               params.bitpercolor = PANEL_12BIT_PER_COLOR;
+               break;
+       case COLOR_DEPTH_161616:
+               params.bitpercolor = PANEL_16BIT_PER_COLOR;
+               break;
+       default:
+               break;
+       }
+
+       if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+               switch (cntl->color_depth) {
+               case COLOR_DEPTH_101010:
+                       params.pclk_10khz =
+                               (params.pclk_10khz * 30) / 24;
+                       break;
+               case COLOR_DEPTH_121212:
+                       params.pclk_10khz =
+                               (params.pclk_10khz * 36) / 24;
+                       break;
+               case COLOR_DEPTH_161616:
+                       params.pclk_10khz =
+                               (params.pclk_10khz * 48) / 24;
+                       break;
+               default:
+                       break;
+               }
+
+       if (EXEC_BIOS_CMD_TABLE(digxencodercontrol, params))
+               result = BP_RESULT_OK;
+
+       return result;
+}
+
+/*****************************************************************************
+ ******************************************************************************
+ **
+ **                  TRANSMITTER CONTROL
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result transmitter_control_v1_6(
+       struct bios_parser *bp,
+       struct bp_transmitter_control *cntl);
+
+static void init_transmitter_control(struct bios_parser *bp)
+{
+       uint8_t frev;
+       uint8_t crev;
+
+       if (BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev) != 0)
+               BREAK_TO_DEBUGGER();
+       switch (crev) {
+       case 6:
+               bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;
+               break;
+       default:
+               bp->cmd_tbl.transmitter_control = NULL;
+               break;
+       }
+}
+
+static enum bp_result transmitter_control_v1_6(
+       struct bios_parser *bp,
+       struct bp_transmitter_control *cntl)
+{
+       enum bp_result result = BP_RESULT_FAILURE;
+       const struct command_table_helper *cmd = bp->cmd_helper;
+       struct dig_transmitter_control_ps_allocation_v1_6 ps = { { 0 } };
+
+       ps.param.phyid = cmd->phy_id_to_atom(cntl->transmitter);
+       ps.param.action = (uint8_t)cntl->action;
+
+       if (cntl->action == TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS)
+               ps.param.mode_laneset.dplaneset = (uint8_t)cntl->lane_settings;
+       else
+               ps.param.mode_laneset.digmode =
+                               cmd->signal_type_to_atom_dig_mode(cntl->signal);
+
+       ps.param.lanenum = (uint8_t)cntl->lanes_number;
+       ps.param.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel);
+       ps.param.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id);
+       ps.param.connobj_id = (uint8_t)cntl->connector_obj_id.id;
+       ps.param.symclk_10khz = cntl->pixel_clock/10;
+
+
+       if (cntl->action == TRANSMITTER_CONTROL_ENABLE ||
+               cntl->action == TRANSMITTER_CONTROL_ACTIAVATE ||
+               cntl->action == TRANSMITTER_CONTROL_DEACTIVATE) {
+               dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\
+               "************************%s:ps.param.symclk_10khz = %d\n",\
+               __func__, ps.param.symclk_10khz);
+       }
+
+
+/*color_depth not used any more, driver has deep color factor in the Phyclk*/
+       if (EXEC_BIOS_CMD_TABLE(dig1transmittercontrol, ps))
+               result = BP_RESULT_OK;
+       return result;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  SET PIXEL CLOCK
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result set_pixel_clock_v7(
+       struct bios_parser *bp,
+       struct bp_pixel_clock_parameters *bp_params);
+
+static void init_set_pixel_clock(struct bios_parser *bp)
+{
+       switch (BIOS_CMD_TABLE_PARA_REVISION(setpixelclock)) {
+       case 7:
+               bp->cmd_tbl.set_pixel_clock = set_pixel_clock_v7;
+               break;
+       default:
+               bp->cmd_tbl.set_pixel_clock = NULL;
+               break;
+       }
+}
+
+
+
+static enum bp_result set_pixel_clock_v7(
+       struct bios_parser *bp,
+       struct bp_pixel_clock_parameters *bp_params)
+{
+       enum bp_result result = BP_RESULT_FAILURE;
+       struct set_pixel_clock_parameter_v1_7 clk;
+       uint8_t controller_id;
+       uint32_t pll_id;
+
+       memset(&clk, 0, sizeof(clk));
+
+       if (bp->cmd_helper->clock_source_id_to_atom(bp_params->pll_id, &pll_id)
+                       && bp->cmd_helper->controller_id_to_atom(bp_params->
+                                       controller_id, &controller_id)) {
+               /* Note: VBIOS still wants to use ucCRTC name which is now
+                * 1 byte in ULONG
+                *typedef struct _CRTC_PIXEL_CLOCK_FREQ
+                *{
+                * target the pixel clock to drive the CRTC timing.
+                * ULONG ulPixelClock:24;
+                * 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to
+                * previous version.
+                * ATOM_CRTC1~6, indicate the CRTC controller to
+                * ULONG ucCRTC:8;
+                * drive the pixel clock. not used for DCPLL case.
+                *}CRTC_PIXEL_CLOCK_FREQ;
+                *union
+                *{
+                * pixel clock and CRTC id frequency
+                * CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq;
+                * ULONG ulDispEngClkFreq; dispclk frequency
+                *};
+                */
+               clk.crtc_id = controller_id;
+               clk.pll_id = (uint8_t) pll_id;
+               clk.encoderobjid =
+                       bp->cmd_helper->encoder_id_to_atom(
+                               dal_graphics_object_id_get_encoder_id(
+                                       bp_params->encoder_object_id));
+
+               clk.encoder_mode = (uint8_t) bp->
+                       cmd_helper->encoder_mode_bp_to_atom(
+                               bp_params->signal_type, false);
+
+               /* We need to convert from KHz units into 10KHz units */
+               clk.pixclk_100hz = cpu_to_le32(bp_params->target_pixel_clock *
+                               10);
+
+               clk.deep_color_ratio =
+                       (uint8_t) bp->cmd_helper->
+                               transmitter_color_depth_to_atom(
+                                       bp_params->color_depth);
+               dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,\
+                               "************************%s:program display clock = %d"\
+                               "colorDepth = %d\n", __func__,\
+                               bp_params->target_pixel_clock, bp_params->color_depth);
+
+               if (bp_params->flags.FORCE_PROGRAMMING_OF_PLL)
+                       clk.miscinfo |= PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL;
+
+               if (bp_params->flags.PROGRAM_PHY_PLL_ONLY)
+                       clk.miscinfo |= PIXEL_CLOCK_V7_MISC_PROG_PHYPLL;
+
+               if (bp_params->flags.SUPPORT_YUV_420)
+                       clk.miscinfo |= PIXEL_CLOCK_V7_MISC_YUV420_MODE;
+
+               if (bp_params->flags.SET_XTALIN_REF_SRC)
+                       clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN;
+
+               if (bp_params->flags.SET_GENLOCK_REF_DIV_SRC)
+                       clk.miscinfo |= PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK;
+
+               if (bp_params->signal_type == SIGNAL_TYPE_DVI_DUAL_LINK)
+                       clk.miscinfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
+
+               if (EXEC_BIOS_CMD_TABLE(setpixelclock, clk))
+                       result = BP_RESULT_OK;
+       }
+       return result;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  SET CRTC TIMING
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+       struct bios_parser *bp,
+       struct bp_hw_crtc_timing_parameters *bp_params);
+
+static void init_set_crtc_timing(struct bios_parser *bp)
+{
+       uint32_t dtd_version =
+                       BIOS_CMD_TABLE_PARA_REVISION(setcrtc_usingdtdtiming);
+
+               switch (dtd_version) {
+               case 3:
+                       bp->cmd_tbl.set_crtc_timing =
+                                       set_crtc_using_dtd_timing_v3;
+                       break;
+               default:
+                       bp->cmd_tbl.set_crtc_timing = NULL;
+                       break;
+               }
+}
+
+static enum bp_result set_crtc_using_dtd_timing_v3(
+       struct bios_parser *bp,
+       struct bp_hw_crtc_timing_parameters *bp_params)
+{
+       enum bp_result result = BP_RESULT_FAILURE;
+       struct set_crtc_using_dtd_timing_parameters params = {0};
+       uint8_t atom_controller_id;
+
+       if (bp->cmd_helper->controller_id_to_atom(
+                       bp_params->controller_id, &atom_controller_id))
+               params.crtc_id = atom_controller_id;
+
+       /* bios usH_Size wants h addressable size */
+       params.h_size = cpu_to_le16((uint16_t)bp_params->h_addressable);
+       /* bios usH_Blanking_Time wants borders included in blanking */
+       params.h_blanking_time =
+                       cpu_to_le16((uint16_t)(bp_params->h_total -
+                                       bp_params->h_addressable));
+       /* bios usV_Size wants v addressable size */
+       params.v_size = cpu_to_le16((uint16_t)bp_params->v_addressable);
+       /* bios usV_Blanking_Time wants borders included in blanking */
+       params.v_blanking_time =
+                       cpu_to_le16((uint16_t)(bp_params->v_total -
+                                       bp_params->v_addressable));
+       /* bios usHSyncOffset is the offset from the end of h addressable,
+        * our horizontalSyncStart is the offset from the beginning
+        * of h addressable
+        */
+       params.h_syncoffset =
+                       cpu_to_le16((uint16_t)(bp_params->h_sync_start -
+                                       bp_params->h_addressable));
+       params.h_syncwidth = cpu_to_le16((uint16_t)bp_params->h_sync_width);
+       /* bios usHSyncOffset is the offset from the end of v addressable,
+        * our verticalSyncStart is the offset from the beginning of
+        * v addressable
+        */
+       params.v_syncoffset =
+                       cpu_to_le16((uint16_t)(bp_params->v_sync_start -
+                                       bp_params->v_addressable));
+       params.v_syncwidth = cpu_to_le16((uint16_t)bp_params->v_sync_width);
+
+       /* we assume that overscan from original timing does not get bigger
+        * than 255
+        * we will program all the borders in the Set CRTC Overscan call below
+        */
+
+       if (bp_params->flags.HSYNC_POSITIVE_POLARITY == 0)
+               params.modemiscinfo =
+                               cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
+                                               ATOM_HSYNC_POLARITY);
+
+       if (bp_params->flags.VSYNC_POSITIVE_POLARITY == 0)
+               params.modemiscinfo =
+                               cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
+                                               ATOM_VSYNC_POLARITY);
+
+       if (bp_params->flags.INTERLACE) {
+               params.modemiscinfo =
+                               cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
+                                               ATOM_INTERLACE);
+
+               /* original DAL code has this condition to apply this
+                * for non-TV/CV only
+                * due to complex MV testing for possible impact
+                * if ( pACParameters->signal != SignalType_YPbPr &&
+                *  pACParameters->signal != SignalType_Composite &&
+                *  pACParameters->signal != SignalType_SVideo)
+                */
+               {
+                       /* HW will deduct 0.5 line from 2nd feild.
+                        * i.e. for 1080i, it is 2 lines for 1st field,
+                        * 2.5 lines for the 2nd feild. we need input as 5
+                        * instead of 4.
+                        * but it is 4 either from Edid data (spec CEA 861)
+                        * or CEA timing table.
+                        */
+                       params.v_syncoffset =
+                               cpu_to_le16(le16_to_cpu(params.v_syncoffset) +
+                                               1);
+
+               }
+       }
+
+       if (bp_params->flags.HORZ_COUNT_BY_TWO)
+               params.modemiscinfo =
+                       cpu_to_le16(le16_to_cpu(params.modemiscinfo) |
+                                       0x100); /* ATOM_DOUBLE_CLOCK_MODE */
+
+       if (EXEC_BIOS_CMD_TABLE(setcrtc_usingdtdtiming, params))
+               result = BP_RESULT_OK;
+
+       return result;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  SELECT CRTC SOURCE
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+
+static enum bp_result select_crtc_source_v3(
+       struct bios_parser *bp,
+       struct bp_crtc_source_select *bp_params);
+
+static void init_select_crtc_source(struct bios_parser *bp)
+{
+       switch (BIOS_CMD_TABLE_PARA_REVISION(selectcrtc_source)) {
+       case 3:
+               bp->cmd_tbl.select_crtc_source = select_crtc_source_v3;
+               break;
+       default:
+               bp->cmd_tbl.select_crtc_source = NULL;
+               break;
+       }
+}
+
+
+static enum bp_result select_crtc_source_v3(
+       struct bios_parser *bp,
+       struct bp_crtc_source_select *bp_params)
+{
+       bool result = BP_RESULT_FAILURE;
+       struct select_crtc_source_parameters_v2_3 params;
+       uint8_t atom_controller_id;
+       uint32_t atom_engine_id;
+       enum signal_type s = bp_params->signal;
+
+       memset(&params, 0, sizeof(params));
+
+       if (bp->cmd_helper->controller_id_to_atom(bp_params->controller_id,
+                       &atom_controller_id))
+               params.crtc_id = atom_controller_id;
+       else
+               return result;
+
+       if (bp->cmd_helper->engine_bp_to_atom(bp_params->engine_id,
+                       &atom_engine_id))
+               params.encoder_id = (uint8_t)atom_engine_id;
+       else
+               return result;
+
+       if (s == SIGNAL_TYPE_EDP ||
+               (s == SIGNAL_TYPE_DISPLAY_PORT && bp_params->sink_signal ==
+                                                       SIGNAL_TYPE_LVDS))
+               s = SIGNAL_TYPE_LVDS;
+
+       params.encode_mode =
+                       bp->cmd_helper->encoder_mode_bp_to_atom(
+                                       s, bp_params->enable_dp_audio);
+       /* Needed for VBIOS Random Spatial Dithering feature */
+       params.dst_bpc = (uint8_t)(bp_params->display_output_bit_depth);
+
+       if (EXEC_BIOS_CMD_TABLE(selectcrtc_source, params))
+               result = BP_RESULT_OK;
+
+       return result;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  ENABLE CRTC
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result enable_crtc_v1(
+       struct bios_parser *bp,
+       enum controller_id controller_id,
+       bool enable);
+
+static void init_enable_crtc(struct bios_parser *bp)
+{
+       switch (BIOS_CMD_TABLE_PARA_REVISION(enablecrtc)) {
+       case 1:
+               bp->cmd_tbl.enable_crtc = enable_crtc_v1;
+               break;
+       default:
+               bp->cmd_tbl.enable_crtc = NULL;
+               break;
+       }
+}
+
+static enum bp_result enable_crtc_v1(
+       struct bios_parser *bp,
+       enum controller_id controller_id,
+       bool enable)
+{
+       bool result = BP_RESULT_FAILURE;
+       struct enable_crtc_parameters params = {0};
+       uint8_t id;
+
+       if (bp->cmd_helper->controller_id_to_atom(controller_id, &id))
+               params.crtc_id = id;
+       else
+               return BP_RESULT_BADINPUT;
+
+       if (enable)
+               params.enable = ATOM_ENABLE;
+       else
+               params.enable = ATOM_DISABLE;
+
+       if (EXEC_BIOS_CMD_TABLE(enablecrtc, params))
+               result = BP_RESULT_OK;
+
+       return result;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  DISPLAY PLL
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  EXTERNAL ENCODER CONTROL
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result external_encoder_control_v3(
+       struct bios_parser *bp,
+       struct bp_external_encoder_control *cntl);
+
+static void init_external_encoder_control(
+       struct bios_parser *bp)
+{
+       switch (BIOS_CMD_TABLE_PARA_REVISION(externalencodercontrol)) {
+       case 3:
+               bp->cmd_tbl.external_encoder_control =
+                               external_encoder_control_v3;
+               break;
+       default:
+               bp->cmd_tbl.external_encoder_control = NULL;
+               break;
+       }
+}
+
+static enum bp_result external_encoder_control_v3(
+       struct bios_parser *bp,
+       struct bp_external_encoder_control *cntl)
+{
+       /* TODO */
+       return BP_RESULT_OK;
+}
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  ENABLE DISPLAY POWER GATING
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static enum bp_result enable_disp_power_gating_v2_1(
+       struct bios_parser *bp,
+       enum controller_id crtc_id,
+       enum bp_pipe_control_action action);
+
+static void init_enable_disp_power_gating(
+       struct bios_parser *bp)
+{
+       switch (BIOS_CMD_TABLE_PARA_REVISION(enabledisppowergating)) {
+       case 1:
+               bp->cmd_tbl.enable_disp_power_gating =
+                               enable_disp_power_gating_v2_1;
+               break;
+       default:
+               bp->cmd_tbl.enable_disp_power_gating = NULL;
+               break;
+       }
+}
+
+static enum bp_result enable_disp_power_gating_v2_1(
+       struct bios_parser *bp,
+       enum controller_id crtc_id,
+       enum bp_pipe_control_action action)
+{
+       enum bp_result result = BP_RESULT_FAILURE;
+
+
+       struct enable_disp_power_gating_ps_allocation ps = { { 0 } };
+       uint8_t atom_crtc_id;
+
+       if (bp->cmd_helper->controller_id_to_atom(crtc_id, &atom_crtc_id))
+               ps.param.disp_pipe_id = atom_crtc_id;
+       else
+               return BP_RESULT_BADINPUT;
+
+       ps.param.enable =
+               bp->cmd_helper->disp_power_gating_action_to_atom(action);
+
+       if (EXEC_BIOS_CMD_TABLE(enabledisppowergating, ps.param))
+               result = BP_RESULT_OK;
+
+       return result;
+}
+
+/******************************************************************************
+*******************************************************************************
+ **
+ **                  SET DCE CLOCK
+ **
+*******************************************************************************
+*******************************************************************************/
+
+static enum bp_result set_dce_clock_v2_1(
+       struct bios_parser *bp,
+       struct bp_set_dce_clock_parameters *bp_params);
+
+static void init_set_dce_clock(struct bios_parser *bp)
+{
+       switch (BIOS_CMD_TABLE_PARA_REVISION(setdceclock)) {
+       case 1:
+               bp->cmd_tbl.set_dce_clock = set_dce_clock_v2_1;
+               break;
+       default:
+               bp->cmd_tbl.set_dce_clock = NULL;
+               break;
+       }
+}
+
+static enum bp_result set_dce_clock_v2_1(
+       struct bios_parser *bp,
+       struct bp_set_dce_clock_parameters *bp_params)
+{
+       enum bp_result result = BP_RESULT_FAILURE;
+
+       struct set_dce_clock_ps_allocation_v2_1 params;
+       uint32_t atom_pll_id;
+       uint32_t atom_clock_type;
+       const struct command_table_helper *cmd = bp->cmd_helper;
+
+       memset(&params, 0, sizeof(params));
+
+       if (!cmd->clock_source_id_to_atom(bp_params->pll_id, &atom_pll_id) ||
+                       !cmd->dc_clock_type_to_atom(bp_params->clock_type,
+                                       &atom_clock_type))
+               return BP_RESULT_BADINPUT;
+
+       params.param.dceclksrc  = atom_pll_id;
+       params.param.dceclktype = atom_clock_type;
+
+       if (bp_params->clock_type == DCECLOCK_TYPE_DPREFCLK) {
+               if (bp_params->flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK)
+                       params.param.dceclkflag |=
+                                       DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK;
+
+               if (bp_params->flags.USE_PCIE_AS_SOURCE_FOR_DPREFCLK)
+                       params.param.dceclkflag |=
+                                       DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE;
+
+               if (bp_params->flags.USE_XTALIN_AS_SOURCE_FOR_DPREFCLK)
+                       params.param.dceclkflag |=
+                                       DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN;
+
+               if (bp_params->flags.USE_GENERICA_AS_SOURCE_FOR_DPREFCLK)
+                       params.param.dceclkflag |=
+                                       DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA;
+       } else
+               /* only program clock frequency if display clock is used;
+                * VBIOS will program DPREFCLK
+                * We need to convert from KHz units into 10KHz units
+                */
+               params.param.dceclk_10khz = cpu_to_le32(
+                               bp_params->target_clock_frequency / 10);
+       dm_logger_write(bp->base.ctx->logger, LOG_HW_SET_MODE,
+                       "************************%s:target_clock_frequency = %d"\
+                       "clock_type = %d \n", __func__,\
+                       bp_params->target_clock_frequency,\
+                       bp_params->clock_type);
+
+       if (EXEC_BIOS_CMD_TABLE(setdceclock, params)) {
+               /* Convert from 10KHz units back to KHz */
+               bp_params->target_clock_frequency = le32_to_cpu(
+                               params.param.dceclk_10khz) * 10;
+               result = BP_RESULT_OK;
+       }
+
+       return result;
+}
+
+
+/******************************************************************************
+ ******************************************************************************
+ **
+ **                  GET SMU CLOCK INFO
+ **
+ ******************************************************************************
+ *****************************************************************************/
+
+static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp);
+
+static void init_get_smu_clock_info(struct bios_parser *bp)
+{
+       /* TODO add switch for table vrsion */
+       bp->cmd_tbl.get_smu_clock_info = get_smu_clock_info_v3_1;
+
+}
+
+static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp)
+{
+       struct atom_get_smu_clock_info_parameters_v3_1 smu_input = {0};
+       struct atom_get_smu_clock_info_output_parameters_v3_1 smu_output;
+
+       smu_input.command = GET_SMU_CLOCK_INFO_V3_1_GET_PLLVCO_FREQ;
+
+       /* Get Specific Clock */
+       if (EXEC_BIOS_CMD_TABLE(getsmuclockinfo, smu_input)) {
+               memmove(&smu_output, &smu_input, sizeof(
+                       struct atom_get_smu_clock_info_parameters_v3_1));
+               return smu_output.atom_smu_outputclkfreq.syspllvcofreq_10khz;
+       }
+
+       return 0;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h
new file mode 100644 (file)
index 0000000..59061b8
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE2_H__
+#define __DAL_COMMAND_TABLE2_H__
+
+struct bios_parser;
+struct bp_encoder_control;
+
+struct cmd_tbl {
+       enum bp_result (*dig_encoder_control)(
+               struct bios_parser *bp,
+               struct bp_encoder_control *control);
+       enum bp_result (*encoder_control_dig1)(
+               struct bios_parser *bp,
+               struct bp_encoder_control *control);
+       enum bp_result (*encoder_control_dig2)(
+               struct bios_parser *bp,
+               struct bp_encoder_control *control);
+       enum bp_result (*transmitter_control)(
+               struct bios_parser *bp,
+               struct bp_transmitter_control *control);
+       enum bp_result (*set_pixel_clock)(
+               struct bios_parser *bp,
+               struct bp_pixel_clock_parameters *bp_params);
+       enum bp_result (*enable_spread_spectrum_on_ppll)(
+               struct bios_parser *bp,
+               struct bp_spread_spectrum_parameters *bp_params,
+               bool enable);
+       enum bp_result (*adjust_display_pll)(
+               struct bios_parser *bp,
+               struct bp_adjust_pixel_clock_parameters *bp_params);
+       enum bp_result (*dac1_encoder_control)(
+               struct bios_parser *bp,
+               bool enable,
+               uint32_t pixel_clock,
+               uint8_t dac_standard);
+       enum bp_result (*dac2_encoder_control)(
+               struct bios_parser *bp,
+               bool enable,
+               uint32_t pixel_clock,
+               uint8_t dac_standard);
+       enum bp_result (*dac1_output_control)(
+               struct bios_parser *bp,
+               bool enable);
+       enum bp_result (*dac2_output_control)(
+               struct bios_parser *bp,
+               bool enable);
+       enum bp_result (*set_crtc_timing)(
+               struct bios_parser *bp,
+               struct bp_hw_crtc_timing_parameters *bp_params);
+       enum bp_result (*select_crtc_source)(
+               struct bios_parser *bp,
+               struct bp_crtc_source_select *bp_params);
+       enum bp_result (*enable_crtc)(
+               struct bios_parser *bp,
+               enum controller_id controller_id,
+               bool enable);
+       enum bp_result (*enable_crtc_mem_req)(
+               struct bios_parser *bp,
+               enum controller_id controller_id,
+               bool enable);
+       enum bp_result (*program_clock)(
+               struct bios_parser *bp,
+               struct bp_pixel_clock_parameters *bp_params);
+       enum bp_result (*external_encoder_control)(
+                       struct bios_parser *bp,
+                       struct bp_external_encoder_control *cntl);
+       enum bp_result (*enable_disp_power_gating)(
+               struct bios_parser *bp,
+               enum controller_id crtc_id,
+               enum bp_pipe_control_action action);
+       enum bp_result (*set_dce_clock)(
+               struct bios_parser *bp,
+               struct bp_set_dce_clock_parameters *bp_params);
+       unsigned int (*get_smu_clock_info)(
+                       struct bios_parser *bp);
+
+};
+
+void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
new file mode 100644 (file)
index 0000000..b0dcad2
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "ObjectID.h"
+#include "atomfirmware.h"
+#include "atomfirmwareid.h"
+
+#include "include/bios_parser_types.h"
+
+#include "command_table_helper2.h"
+
+bool dal_bios_parser_init_cmd_tbl_helper2(
+       const struct command_table_helper **h,
+       enum dce_version dce)
+{
+       switch (dce) {
+       case DCE_VERSION_8_0:
+               *h = dal_cmd_tbl_helper_dce80_get_table();
+               return true;
+
+       case DCE_VERSION_10_0:
+               *h = dal_cmd_tbl_helper_dce110_get_table();
+               return true;
+
+       case DCE_VERSION_11_0:
+               *h = dal_cmd_tbl_helper_dce110_get_table();
+               return true;
+
+       case DCE_VERSION_11_2:
+               *h = dal_cmd_tbl_helper_dce112_get_table2();
+               return true;
+#if defined(CONFIG_DRM_AMD_DC_DCE12_0)
+       case DCE_VERSION_12_0:
+               *h = dal_cmd_tbl_helper_dce112_get_table2();
+               return true;
+#endif
+
+       default:
+               /* Unsupported DCE */
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+}
+
+/* real implementations */
+
+bool dal_cmd_table_helper_controller_id_to_atom2(
+       enum controller_id id,
+       uint8_t *atom_id)
+{
+       if (atom_id == NULL) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       switch (id) {
+       case CONTROLLER_ID_D0:
+               *atom_id = ATOM_CRTC1;
+               return true;
+       case CONTROLLER_ID_D1:
+               *atom_id = ATOM_CRTC2;
+               return true;
+       case CONTROLLER_ID_D2:
+               *atom_id = ATOM_CRTC3;
+               return true;
+       case CONTROLLER_ID_D3:
+               *atom_id = ATOM_CRTC4;
+               return true;
+       case CONTROLLER_ID_D4:
+               *atom_id = ATOM_CRTC5;
+               return true;
+       case CONTROLLER_ID_D5:
+               *atom_id = ATOM_CRTC6;
+               return true;
+       /* TODO :case CONTROLLER_ID_UNDERLAY0:
+               *atom_id = ATOM_UNDERLAY_PIPE0;
+               return true;
+       */
+       case CONTROLLER_ID_UNDEFINED:
+               *atom_id = ATOM_CRTC_INVALID;
+               return true;
+       default:
+               /* Wrong controller id */
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+}
+
+/**
+* translate_transmitter_bp_to_atom
+*
+* @brief
+*  Translate the Transmitter to the corresponding ATOM BIOS value
+*
+* @param
+*   input transmitter
+*   output digitalTransmitter
+*    // =00: Digital Transmitter1 ( UNIPHY linkAB )
+*    // =01: Digital Transmitter2 ( UNIPHY linkCD )
+*    // =02: Digital Transmitter3 ( UNIPHY linkEF )
+*/
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom2(
+       enum transmitter t)
+{
+       switch (t) {
+       case TRANSMITTER_UNIPHY_A:
+       case TRANSMITTER_UNIPHY_B:
+       case TRANSMITTER_TRAVIS_LCD:
+               return 0;
+       case TRANSMITTER_UNIPHY_C:
+       case TRANSMITTER_UNIPHY_D:
+               return 1;
+       case TRANSMITTER_UNIPHY_E:
+       case TRANSMITTER_UNIPHY_F:
+               return 2;
+       default:
+               /* Invalid Transmitter Type! */
+               BREAK_TO_DEBUGGER();
+               return 0;
+       }
+}
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2(
+       enum signal_type s,
+       bool enable_dp_audio)
+{
+       switch (s) {
+       case SIGNAL_TYPE_DVI_SINGLE_LINK:
+       case SIGNAL_TYPE_DVI_DUAL_LINK:
+               return ATOM_ENCODER_MODE_DVI;
+       case SIGNAL_TYPE_HDMI_TYPE_A:
+               return ATOM_ENCODER_MODE_HDMI;
+       case SIGNAL_TYPE_LVDS:
+               return ATOM_ENCODER_MODE_LVDS;
+       case SIGNAL_TYPE_EDP:
+       case SIGNAL_TYPE_DISPLAY_PORT_MST:
+       case SIGNAL_TYPE_DISPLAY_PORT:
+       case SIGNAL_TYPE_VIRTUAL:
+               if (enable_dp_audio)
+                       return ATOM_ENCODER_MODE_DP_AUDIO;
+               else
+                       return ATOM_ENCODER_MODE_DP;
+       case SIGNAL_TYPE_RGB:
+               return ATOM_ENCODER_MODE_CRT;
+       default:
+               return ATOM_ENCODER_MODE_CRT;
+       }
+}
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src2(
+       enum clock_source_id id,
+       uint32_t *ref_clk_src_id)
+{
+       if (ref_clk_src_id == NULL) {
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+
+       switch (id) {
+       case CLOCK_SOURCE_ID_PLL1:
+               *ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL;
+               return true;
+       case CLOCK_SOURCE_ID_PLL2:
+               *ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL;
+               return true;
+       /*TODO:case CLOCK_SOURCE_ID_DCPLL:
+               *ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL;
+               return true;
+       */
+       case CLOCK_SOURCE_ID_EXTERNAL:
+               *ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK;
+               return true;
+       case CLOCK_SOURCE_ID_UNDEFINED:
+               *ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID;
+               return true;
+       default:
+               /* Unsupported clock source id */
+               BREAK_TO_DEBUGGER();
+               return false;
+       }
+}
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom2(
+       enum encoder_id id)
+{
+       switch (id) {
+       case ENCODER_ID_INTERNAL_LVDS:
+               return ENCODER_OBJECT_ID_INTERNAL_LVDS;
+       case ENCODER_ID_INTERNAL_TMDS1:
+               return ENCODER_OBJECT_ID_INTERNAL_TMDS1;
+       case ENCODER_ID_INTERNAL_TMDS2:
+               return ENCODER_OBJECT_ID_INTERNAL_TMDS2;
+       case ENCODER_ID_INTERNAL_DAC1:
+               return ENCODER_OBJECT_ID_INTERNAL_DAC1;
+       case ENCODER_ID_INTERNAL_DAC2:
+               return ENCODER_OBJECT_ID_INTERNAL_DAC2;
+       case ENCODER_ID_INTERNAL_LVTM1:
+               return ENCODER_OBJECT_ID_INTERNAL_LVTM1;
+       case ENCODER_ID_INTERNAL_HDMI:
+               return ENCODER_OBJECT_ID_HDMI_INTERNAL;
+       case ENCODER_ID_EXTERNAL_TRAVIS:
+               return ENCODER_OBJECT_ID_TRAVIS;
+       case ENCODER_ID_EXTERNAL_NUTMEG:
+               return ENCODER_OBJECT_ID_NUTMEG;
+       case ENCODER_ID_INTERNAL_KLDSCP_TMDS1:
+               return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
+       case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
+               return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
+       case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
+               return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
+       case ENCODER_ID_EXTERNAL_MVPU_FPGA:
+               return ENCODER_OBJECT_ID_MVPU_FPGA;
+       case ENCODER_ID_INTERNAL_DDI:
+               return ENCODER_OBJECT_ID_INTERNAL_DDI;
+       case ENCODER_ID_INTERNAL_UNIPHY:
+               return ENCODER_OBJECT_ID_INTERNAL_UNIPHY;
+       case ENCODER_ID_INTERNAL_KLDSCP_LVTMA:
+               return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA;
+       case ENCODER_ID_INTERNAL_UNIPHY1:
+               return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1;
+       case ENCODER_ID_INTERNAL_UNIPHY2:
+               return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2;
+       case ENCODER_ID_INTERNAL_UNIPHY3:
+               return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3;
+       case ENCODER_ID_INTERNAL_WIRELESS:
+               return ENCODER_OBJECT_ID_INTERNAL_VCE;
+       case ENCODER_ID_INTERNAL_VIRTUAL:
+               return ENCODER_OBJECT_ID_NONE;
+       case ENCODER_ID_UNKNOWN:
+               return ENCODER_OBJECT_ID_NONE;
+       default:
+               /* Invalid encoder id */
+               BREAK_TO_DEBUGGER();
+               return ENCODER_OBJECT_ID_NONE;
+       }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h
new file mode 100644 (file)
index 0000000..9f587c9
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER2_H__
+#define __DAL_COMMAND_TABLE_HELPER2_H__
+
+#include "dce80/command_table_helper_dce80.h"
+#include "dce110/command_table_helper_dce110.h"
+#include "dce112/command_table_helper2_dce112.h"
+
+struct command_table_helper {
+       bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id);
+       uint8_t (*encoder_action_to_atom)(
+                       enum bp_encoder_control_action action);
+       uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s,
+                       bool enable_dp_audio);
+       bool (*engine_bp_to_atom)(enum engine_id engine_id,
+                       uint32_t *atom_engine_id);
+       bool (*clock_source_id_to_atom)(enum clock_source_id id,
+                       uint32_t *atom_pll_id);
+       bool (*clock_source_id_to_ref_clk_src)(
+                       enum clock_source_id id,
+                       uint32_t *ref_clk_src_id);
+       uint8_t (*transmitter_bp_to_atom)(enum transmitter t);
+       uint8_t (*encoder_id_to_atom)(enum encoder_id id);
+       uint8_t (*clock_source_id_to_atom_phy_clk_src_id)(
+                       enum clock_source_id id);
+       uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s);
+       uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id);
+       uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id);
+       uint8_t (*phy_id_to_atom)(enum transmitter t);
+       uint8_t (*disp_power_gating_action_to_atom)(
+                       enum bp_pipe_control_action action);
+       bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id,
+                       uint32_t *atom_clock_type);
+       uint8_t (*transmitter_color_depth_to_atom)(
+                       enum transmitter_color_depth id);
+};
+
+bool dal_bios_parser_init_cmd_tbl_helper2(const struct command_table_helper **h,
+       enum dce_version dce);
+
+bool dal_cmd_table_helper_controller_id_to_atom2(
+       enum controller_id id,
+       uint8_t *atom_id);
+
+uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom2(
+       enum signal_type s,
+       bool enable_dp_audio);
+
+bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src2(
+       enum clock_source_id id,
+       uint32_t *ref_clk_src_id);
+
+uint8_t dal_cmd_table_helper_transmitter_bp_to_atom2(
+       enum transmitter t);
+
+uint8_t dal_cmd_table_helper_encoder_id_to_atom2(
+       enum encoder_id id);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
new file mode 100644 (file)
index 0000000..d342cde
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include "dm_services.h"
+
+#include "atom.h"
+
+#include "include/bios_parser_types.h"
+
+#include "../command_table_helper2.h"
+
+static uint8_t phy_id_to_atom(enum transmitter t)
+{
+       uint8_t atom_phy_id;
+
+       switch (t) {
+       case TRANSMITTER_UNIPHY_A:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+               break;
+       case TRANSMITTER_UNIPHY_B:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYB;
+               break;
+       case TRANSMITTER_UNIPHY_C:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYC;
+               break;
+       case TRANSMITTER_UNIPHY_D:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYD;
+               break;
+       case TRANSMITTER_UNIPHY_E:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYE;
+               break;
+       case TRANSMITTER_UNIPHY_F:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYF;
+               break;
+       case TRANSMITTER_UNIPHY_G:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYG;
+               break;
+       default:
+               atom_phy_id = ATOM_PHY_ID_UNIPHYA;
+               break;
+       }
+       return atom_phy_id;
+}
+
+static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
+{
+       uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP;
+
+       switch (s) {
+       case SIGNAL_TYPE_DISPLAY_PORT:
+       case SIGNAL_TYPE_EDP:
+               atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP;
+               break;
+       case SIGNAL_TYPE_DVI_SINGLE_LINK:
+       case SIGNAL_TYPE_DVI_DUAL_LINK:
+               atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI;
+               break;
+       case SIGNAL_TYPE_HDMI_TYPE_A:
+               atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI;
+               break;
+       case SIGNAL_TYPE_DISPLAY_PORT_MST:
+               atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST;
+               break;
+       default:
+               atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI;
+               break;
+       }
+
+       return atom_dig_mode;
+}
+
+static uint8_t clock_source_id_to_atom_phy_clk_src_id(
+               enum clock_source_id id)
+{
+       uint8_t atom_phy_clk_src_id = 0;
+
+       switch (id) {
+       case CLOCK_SOURCE_ID_PLL0:
+               atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
+               break;
+       case CLOCK_SOURCE_ID_PLL1:
+               atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+               break;
+       case CLOCK_SOURCE_ID_PLL2:
+               atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
+               break;
+       case CLOCK_SOURCE_ID_EXTERNAL:
+               atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
+               break;
+       default:
+               atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
+               break;
+       }
+
+       return atom_phy_clk_src_id >> 2;
+}
+
+static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
+{
+       uint8_t atom_hpd_sel = 0;
+
+       switch (id) {
+       case HPD_SOURCEID1:
+               atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL;
+               break;
+       case HPD_SOURCEID2:
+               atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL;
+               break;
+       case HPD_SOURCEID3:
+               atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL;
+               break;
+       case HPD_SOURCEID4:
+               atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL;
+               break;
+       case HPD_SOURCEID5:
+               atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL;
+               break;
+       case HPD_SOURCEID6:
+               atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL;
+               break;
+       case HPD_SOURCEID_UNKNOWN:
+       default:
+               atom_hpd_sel = 0;
+               break;
+       }
+       return atom_hpd_sel;
+}
+
+static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
+{
+       uint8_t atom_dig_encoder_sel = 0;
+
+       switch (id) {
+       case ENGINE_ID_DIGA:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL;
+               break;
+       case ENGINE_ID_DIGB:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL;
+               break;
+       case ENGINE_ID_DIGC:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL;
+               break;
+       case ENGINE_ID_DIGD:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL;
+               break;
+       case ENGINE_ID_DIGE:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL;
+               break;
+       case ENGINE_ID_DIGF:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL;
+               break;
+       case ENGINE_ID_DIGG:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL;
+               break;
+       case ENGINE_ID_UNKNOWN:
+               /* No DIG_FRONT is associated to DIG_BACKEND */
+               atom_dig_encoder_sel = 0;
+               break;
+       default:
+               atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL;
+               break;
+       }
+
+       return 0;
+}
+
+static bool clock_source_id_to_atom(
+       enum clock_source_id id,
+       uint32_t *atom_pll_id)
+{
+       bool result = true;
+
+       if (atom_pll_id != NULL)
+               switch (id) {
+               case CLOCK_SOURCE_COMBO_PHY_PLL0:
+                       *atom_pll_id = ATOM_COMBOPHY_PLL0;
+                       break;
+               case CLOCK_SOURCE_COMBO_PHY_PLL1:
+                       *atom_pll_id = ATOM_COMBOPHY_PLL1;
+                       break;
+               case CLOCK_SOURCE_COMBO_PHY_PLL2:
+                       *atom_pll_id = ATOM_COMBOPHY_PLL2;
+                       break;
+               case CLOCK_SOURCE_COMBO_PHY_PLL3:
+                       *atom_pll_id = ATOM_COMBOPHY_PLL3;
+                       break;
+               case CLOCK_SOURCE_COMBO_PHY_PLL4:
+                       *atom_pll_id = ATOM_COMBOPHY_PLL4;
+                       break;
+               case CLOCK_SOURCE_COMBO_PHY_PLL5:
+                       *atom_pll_id = ATOM_COMBOPHY_PLL5;
+                       break;
+               case CLOCK_SOURCE_COMBO_DISPLAY_PLL0:
+                       *atom_pll_id = ATOM_PPLL0;
+                       break;
+               case CLOCK_SOURCE_ID_DFS:
+                       *atom_pll_id = ATOM_GCK_DFS;
+                       break;
+               case CLOCK_SOURCE_ID_VCE:
+                       *atom_pll_id = ATOM_DP_DTO;
+                       break;
+               case CLOCK_SOURCE_ID_DP_DTO:
+                       *atom_pll_id = ATOM_DP_DTO;
+                       break;
+               case CLOCK_SOURCE_ID_UNDEFINED:
+                       /* Should not happen */
+                       *atom_pll_id = ATOM_PPLL_INVALID;
+                       result = false;
+                       break;
+               default:
+                       result = false;
+                       break;
+               }
+
+       return result;
+}
+
+static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
+{
+       bool result = false;
+
+       if (atom_engine_id != NULL)
+               switch (id) {
+               case ENGINE_ID_DIGA:
+                       *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DIGB:
+                       *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DIGC:
+                       *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DIGD:
+                       *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DIGE:
+                       *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DIGF:
+                       *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DIGG:
+                       *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
+                       result = true;
+                       break;
+               case ENGINE_ID_DACA:
+                       *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
+                       result = true;
+                       break;
+               default:
+                       break;
+               }
+
+       return result;
+}
+
+static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
+{
+       uint8_t atom_action = 0;
+
+       switch (action) {
+       case ENCODER_CONTROL_ENABLE:
+               atom_action = ATOM_ENABLE;
+               break;
+       case ENCODER_CONTROL_DISABLE:
+               atom_action = ATOM_DISABLE;
+               break;
+       case ENCODER_CONTROL_SETUP:
+               atom_action = ATOM_ENCODER_CMD_STREAM_SETUP;
+               break;
+       case ENCODER_CONTROL_INIT:
+               atom_action = ATOM_ENCODER_INIT;
+               break;
+       default:
+               BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
+               break;
+       }
+
+       return atom_action;
+}
+
+static uint8_t disp_power_gating_action_to_atom(
+       enum bp_pipe_control_action action)
+{
+       uint8_t atom_pipe_action = 0;
+
+       switch (action) {
+       case ASIC_PIPE_DISABLE:
+               atom_pipe_action = ATOM_DISABLE;
+               break;
+       case ASIC_PIPE_ENABLE:
+               atom_pipe_action = ATOM_ENABLE;
+               break;
+       case ASIC_PIPE_INIT:
+               atom_pipe_action = ATOM_INIT;
+               break;
+       default:
+               ASSERT_CRITICAL(false); /* Unhandle action in driver! */
+               break;
+       }
+
+       return atom_pipe_action;
+}
+
+static bool dc_clock_type_to_atom(
+               enum bp_dce_clock_type id,
+               uint32_t *atom_clock_type)
+{
+       bool retCode = true;
+
+       if (atom_clock_type != NULL) {
+               switch (id) {
+               case DCECLOCK_TYPE_DISPLAY_CLOCK:
+                       *atom_clock_type = DCE_CLOCK_TYPE_DISPCLK;
+                       break;
+
+               case DCECLOCK_TYPE_DPREFCLK:
+                       *atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK;
+                       break;
+
+               default:
+                       ASSERT_CRITICAL(false); /* Unhandle action in driver! */
+                       break;
+               }
+       }
+
+       return retCode;
+}
+
+static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id)
+{
+       uint8_t atomColorDepth = 0;
+
+       switch (id) {
+       case TRANSMITTER_COLOR_DEPTH_24:
+               atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS;
+               break;
+       case TRANSMITTER_COLOR_DEPTH_30:
+               atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4;
+               break;
+       case TRANSMITTER_COLOR_DEPTH_36:
+               atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2;
+               break;
+       case TRANSMITTER_COLOR_DEPTH_48:
+               atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1;
+               break;
+       default:
+               ASSERT_CRITICAL(false); /* Unhandle action in driver! */
+               break;
+       }
+
+       return atomColorDepth;
+}
+
+/* function table */
+static const struct command_table_helper command_table_helper_funcs = {
+       .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom2,
+       .encoder_action_to_atom = encoder_action_to_atom,
+       .engine_bp_to_atom = engine_bp_to_atom,
+       .clock_source_id_to_atom = clock_source_id_to_atom,
+       .clock_source_id_to_atom_phy_clk_src_id =
+                       clock_source_id_to_atom_phy_clk_src_id,
+       .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
+       .hpd_sel_to_atom = hpd_sel_to_atom,
+       .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
+       .phy_id_to_atom = phy_id_to_atom,
+       .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
+       .clock_source_id_to_ref_clk_src = NULL,
+       .transmitter_bp_to_atom = NULL,
+       .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom2,
+       .encoder_mode_bp_to_atom =
+                       dal_cmd_table_helper_encoder_mode_bp_to_atom2,
+       .dc_clock_type_to_atom = dc_clock_type_to_atom,
+       .transmitter_color_depth_to_atom = transmitter_color_depth_to_atom,
+};
+
+/*
+ * dal_cmd_tbl_helper_dce110_get_table
+ *
+ * @brief
+ * Initialize command table helper functions
+ *
+ * @param
+ * const struct command_table_helper **h - [out] struct of functions
+ *
+ */
+const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2()
+{
+       return &command_table_helper_funcs;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h
new file mode 100644 (file)
index 0000000..abf28a0
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012-15 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DAL_COMMAND_TABLE_HELPER2_DCE112_H__
+#define __DAL_COMMAND_TABLE_HELPER2_DCE112_H__
+
+struct command_table_helper;
+
+/* Initialize command table helper functions */
+const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table2(void);
+
+#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */