Commit ae79c310 authored by Harry Wentland's avatar Harry Wentland Committed by Alex Deucher

drm/amd/display: Add DCE12 bios parser support

Signed-off-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b7ad57b5
/*
* 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;
}
/*
* 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
/*
* 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
/*
* 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;
}
/*
* 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
/*
* 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;
}
}
/*
* 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
/*
* 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;
}
/*
* 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__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment