2693 lines · 80.0 KB · C
RawDownload
/* * 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 "amdgpu.h"#include "atom.h" #include "include/bios_parser_interface.h" #include "command_table.h"#include "command_table_helper.h"#include "bios_parser_helper.h"#include "bios_parser_types_internal.h" #define EXEC_BIOS_CMD_TABLE(command, params)\	(amdgpu_atom_execute_table(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \		GetIndexIntoMasterTable(COMMAND, command), \		(uint32_t *)&params, sizeof(params)) == 0) #define BIOS_CMD_TABLE_REVISION(command, frev, crev)\	amdgpu_atom_parse_cmd_header(((struct amdgpu_device *)bp->base.ctx->driver_context)->mode_info.atom_context, \		GetIndexIntoMasterTable(COMMAND, command), &frev, &crev) #define BIOS_CMD_TABLE_PARA_REVISION(command)\	bios_cmd_table_para_revision(bp->base.ctx->driver_context, \		GetIndexIntoMasterTable(COMMAND, command)) 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_enable_spread_spectrum_on_ppll(struct bios_parser *bp);static void init_adjust_display_pll(struct bios_parser *bp);static void init_select_crtc_source(struct bios_parser *bp);static void init_dac_encoder_control(struct bios_parser *bp);static void init_dac_load_detection(struct bios_parser *bp);static void init_dac_output_control(struct bios_parser *bp);static void init_set_crtc_timing(struct bios_parser *bp);static void init_enable_crtc(struct bios_parser *bp);static void init_enable_crtc_mem_req(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_program_clock(struct bios_parser *bp);static void init_set_dce_clock(struct bios_parser *bp); void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp){	init_dig_encoder_control(bp);	init_transmitter_control(bp);	init_set_pixel_clock(bp);	init_enable_spread_spectrum_on_ppll(bp);	init_adjust_display_pll(bp);	init_select_crtc_source(bp);	init_dac_encoder_control(bp);	init_dac_load_detection(bp);	init_dac_output_control(bp);	init_set_crtc_timing(bp);	init_enable_crtc(bp);	init_enable_crtc_mem_req(bp);	init_program_clock(bp);	init_external_encoder_control(bp);	init_enable_disp_power_gating(bp);	init_set_dce_clock(bp);} static uint32_t bios_cmd_table_para_revision(void *dev,					     uint32_t index){	struct amdgpu_device *adev = dev;	uint8_t frev, crev; 	if (amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context,					index,					&frev, &crev))		return crev;	else		return 0;} /******************************************************************************* ******************************************************************************** ** **                  D I G E N C O D E R C O N T R O L ** ******************************************************************************** *******************************************************************************/static enum bp_result encoder_control_digx_v3(	struct bios_parser *bp,	struct bp_encoder_control *cntl); static enum bp_result encoder_control_digx_v4(	struct bios_parser *bp,	struct bp_encoder_control *cntl); static enum bp_result encoder_control_digx_v5(	struct bios_parser *bp,	struct bp_encoder_control *cntl); static void init_encoder_control_dig_v1(struct bios_parser *bp); static void init_dig_encoder_control(struct bios_parser *bp){	uint32_t version =		BIOS_CMD_TABLE_PARA_REVISION(DIGxEncoderControl); 	switch (version) {	case 2:		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v3;		break;	case 4:		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v4;		break; 	case 5:		bp->cmd_tbl.dig_encoder_control = encoder_control_digx_v5;		break; 	default:		init_encoder_control_dig_v1(bp);		break;	}} static enum bp_result encoder_control_dig_v1(	struct bios_parser *bp,	struct bp_encoder_control *cntl);static enum bp_result encoder_control_dig1_v1(	struct bios_parser *bp,	struct bp_encoder_control *cntl);static enum bp_result encoder_control_dig2_v1(	struct bios_parser *bp,	struct bp_encoder_control *cntl); static void init_encoder_control_dig_v1(struct bios_parser *bp){	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; 	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG1EncoderControl))		cmd_tbl->encoder_control_dig1 = encoder_control_dig1_v1;	else		cmd_tbl->encoder_control_dig1 = NULL; 	if (1 == BIOS_CMD_TABLE_PARA_REVISION(DIG2EncoderControl))		cmd_tbl->encoder_control_dig2 = encoder_control_dig2_v1;	else		cmd_tbl->encoder_control_dig2 = NULL; 	cmd_tbl->dig_encoder_control = encoder_control_dig_v1;} static enum bp_result encoder_control_dig_v1(	struct bios_parser *bp,	struct bp_encoder_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	struct cmd_tbl *cmd_tbl = &bp->cmd_tbl; 	if (cntl != NULL)		switch (cntl->engine_id) {		case ENGINE_ID_DIGA:			if (cmd_tbl->encoder_control_dig1 != NULL)				result =					cmd_tbl->encoder_control_dig1(bp, cntl);			break;		case ENGINE_ID_DIGB:			if (cmd_tbl->encoder_control_dig2 != NULL)				result =					cmd_tbl->encoder_control_dig2(bp, cntl);			break; 		default:			break;		} 	return result;} static enum bp_result encoder_control_dig1_v1(	struct bios_parser *bp,	struct bp_encoder_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; 	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params); 	if (EXEC_BIOS_CMD_TABLE(DIG1EncoderControl, params))		result = BP_RESULT_OK; 	return result;} static enum bp_result encoder_control_dig2_v1(	struct bios_parser *bp,	struct bp_encoder_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	DIG_ENCODER_CONTROL_PARAMETERS_V2 params = {0}; 	bp->cmd_helper->assign_control_parameter(bp->cmd_helper, cntl, &params); 	if (EXEC_BIOS_CMD_TABLE(DIG2EncoderControl, params))		result = BP_RESULT_OK; 	return result;} static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth){	switch (color_depth) {	case COLOR_DEPTH_UNDEFINED:		return PANEL_BPC_UNDEFINE;	case COLOR_DEPTH_666:		return PANEL_6BIT_PER_COLOR;	default:	case COLOR_DEPTH_888:		return PANEL_8BIT_PER_COLOR;	case COLOR_DEPTH_101010:		return PANEL_10BIT_PER_COLOR;	case COLOR_DEPTH_121212:		return PANEL_12BIT_PER_COLOR;	case COLOR_DEPTH_141414:		dm_error("14-bit color not supported by ATOMBIOS\n");		return PANEL_BPC_UNDEFINE;	case COLOR_DEPTH_161616:		return PANEL_16BIT_PER_COLOR;	}} static enum bp_result encoder_control_digx_v3(	struct bios_parser *bp,	struct bp_encoder_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	DIG_ENCODER_CONTROL_PARAMETERS_V3 params = {0}; 	if (LANE_COUNT_FOUR < cntl->lanes_number)		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */	else		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ 	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); 	/* We need to convert from KHz units into 10KHz units */	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));	params.ucEncoderMode =			(uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(					cntl->signal,					cntl->enable_dp_audio);	params.ucLaneNum = (uint8_t)(cntl->lanes_number);	params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))		result = BP_RESULT_OK; 	return result;} static enum bp_result encoder_control_digx_v4(	struct bios_parser *bp,	struct bp_encoder_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	DIG_ENCODER_CONTROL_PARAMETERS_V4 params = {0}; 	if (LANE_COUNT_FOUR < cntl->lanes_number)		params.acConfig.ucDPLinkRate = 1; /* dual link 2.7GHz */	else		params.acConfig.ucDPLinkRate = 0; /* single link 1.62GHz */ 	params.acConfig.ucDigSel = (uint8_t)(cntl->engine_id); 	/* We need to convert from KHz units into 10KHz units */	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action);	params.usPixelClock = cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));	params.ucEncoderMode =			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(					cntl->signal,					cntl->enable_dp_audio));	params.ucLaneNum = (uint8_t)(cntl->lanes_number);	params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))		result = BP_RESULT_OK; 	return result;} static enum bp_result encoder_control_digx_v5(	struct bios_parser *bp,	struct bp_encoder_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	ENCODER_STREAM_SETUP_PARAMETERS_V5 params = {0}; 	params.ucDigId = (uint8_t)(cntl->engine_id);	params.ucAction = bp->cmd_helper->encoder_action_to_atom(cntl->action); 	params.ulPixelClock = cntl->pixel_clock / 10;	params.ucDigMode =			(uint8_t)(bp->cmd_helper->encoder_mode_bp_to_atom(					cntl->signal,					cntl->enable_dp_audio));	params.ucLaneNum = (uint8_t)(cntl->lanes_number);	params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth); 	if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)		switch (cntl->color_depth) {		case COLOR_DEPTH_101010:			params.ulPixelClock =				(params.ulPixelClock * 30) / 24;			break;		case COLOR_DEPTH_121212:			params.ulPixelClock =				(params.ulPixelClock * 36) / 24;			break;		case COLOR_DEPTH_161616:			params.ulPixelClock =				(params.ulPixelClock * 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_v2(	struct bios_parser *bp,	struct bp_transmitter_control *cntl);static enum bp_result transmitter_control_v3(	struct bios_parser *bp,	struct bp_transmitter_control *cntl);static enum bp_result transmitter_control_v4(	struct bios_parser *bp,	struct bp_transmitter_control *cntl);static enum bp_result transmitter_control_v1_5(	struct bios_parser *bp,	struct bp_transmitter_control *cntl);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 = 0; 	if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl,			frev, crev) == false)		BREAK_TO_DEBUGGER();	switch (crev) {	case 2:		bp->cmd_tbl.transmitter_control = transmitter_control_v2;		break;	case 3:		bp->cmd_tbl.transmitter_control = transmitter_control_v3;		break;	case 4:		bp->cmd_tbl.transmitter_control = transmitter_control_v4;		break;	case 5:		bp->cmd_tbl.transmitter_control = transmitter_control_v1_5;		break;	case 6:		bp->cmd_tbl.transmitter_control = transmitter_control_v1_6;		break;	default:		dm_output_to_console("Don't have transmitter_control for v%d\n", crev);		bp->cmd_tbl.transmitter_control = NULL;		break;	}} static enum bp_result transmitter_control_v2(	struct bios_parser *bp,	struct bp_transmitter_control *cntl){	enum bp_result result = BP_RESULT_FAILURE;	DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 params;	enum connector_id connector_id =		dal_graphics_object_id_get_connector_id(cntl->connector_obj_id); 	memset(&params, 0, sizeof(params)); 	switch (cntl->transmitter) {	case TRANSMITTER_UNIPHY_A:	case TRANSMITTER_UNIPHY_B:	case TRANSMITTER_UNIPHY_C:	case TRANSMITTER_UNIPHY_D:	case TRANSMITTER_UNIPHY_E:	case TRANSMITTER_UNIPHY_F:	case TRANSMITTER_TRAVIS_LCD:		break;	default:		return BP_RESULT_BADINPUT;	} 	switch (cntl->action) {	case TRANSMITTER_CONTROL_INIT:		if ((CONNECTOR_ID_DUAL_LINK_DVII == connector_id) ||				(CONNECTOR_ID_DUAL_LINK_DVID == connector_id))			/* on INIT this bit should be set according to the			 * physical connector			 * Bit0: dual link connector flag			 * =0 connector is single link connector			 * =1 connector is dual link connector			 */			params.acConfig.fDualLinkConnector = 1; 		/* connector object id */		params.usInitInfo =				cpu_to_le16((uint8_t)cntl->connector_obj_id.id);		break;	case TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS:		/* voltage swing and pre-emphsis */		params.asMode.ucLaneSel = (uint8_t)cntl->lane_select;		params.asMode.ucLaneSet = (uint8_t)cntl->lane_settings;		break;	default:		/* if dual-link */		if (LANE_COUNT_FOUR < cntl->lanes_number) {			/* on ENABLE/DISABLE this bit should be set according to			 * actual timing (number of lanes)			 * Bit0: dual link connector flag			 * =0 connector is single link connector			 * =1 connector is dual link connector			 */			params.acConfig.fDualLinkConnector = 1; 			/* link rate, half for dual link			 * We need to convert from KHz units into 20KHz units			 */			params.usPixelClock =					cpu_to_le16((uint16_t)(cntl->pixel_clock / 20));		} else			/* link rate, half for dual link			 * We need to convert from KHz units into 10KHz units			 */			params.usPixelClock =					cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));		break;	} 	/* 00 - coherent mode	 * 01 - incoherent mode	 */ 	params.acConfig.fCoherentMode = cntl->coherent; 	if ((TRANSMITTER_UNIPHY_B == cntl->transmitter)			|| (TRANSMITTER_UNIPHY_D == cntl->transmitter)			|| (TRANSMITTER_UNIPHY_F == cntl->transmitter))		/* Bit2: Transmitter Link selection		 * =0 when bit0=0, single link A/C/E, when bit0=1,		 * master link A/C/E		 * =1 when bit0=0, single link B/D/F, when bit0=1,		 * master link B/D/F		 */		params.acConfig.ucLinkSel = 1; 	if (ENGINE_ID_DIGB == cntl->engine_id)		/* Bit3: Transmitter data source selection		 * =0 DIGA is data source.		 * =1 DIGB is data source.		 * This bit is only useful when ucAction= ATOM_ENABLE		 */

Lines 1–500 of 2693.