drm/amd/display: Power down hardware if set mode is not called before timeout
[WHY] In headless systems, if set mode is not called, hardware will not be powered down on boot, causing HW/SW discrepancies. Powering down hardware on boot will ensure SW state is accurate. [HOW] Set a timer callback on boot for 10 seconds. If set mode is not called within that time, power down hardware. Otherwise, do not power down. Signed-off-by: Sung Lee <sung.lee@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Родитель
eaa483642f
Коммит
ca751df231
|
@ -2683,6 +2683,13 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src)
|
||||||
dal_irq_service_ack(dc->res_pool->irqs, src);
|
dal_irq_service_ack(dc->res_pool->irqs, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dc_power_down_on_boot(struct dc *dc)
|
||||||
|
{
|
||||||
|
if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW &&
|
||||||
|
dc->hwss.power_down_on_boot)
|
||||||
|
dc->hwss.power_down_on_boot(dc);
|
||||||
|
}
|
||||||
|
|
||||||
void dc_set_power_state(
|
void dc_set_power_state(
|
||||||
struct dc *dc,
|
struct dc *dc,
|
||||||
enum dc_acpi_cm_power_state power_state)
|
enum dc_acpi_cm_power_state power_state)
|
||||||
|
|
|
@ -1029,6 +1029,7 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
|
||||||
*/
|
*/
|
||||||
bool dc_commit_state(struct dc *dc, struct dc_state *context);
|
bool dc_commit_state(struct dc *dc, struct dc_state *context);
|
||||||
|
|
||||||
|
void dc_power_down_on_boot(struct dc *dc);
|
||||||
|
|
||||||
struct dc_state *dc_create_state(struct dc *dc);
|
struct dc_state *dc_create_state(struct dc *dc);
|
||||||
struct dc_state *dc_copy_state(struct dc_state *src_ctx);
|
struct dc_state *dc_copy_state(struct dc_state *src_ctx);
|
||||||
|
@ -1229,6 +1230,8 @@ void dc_set_power_state(
|
||||||
enum dc_acpi_cm_power_state power_state);
|
enum dc_acpi_cm_power_state power_state);
|
||||||
void dc_resume(struct dc *dc);
|
void dc_resume(struct dc *dc);
|
||||||
|
|
||||||
|
void dc_power_down_on_boot(struct dc *dc);
|
||||||
|
|
||||||
#if defined(CONFIG_DRM_AMD_DC_HDCP)
|
#if defined(CONFIG_DRM_AMD_DC_HDCP)
|
||||||
/*
|
/*
|
||||||
* HDCP Interfaces
|
* HDCP Interfaces
|
||||||
|
|
|
@ -1390,38 +1390,6 @@ void dcn10_init_hw(struct dc *dc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In headless boot cases, DIG may be turned
|
|
||||||
* on which causes HW/SW discrepancies.
|
|
||||||
* To avoid this, power down hardware on boot
|
|
||||||
* if DIG is turned on and seamless boot not enabled
|
|
||||||
*/
|
|
||||||
if (dc->config.power_down_display_on_boot) {
|
|
||||||
struct dc_link *edp_link = get_edp_link(dc);
|
|
||||||
|
|
||||||
if (edp_link &&
|
|
||||||
edp_link->link_enc->funcs->is_dig_enabled &&
|
|
||||||
edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
|
|
||||||
dc->hwseq->funcs.edp_backlight_control &&
|
|
||||||
dc->hwss.power_down &&
|
|
||||||
dc->hwss.edp_power_control) {
|
|
||||||
dc->hwseq->funcs.edp_backlight_control(edp_link, false);
|
|
||||||
dc->hwss.power_down(dc);
|
|
||||||
dc->hwss.edp_power_control(edp_link, false);
|
|
||||||
} else {
|
|
||||||
for (i = 0; i < dc->link_count; i++) {
|
|
||||||
struct dc_link *link = dc->links[i];
|
|
||||||
|
|
||||||
if (link->link_enc->funcs->is_dig_enabled &&
|
|
||||||
link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
|
|
||||||
dc->hwss.power_down) {
|
|
||||||
dc->hwss.power_down(dc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_optimized_init_done) {
|
if (!is_optimized_init_done) {
|
||||||
|
|
||||||
for (i = 0; i < res_pool->audio_count; i++) {
|
for (i = 0; i < res_pool->audio_count; i++) {
|
||||||
|
@ -1472,6 +1440,43 @@ void dcn10_init_hw(struct dc *dc)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In headless boot cases, DIG may be turned
|
||||||
|
* on which causes HW/SW discrepancies.
|
||||||
|
* To avoid this, power down hardware on boot
|
||||||
|
* if DIG is turned on and seamless boot not enabled
|
||||||
|
*/
|
||||||
|
void dcn10_power_down_on_boot(struct dc *dc)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (dc->config.power_down_display_on_boot) {
|
||||||
|
struct dc_link *edp_link = get_edp_link(dc);
|
||||||
|
|
||||||
|
if (edp_link &&
|
||||||
|
edp_link->link_enc->funcs->is_dig_enabled &&
|
||||||
|
edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
|
||||||
|
dc->hwseq->funcs.edp_backlight_control &&
|
||||||
|
dc->hwss.power_down &&
|
||||||
|
dc->hwss.edp_power_control) {
|
||||||
|
dc->hwseq->funcs.edp_backlight_control(edp_link, false);
|
||||||
|
dc->hwss.power_down(dc);
|
||||||
|
dc->hwss.edp_power_control(edp_link, false);
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < dc->link_count; i++) {
|
||||||
|
struct dc_link *link = dc->links[i];
|
||||||
|
|
||||||
|
if (link->link_enc->funcs->is_dig_enabled &&
|
||||||
|
link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
|
||||||
|
dc->hwss.power_down) {
|
||||||
|
dc->hwss.power_down(dc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dcn10_reset_hw_ctx_wrap(
|
void dcn10_reset_hw_ctx_wrap(
|
||||||
struct dc *dc,
|
struct dc *dc,
|
||||||
struct dc_state *context)
|
struct dc_state *context)
|
||||||
|
|
|
@ -109,6 +109,7 @@ void dcn10_program_pipe(
|
||||||
void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx);
|
void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx);
|
||||||
void dcn10_init_hw(struct dc *dc);
|
void dcn10_init_hw(struct dc *dc);
|
||||||
void dcn10_init_pipes(struct dc *dc, struct dc_state *context);
|
void dcn10_init_pipes(struct dc *dc, struct dc_state *context);
|
||||||
|
void dcn10_power_down_on_boot(struct dc *dc);
|
||||||
enum dc_status dce110_apply_ctx_to_hw(
|
enum dc_status dce110_apply_ctx_to_hw(
|
||||||
struct dc *dc,
|
struct dc *dc,
|
||||||
struct dc_state *context);
|
struct dc_state *context);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
static const struct hw_sequencer_funcs dcn10_funcs = {
|
static const struct hw_sequencer_funcs dcn10_funcs = {
|
||||||
.program_gamut_remap = dcn10_program_gamut_remap,
|
.program_gamut_remap = dcn10_program_gamut_remap,
|
||||||
.init_hw = dcn10_init_hw,
|
.init_hw = dcn10_init_hw,
|
||||||
|
.power_down_on_boot = dcn10_power_down_on_boot,
|
||||||
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
||||||
.apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
|
.apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
|
||||||
.post_unlock_program_front_end = dcn10_post_unlock_program_front_end,
|
.post_unlock_program_front_end = dcn10_post_unlock_program_front_end,
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
static const struct hw_sequencer_funcs dcn20_funcs = {
|
static const struct hw_sequencer_funcs dcn20_funcs = {
|
||||||
.program_gamut_remap = dcn10_program_gamut_remap,
|
.program_gamut_remap = dcn10_program_gamut_remap,
|
||||||
.init_hw = dcn10_init_hw,
|
.init_hw = dcn10_init_hw,
|
||||||
|
.power_down_on_boot = dcn10_power_down_on_boot,
|
||||||
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
||||||
.apply_ctx_for_surface = NULL,
|
.apply_ctx_for_surface = NULL,
|
||||||
.program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
|
.program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
static const struct hw_sequencer_funcs dcn21_funcs = {
|
static const struct hw_sequencer_funcs dcn21_funcs = {
|
||||||
.program_gamut_remap = dcn10_program_gamut_remap,
|
.program_gamut_remap = dcn10_program_gamut_remap,
|
||||||
.init_hw = dcn10_init_hw,
|
.init_hw = dcn10_init_hw,
|
||||||
|
.power_down_on_boot = dcn10_power_down_on_boot,
|
||||||
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
.apply_ctx_to_hw = dce110_apply_ctx_to_hw,
|
||||||
.apply_ctx_for_surface = NULL,
|
.apply_ctx_for_surface = NULL,
|
||||||
.program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
|
.program_front_end_for_ctx = dcn20_program_front_end_for_ctx,
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct hw_sequencer_funcs {
|
||||||
|
|
||||||
/* Pipe Programming Related */
|
/* Pipe Programming Related */
|
||||||
void (*init_hw)(struct dc *dc);
|
void (*init_hw)(struct dc *dc);
|
||||||
|
void (*power_down_on_boot)(struct dc *dc);
|
||||||
void (*enable_accelerated_mode)(struct dc *dc,
|
void (*enable_accelerated_mode)(struct dc *dc,
|
||||||
struct dc_state *context);
|
struct dc_state *context);
|
||||||
enum dc_status (*apply_ctx_to_hw)(struct dc *dc,
|
enum dc_status (*apply_ctx_to_hw)(struct dc *dc,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче