[PATCH 063/100] drm/amd/display: Add DCE12 bios parser support
Mike Lothian
mike at fireburn.co.uk
Thu Aug 3 21:04:12 UTC 2017
Hi
I've just tested out the new amd-staging-drm-next branch and noticed the
following warning caused by this patch
drivers/gpu/drm/amd/amdgpu/../display/dc/bios/bios_parser2.c: In function
‘get_embedded_panel_info_v2_1’:
drivers/gpu/drm/amd/amdgpu/../display/dc/bios/bios_parser2.c:1335:3:
warning: overflow in implicit constant conversion [-Woverflow]
lvds->lcd_timing.miscinfo & ATOM_INTERLACE;
^~~~
Cheers
Mike
On Mon, 20 Mar 2017 at 20:35 Alex Deucher <alexdeucher at gmail.com> wrote:
> From: Harry Wentland <harry.wentland at amd.com>
>
> Signed-off-by: Harry Wentland <harry.wentland at amd.com>
> Signed-off-by: Alex Deucher <alexander.deucher at 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_di
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/amd-gfx/attachments/20170803/c008b2a9/attachment-0001.html>
More information about the amd-gfx
mailing list