aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/0272-drm-amd-display-Add-DCE12-bios-parser-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/0272-drm-amd-display-Add-DCE12-bios-parser-support.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/0272-drm-amd-display-Add-DCE12-bios-parser-support.patch3989
1 files changed, 3989 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/0272-drm-amd-display-Add-DCE12-bios-parser-support.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/0272-drm-amd-display-Add-DCE12-bios-parser-support.patch
new file mode 100644
index 00000000..db5f644f
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/0272-drm-amd-display-Add-DCE12-bios-parser-support.patch
@@ -0,0 +1,3989 @@
+From 4be1f3c0a235197dba29743dcbb84a34ae9101c3 Mon Sep 17 00:00:00 2001
+From: Harry Wentland <harry.wentland@amd.com>
+Date: Mon, 6 Mar 2017 14:29:52 -0500
+Subject: [PATCH 0272/4131] drm/amd/display: Add DCE12 bios parser support
+
+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 | 2085 ++++++++++++++++++++
+ drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h | 33 +
+ .../display/dc/bios/bios_parser_types_internal2.h | 74 +
+ .../gpu/drm/amd/display/dc/bios/command_table2.c | 813 ++++++++
+ .../gpu/drm/amd/display/dc/bios/command_table2.h | 105 +
+ .../amd/display/dc/bios/command_table_helper2.c | 260 +++
+ .../amd/display/dc/bios/command_table_helper2.h | 82 +
+ .../dc/bios/dce112/command_table_helper2_dce112.c | 418 ++++
+ .../dc/bios/dce112/command_table_helper2_dce112.h | 34 +
+ 9 files changed, 3904 insertions(+)
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table2.h
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
+ create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h
+
+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
+index 0000000..f6e77da
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -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
+index 0000000..cb40546
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.h
+@@ -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
+index 0000000..bf1f5c8
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser_types_internal2.h
+@@ -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
+index 0000000..36d1582
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+@@ -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
+index 0000000..59061b8
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h
+@@ -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
+index 0000000..b0dcad2
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+@@ -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
+index 0000000..9f587c9
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h
+@@ -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
+index 0000000..d342cde
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
+@@ -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
+index 0000000..abf28a0
+--- /dev/null
++++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.h
+@@ -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__ */
+--
+2.7.4
+