/* * Copyright 2019 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 *
*/
/* * Convert dmcub psr state to dmcu psr state.
*/ staticenum dc_psr_state convert_psr_state(uint32_t raw_state)
{ enum dc_psr_state state = PSR_STATE0;
if (raw_state == 0)
state = PSR_STATE0; elseif (raw_state == 0x10)
state = PSR_STATE1; elseif (raw_state == 0x11)
state = PSR_STATE1a; elseif (raw_state == 0x20)
state = PSR_STATE2; elseif (raw_state == 0x21)
state = PSR_STATE2a; elseif (raw_state == 0x22)
state = PSR_STATE2b; elseif (raw_state == 0x30)
state = PSR_STATE3; elseif (raw_state == 0x31)
state = PSR_STATE3Init; elseif (raw_state == 0x40)
state = PSR_STATE4; elseif (raw_state == 0x41)
state = PSR_STATE4a; elseif (raw_state == 0x42)
state = PSR_STATE4b; elseif (raw_state == 0x43)
state = PSR_STATE4c; elseif (raw_state == 0x44)
state = PSR_STATE4d; elseif (raw_state == 0x50)
state = PSR_STATE5; elseif (raw_state == 0x51)
state = PSR_STATE5a; elseif (raw_state == 0x52)
state = PSR_STATE5b; elseif (raw_state == 0x53)
state = PSR_STATE5c; elseif (raw_state == 0x4A)
state = PSR_STATE4_FULL_FRAME; elseif (raw_state == 0x4B)
state = PSR_STATE4a_FULL_FRAME; elseif (raw_state == 0x4C)
state = PSR_STATE4b_FULL_FRAME; elseif (raw_state == 0x4D)
state = PSR_STATE4c_FULL_FRAME; elseif (raw_state == 0x4E)
state = PSR_STATE4_FULL_FRAME_POWERUP; elseif (raw_state == 0x4F)
state = PSR_STATE4_FULL_FRAME_HW_LOCK; elseif (raw_state == 0x60)
state = PSR_STATE_HWLOCK_MGR; elseif (raw_state == 0x61)
state = PSR_STATE_POLLVUPDATE; elseif (raw_state == 0x62)
state = PSR_STATE_RELEASE_HWLOCK_MGR_FULL_FRAME; else
state = PSR_STATE_INVALID;
return state;
}
/* * Get PSR state from firmware.
*/ staticvoid dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst)
{
uint32_t raw_state = 0;
uint32_t retry_count = 0;
do { // Send gpint command and wait for ack if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_PSR_STATE, panel_inst, &raw_state,
DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
*state = convert_psr_state(raw_state);
} else { // Return invalid state when GPINT times out
*state = PSR_STATE_INVALID;
}
} while (++retry_count <= 1000 && *state == PSR_STATE_INVALID);
// Assert if max retry hit if (retry_count >= 1000 && *state == PSR_STATE_INVALID) {
ASSERT(0);
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
WPP_BIT_FLAG_Firmware_PsrState, "Unable to get PSR state from FW.");
} else
DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
WPP_BIT_FLAG_Firmware_PsrState, "Got PSR state from FW. PSR state: %d, Retry count: %d",
*state, retry_count);
}
/* * Set PSR version.
*/ staticbool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state *stream, uint8_t panel_inst)
{ union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx;
if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_UNSUPPORTED) returnfalse;
/* Below loops 1000 x 500us = 500 ms. * Exit PSR may need to wait 1-2 frames to power up. Timeout after at * least a few frames. Should never hit the max retry assert below.
*/ if (wait) { for (retry_count = 0; retry_count <= 1000; retry_count++) {
dmub_psr_get_state(dmub, &state, panel_inst);
if (enable) { if (state != PSR_STATE0) break;
} else { if (state == PSR_STATE0) break;
}
/* must *not* be fsleep - this can be called from high irq levels */
udelay(500);
}
/* assert if max retry hit */ if (retry_count >= 1000)
ASSERT(0);
}
}
/* * Set PSR level.
*/ staticvoid dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_t panel_inst)
{ union dmub_rb_cmd cmd; enum dc_psr_state state = PSR_STATE0; struct dc_context *dc = dmub->ctx;
/* * Setup PSR by programming phy registers and sending psr hw context values to firmware.
*/ staticbool dmub_psr_copy_settings(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context,
uint8_t panel_inst)
{ union dmub_rb_cmd cmd = { 0 }; struct dc_context *dc = dmub->ctx; struct dmub_cmd_psr_copy_settings_data *copy_settings_data
= &cmd.psr_copy_settings.psr_copy_settings_data; struct pipe_ctx *pipe_ctx = NULL; struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx; int i = 0;
for (i = 0; i < MAX_PIPES; i++) { if (res_ctx->pipe_ctx[i].stream &&
res_ctx->pipe_ctx[i].stream->link == link &&
res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) {
pipe_ctx = &res_ctx->pipe_ctx[i]; //TODO: refactor for multi edp support break;
}
}
if (!pipe_ctx) returnfalse;
// First, set the psr version if (!dmub_psr_set_version(dmub, pipe_ctx->stream, panel_inst)) returnfalse;
// Program DP DPHY fast training registers
link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc,
psr_context->psrExitLinkTrainingRequired);
// Program DP_SEC_CNTL1 register to set transmission GPS0 line num and priority to high
link->link_enc->funcs->psr_program_secondary_packet(link->link_enc,
psr_context->sdpTransmitLineNumDeadline);
/** * WA for PSRSU+DSC on specific TCON, if DSC is enabled, force PSRSU as ffu mode(full frame update) * Note that PSRSU+DSC is still under development.
*/ if (copy_settings_data->dsc_enable_status &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1, sizeof(DP_SINK_DEVICE_STR_ID_1)))
link->psr_settings.force_ffu_mode = 1;
//WA for PSR1 on specific TCON, require frame delay for frame re-lock
copy_settings_data->relock_delay_frame_cnt = 0; if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
copy_settings_data->relock_delay_frame_cnt = 2;
/* * Send command to PSR to force static ENTER and ignore all state changes until exit
*/ staticvoid dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst)
{ union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.