From 925f566cb7aedbcf26005035cf894ec824e8ca2f Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Thu, 27 Jun 2019 18:16:21 -0400 Subject: drm/amd/display: add set and get clock for testing purposes add dc_set_clock add dc_get_clock this is for testing and diagnostics to get/set DPPCLK and DISPCLK. Signed-off-by: Charlene Liu Reviewed-by: Dmytro Laktyushkin Acked-by: Leo Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h') diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 4d56d48a3179..36be08adae05 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -294,6 +294,15 @@ struct hw_sequencer_funcs { void (*disable_writeback)(struct dc *dc, unsigned int dwb_pipe_inst); #endif + enum dc_status (*set_clock)(struct dc *dc, + enum dc_clock_type clock_type, + uint32_t clk_khz, + uint32_t stepping); + + void (*get_clock)(struct dc *dc, + enum dc_clock_type clock_type, + struct dc_clock_config *clock_cfg); + }; void color_space_to_black_color( -- cgit v1.2.3 From f591344e89dca887afeb5bbe21fa199687fd4a5f Mon Sep 17 00:00:00 2001 From: Julian Parkin Date: Wed, 3 Jul 2019 13:59:26 -0400 Subject: drm/amd/display: Clean up dynamic metadata logic [Why] Code to enable DCN20 dynamic metadata feature is duplicated in two places and was added to DCE110 enable stream. [How] Create DCN20 specific enable stream function for clarity, and add a hardware sequencer function to program dynamic metadata to avoid the duplicate code. Signed-off-by: Julian Parkin Reviewed-by: Charlene Liu Acked-by: Leo Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 27 +++----- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 24 +------ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 74 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 + 4 files changed, 86 insertions(+), 40 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 352862370390..bf1d7bb90e0f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -566,6 +566,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, return ret; } + #if defined(CONFIG_DRM_AMD_DC_DCN2_0) bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream) { @@ -597,6 +598,14 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc, struct hubp *hubp; int i; + /* Dynamic metadata is only supported on HDMI or DP */ + if (!dc_is_hdmi_signal(stream->signal) && !dc_is_dp_signal(stream->signal)) + return false; + + /* Check hardware support */ + if (!dc->hwss.program_dmdata_engine) + return false; + for (i = 0; i < MAX_PIPES; i++) { pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe_ctx->stream == stream) @@ -612,23 +621,7 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc, pipe_ctx->stream->dmdata_address = attr->address; - if (pipe_ctx->stream_res.stream_enc && - pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) { - if (pipe_ctx->stream->dmdata_address.quad_part != 0) { - /* if using dynamic meta, don't set up generic infopackets */ - pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false; - pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata( - pipe_ctx->stream_res.stream_enc, - true, pipe_ctx->plane_res.hubp->inst, - dc_is_dp_signal(pipe_ctx->stream->signal) ? - dmdata_dp : dmdata_hdmi); - } else - pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata( - pipe_ctx->stream_res.stream_enc, - false, pipe_ctx->plane_res.hubp->inst, - dc_is_dp_signal(pipe_ctx->stream->signal) ? - dmdata_dp : dmdata_hdmi); - } + dc->hwss.program_dmdata_engine(pipe_ctx); if (hubp->funcs->dmdata_set_attributes != NULL && pipe_ctx->stream->dmdata_address.quad_part != 0) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 41f5ef6c5085..ddc5add503ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -667,29 +667,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, pipe_ctx->stream_res.stream_enc->id, true); - /* update AVI info frame (HDMI, DP)*/ - /* TODO: FPGA may change to hwss.update_info_frame */ - -#if defined(CONFIG_DRM_AMD_DC_DCN2_0) - if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL && - pipe_ctx->plane_res.hubp != NULL) { - if (pipe_ctx->stream->dmdata_address.quad_part != 0) { - /* if using dynamic meta, don't set up generic infopackets */ - pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false; - pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata( - pipe_ctx->stream_res.stream_enc, - true, pipe_ctx->plane_res.hubp->inst, - dc_is_dp_signal(pipe_ctx->stream->signal) ? - dmdata_dp : dmdata_hdmi); - } else - pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata( - pipe_ctx->stream_res.stream_enc, - false, pipe_ctx->plane_res.hubp->inst, - dc_is_dp_signal(pipe_ctx->stream->signal) ? - dmdata_dp : dmdata_hdmi); - } -#endif - dce110_update_info_frame(pipe_ctx); + link->dc->hwss.update_info_frame(pipe_ctx); /* enable early control to avoid corruption on DP monitor*/ active_total_with_borders = diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 566cd4cdfef4..76ce622e1421 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2056,6 +2056,78 @@ static void dcn20_set_flip_control_gsl( } +static void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) +{ + enum dc_lane_count lane_count = + pipe_ctx->stream->link->cur_link_settings.lane_count; + + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; + struct dc_link *link = pipe_ctx->stream->link; + + uint32_t active_total_with_borders; + uint32_t early_control = 0; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + /* For MST, there are multiply stream go to only one link. + * connect DIG back_end to front_end while enable_stream and + * disconnect them during disable_stream + * BY this, it is logic clean to separate stream and link + */ + link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + pipe_ctx->stream_res.stream_enc->id, true); + + if (link->dc->hwss.program_dmdata_engine) + link->dc->hwss.program_dmdata_engine(pipe_ctx); + + link->dc->hwss.update_info_frame(pipe_ctx); + + /* enable early control to avoid corruption on DP monitor*/ + active_total_with_borders = + timing->h_addressable + + timing->h_border_left + + timing->h_border_right; + + if (lane_count != 0) + early_control = active_total_with_borders % lane_count; + + if (early_control == 0) + early_control = lane_count; + + tg->funcs->set_early_control(tg, early_control); + + /* enable audio only within mode set */ + if (pipe_ctx->stream_res.audio != NULL) { + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); + } +} + +static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx) +{ + struct dc_stream_state *stream = pipe_ctx->stream; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + bool enable = false; + struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; + enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal) + ? dmdata_dp + : dmdata_hdmi; + + /* if using dynamic meta, don't set up generic infopackets */ + if (pipe_ctx->stream->dmdata_address.quad_part != 0) { + pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false; + enable = true; + } + + if (!hubp) + return; + + if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata) + return; + + stream_enc->funcs->set_dynamic_metadata(stream_enc, enable, + hubp->inst, mode); +} + void dcn20_hw_sequencer_construct(struct dc *dc) { dcn10_hw_sequencer_construct(dc); @@ -2080,6 +2152,8 @@ void dcn20_hw_sequencer_construct(struct dc *dc) dc->hwss.update_odm = dcn20_update_odm; dc->hwss.blank_pixel_data = dcn20_blank_pixel_data; dc->hwss.dmdata_status_done = dcn20_dmdata_status_done; + dc->hwss.program_dmdata_engine = dcn20_program_dmdata_engine; + dc->hwss.enable_stream = dcn20_enable_stream; dc->hwss.disable_stream = dcn20_disable_stream; dc->hwss.init_sys_ctx = dcn20_init_sys_ctx; dc->hwss.init_vm_ctx = dcn20_init_vm_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 36be08adae05..28645e10f854 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -231,6 +231,7 @@ struct hw_sequencer_funcs { bool (*update_bandwidth)( struct dc *dc, struct dc_state *context); + void (*program_dmdata_engine)(struct pipe_ctx *pipe_ctx); bool (*dmdata_status_done)(struct pipe_ctx *pipe_ctx); #endif -- cgit v1.2.3 From 8a31820b12187c7e31c52e8a00075359d9efac52 Mon Sep 17 00:00:00 2001 From: Martin Leung Date: Tue, 9 Jul 2019 15:15:17 -0400 Subject: drm/amd/display: Make init_hw and init_pipes generic for seamless boot [Why] For seamless boot the init_hw sequence must be split into actual hardware vs pipes, in order to defer pipe initialization to set mode and skip of pipe-destructive sequences [How] made dcn10_init_hw and dcn10_init_pipes generic for future dcns to inherit deleted dcn20 specific versions. This is part 1 of a 2 partimplementation of seamless boot Signed-off-by: Martin Leung Reviewed-by: Jun Lei Acked-by: Leo Li Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 12 +- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 6 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | 4 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 182 +++++++--- .../gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 381 ++++++++------------- drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 32 ++ 9 files changed, 312 insertions(+), 313 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h') diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 997615582528..94b55143827e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -731,7 +731,7 @@ static enum bp_result link_transmitter_control( * @brief * eDP only. */ -void hwss_edp_wait_for_hpd_ready( +void dce110_edp_wait_for_hpd_ready( struct dc_link *link, bool power_up) { @@ -799,7 +799,7 @@ void hwss_edp_wait_for_hpd_ready( } } -void hwss_edp_power_control( +void dce110_edp_power_control( struct dc_link *link, bool power_up) { @@ -881,7 +881,7 @@ void hwss_edp_power_control( * @brief * eDP only. Control the backlight of the eDP panel */ -void hwss_edp_backlight_control( +void dce110_edp_backlight_control( struct dc_link *link, bool enable) { @@ -2758,9 +2758,9 @@ static const struct hw_sequencer_funcs dce110_funcs = { .setup_stereo = NULL, .set_avmute = dce110_set_avmute, .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, - .edp_backlight_control = hwss_edp_backlight_control, - .edp_power_control = hwss_edp_power_control, - .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, + .edp_backlight_control = dce110_edp_backlight_control, + .edp_power_control = dce110_edp_power_control, + .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dce110_set_cursor_position, .set_cursor_attribute = dce110_set_cursor_attribute }; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index cd3e36d52a52..668feb0d169d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -73,15 +73,15 @@ void dce110_optimize_bandwidth( void dp_receiver_power_ctrl(struct dc_link *link, bool on); -void hwss_edp_power_control( +void dce110_edp_power_control( struct dc_link *link, bool power_up); -void hwss_edp_backlight_control( +void dce110_edp_backlight_control( struct dc_link *link, bool enable); -void hwss_edp_wait_for_hpd_ready( +void dce110_edp_wait_for_hpd_ready( struct dc_link *link, bool power_up); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index a780057e2dbc..a02c10e23e0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -104,7 +104,7 @@ void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow) DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow); } -bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub) +bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubbub) { struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); uint32_t enable = 0; @@ -945,6 +945,8 @@ static const struct hubbub_funcs hubbub1_funcs = { .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap, .wm_read_state = hubbub1_wm_read_state, .program_watermarks = hubbub1_program_watermarks, + .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled, + .allow_self_refresh_control = hubbub1_allow_self_refresh_control, }; void hubbub1_construct(struct hubbub *hubbub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h index 7c2559c9ae23..70e5d84fc69a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h @@ -247,7 +247,7 @@ void hubbub1_program_watermarks( void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow); -bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub); +bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubub); void hubbub1_toggle_watermark_change_req( struct hubbub *hubbub); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 51857cab1459..9dc11a43d6d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -438,7 +438,7 @@ bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx) return false; } -static void enable_power_gating_plane( +static void dcn10_enable_power_gating_plane( struct dce_hwseq *hws, bool enable) { @@ -460,7 +460,7 @@ static void enable_power_gating_plane( REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on); } -static void disable_vga( +static void dcn10_disable_vga( struct dce_hwseq *hws) { unsigned int in_vga1_mode = 0; @@ -493,7 +493,7 @@ static void disable_vga( REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1); } -static void dpp_pg_control( +static void dcn10_dpp_pg_control( struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) @@ -545,7 +545,7 @@ static void dpp_pg_control( } } -static void hubp_pg_control( +static void dcn10_hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) @@ -605,8 +605,8 @@ static void power_on_plane( if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(hws, plane_id, true); - hubp_pg_control(hws, plane_id, true); + hws->ctx->dc->hwss.dpp_pg_control(hws, plane_id, true); + hws->ctx->dc->hwss.hubp_pg_control(hws, plane_id, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); DC_LOG_DEBUG( @@ -627,7 +627,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - hubp_pg_control(hws, 0, false); + dc->hwss.hubp_pg_control(hws, 0, false); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); @@ -656,7 +656,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - hubp_pg_control(hws, 0, true); + dc->hwss.hubp_pg_control(hws, 0, true); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); @@ -664,10 +664,23 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc) hws->wa_state.DEGVIDCN10_253_applied = true; } -static void bios_golden_init(struct dc *dc) +static void dcn10_bios_golden_init(struct dc *dc) { struct dc_bios *bp = dc->ctx->dc_bios; int i; + bool allow_self_fresh_force_enable = true; + + if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled) + allow_self_fresh_force_enable = + dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub); + + + /* WA for making DF sleep when idle after resume from S0i3. + * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by + * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 + * before calling command table and it changed to 1 after, + * it should be set back to 0. + */ /* initialize dcn global */ bp->funcs->enable_disp_power_gating(bp, @@ -678,6 +691,12 @@ static void bios_golden_init(struct dc *dc) bp->funcs->enable_disp_power_gating(bp, CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE); } + + if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) + if (allow_self_fresh_force_enable == false && + dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub)) + dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, true); + } static void false_optc_underflow_wa( @@ -971,7 +990,7 @@ void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) dcn10_verify_allow_pstate_change_high(dc); } -static void plane_atomic_power_down(struct dc *dc, +static void dcn10_plane_atomic_power_down(struct dc *dc, struct dpp *dpp, struct hubp *hubp) { @@ -981,8 +1000,8 @@ static void plane_atomic_power_down(struct dc *dc, if (REG(DC_IP_REQUEST_CNTL)) { REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); - dpp_pg_control(hws, dpp->inst, false); - hubp_pg_control(hws, hubp->inst, false); + dc->hwss.dpp_pg_control(hws, dpp->inst, false); + dc->hwss.hubp_pg_control(hws, hubp->inst, false); dpp->funcs->dpp_reset(dpp); REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); @@ -994,7 +1013,7 @@ static void plane_atomic_power_down(struct dc *dc, /* disable HW used by plane. * note: cannot disable until disconnect is complete */ -static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) +static void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) { struct hubp *hubp = pipe_ctx->plane_res.hubp; struct dpp *dpp = pipe_ctx->plane_res.dpp; @@ -1014,7 +1033,7 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) hubp->power_gated = true; dc->optimized_required = false; /* We're powering off, no need to optimize */ - plane_atomic_power_down(dc, + dc->hwss.plane_atomic_power_down(dc, pipe_ctx->plane_res.dpp, pipe_ctx->plane_res.hubp); @@ -1033,7 +1052,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated) return; - plane_atomic_disable(dc, pipe_ctx); + dc->hwss.plane_atomic_disable(dc, pipe_ctx); apply_DEGVIDCN10_253_wa(dc); @@ -1068,9 +1087,14 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context) * command table. */ if (tg->funcs->is_tg_enabled(tg)) { - tg->funcs->lock(tg); - tg->funcs->set_blank(tg, true); - hwss_wait_for_blank_complete(tg); + if (dc->hwss.init_blank != NULL) { + dc->hwss.init_blank(dc, tg); + tg->funcs->lock(tg); + } else { + tg->funcs->lock(tg); + tg->funcs->set_blank(tg, true); + hwss_wait_for_blank_complete(tg); + } } } @@ -1114,12 +1138,12 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context) dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; - hwss1_plane_atomic_disconnect(dc, pipe_ctx); + dc->hwss.plane_atomic_disconnect(dc, pipe_ctx); if (tg->funcs->is_tg_enabled(tg)) tg->funcs->unlock(tg); - dcn10_disable_plane(dc, pipe_ctx); + dc->hwss.disable_plane(dc, pipe_ctx); pipe_ctx->stream_res.tg = NULL; pipe_ctx->plane_res.hubp = NULL; @@ -1135,8 +1159,17 @@ static void dcn10_init_hw(struct dc *dc) struct dmcu *dmcu = dc->res_pool->dmcu; struct dce_hwseq *hws = dc->hwseq; struct dc_bios *dcb = dc->ctx->dc_bios; + struct resource_pool *res_pool = dc->res_pool; + + if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) + dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); + + // Initialize the dccg + if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init) + dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg); if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + REG_WRITE(REFCLK_CNTL, 0); REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); REG_WRITE(DIO_MEM_PWR_CTRL, 0); @@ -1150,30 +1183,39 @@ static void dcn10_init_hw(struct dc *dc) REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); } - enable_power_gating_plane(dc->hwseq, true); + //Enable ability to power gate / don't force power on permanently + dc->hwss.enable_power_gating_plane(hws, true); - /* end of FPGA. Below if real ASIC */ return; } if (!dcb->funcs->is_accelerated_mode(dcb)) { - bool allow_self_fresh_force_enable = - hububu1_is_allow_self_refresh_enabled( - dc->res_pool->hubbub); - - bios_golden_init(dc); - - /* WA for making DF sleep when idle after resume from S0i3. - * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by - * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 - * before calling command table and it changed to 1 after, - * it should be set back to 0. - */ - if (allow_self_fresh_force_enable == false && - hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub)) - hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true); - - disable_vga(dc->hwseq); + dc->hwss.bios_golden_init(dc); + if (dc->ctx->dc_bios->fw_info_valid) { + res_pool->ref_clocks.xtalin_clock_inKhz = + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + if (res_pool->dccg && res_pool->hubbub) { + + (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, + dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, + &res_pool->ref_clocks.dccg_ref_clock_inKhz); + + (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, + res_pool->ref_clocks.dccg_ref_clock_inKhz, + &res_pool->ref_clocks.dchub_ref_clock_inKhz); + } else { + // Not all ASICs have DCCG sw component + res_pool->ref_clocks.dccg_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + res_pool->ref_clocks.dchub_ref_clock_inKhz = + res_pool->ref_clocks.xtalin_clock_inKhz; + } + } + } else + ASSERT_CRITICAL(false); + dc->hwss.disable_vga(dc->hwseq); } for (i = 0; i < dc->link_count; i++) { @@ -1191,6 +1233,13 @@ static void dcn10_init_hw(struct dc *dc) link->link_status.link_active = true; } + /* Power gate DSCs */ +#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT + for (i = 0; i < res_pool->res_cap->num_dsc; i++) + if (dc->hwss.dsc_pg_control != NULL) + dc->hwss.dsc_pg_control(hws, res_pool->dscs[i]->inst, false); +#endif + /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which * pipes we want to use. @@ -1199,10 +1248,21 @@ static void dcn10_init_hw(struct dc *dc) */ if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) { dc->hwss.init_pipes(dc, dc->current_state); + for (i = 0; i < res_pool->pipe_count; i++) { + struct hubp *hubp = res_pool->hubps[i]; + struct dpp *dpp = res_pool->dpps[i]; + + hubp->funcs->hubp_init(hubp); + res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst; + dc->hwss.plane_atomic_power_down(dc, dpp, hubp); + } + + apply_DEGVIDCN10_253_wa(dc); } - for (i = 0; i < dc->res_pool->audio_count; i++) { - struct audio *audio = dc->res_pool->audios[i]; + + for (i = 0; i < res_pool->audio_count; i++) { + struct audio *audio = res_pool->audios[i]; audio->funcs->hw_init(audio); } @@ -1230,7 +1290,7 @@ static void dcn10_init_hw(struct dc *dc) REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); } - enable_power_gating_plane(dc->hwseq, true); + dc->hwss.enable_power_gating_plane(dc->hwseq, true); memset(&dc->clk_mgr->clks, 0, sizeof(dc->clk_mgr->clks)); } @@ -1789,7 +1849,7 @@ static void dcn10_enable_plane( } } -static void program_gamut_remap(struct pipe_ctx *pipe_ctx) +static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx) { int i = 0; struct dpp_grph_csc_adjustment adjust; @@ -2220,7 +2280,7 @@ void update_dchubp_dpp( if (plane_state->update_flags.bits.full_update) { /*gamut remap*/ - program_gamut_remap(pipe_ctx); + dc->hwss.program_gamut_remap(pipe_ctx); dc->hwss.program_output_csc(dc, pipe_ctx, @@ -2457,7 +2517,7 @@ static void dcn10_apply_ctx_for_surface( if (old_pipe_ctx->stream_res.tg == tg && old_pipe_ctx->plane_res.hubp && old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID) - dcn10_disable_plane(dc, old_pipe_ctx); + dc->hwss.disable_plane(dc, old_pipe_ctx); } if ((!pipe_ctx->plane_state || @@ -2505,7 +2565,7 @@ static void dcn10_apply_ctx_for_surface( for (i = 0; i < dc->res_pool->pipe_count; i++) if (removed_pipe[i]) - dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]); for (i = 0; i < dc->res_pool->pipe_count; i++) if (removed_pipe[i]) { @@ -2597,7 +2657,7 @@ static void dcn10_optimize_bandwidth( dcn10_verify_allow_pstate_change_high(dc); } -static void set_drr(struct pipe_ctx **pipe_ctx, +static void dcn10_set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, int vmin, int vmax) { int i = 0; @@ -2622,7 +2682,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, } } -static void get_position(struct pipe_ctx **pipe_ctx, +static void dcn10_get_position(struct pipe_ctx **pipe_ctx, int num_pipes, struct crtc_position *position) { @@ -2634,7 +2694,7 @@ static void get_position(struct pipe_ctx **pipe_ctx, pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position); } -static void set_static_screen_control(struct pipe_ctx **pipe_ctx, +static void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_events *events) { unsigned int i; @@ -3125,7 +3185,7 @@ static void dcn10_get_clock(struct dc *dc, } static const struct hw_sequencer_funcs dcn10_funcs = { - .program_gamut_remap = program_gamut_remap, + .program_gamut_remap = dcn10_program_gamut_remap, .init_hw = dcn10_init_hw, .init_pipes = dcn10_init_pipes, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, @@ -3158,18 +3218,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .optimize_bandwidth = dcn10_optimize_bandwidth, .reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap, .enable_stream_timing = dcn10_enable_stream_timing, - .set_drr = set_drr, - .get_position = get_position, - .set_static_screen_control = set_static_screen_control, + .set_drr = dcn10_set_drr, + .get_position = dcn10_get_position, + .set_static_screen_control = dcn10_set_static_screen_control, .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, .log_hw_state = dcn10_log_hw_state, .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, - .edp_backlight_control = hwss_edp_backlight_control, - .edp_power_control = hwss_edp_power_control, - .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, + .edp_backlight_control = dce110_edp_backlight_control, + .edp_power_control = dce110_edp_power_control, + .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dcn10_set_cursor_position, .set_cursor_attribute = dcn10_set_cursor_attribute, .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level, @@ -3179,6 +3239,16 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt, .set_clock = dcn10_set_clock, .get_clock = dcn10_get_clock, + .did_underflow_occur = dcn10_did_underflow_occur, + .init_blank = NULL, + .disable_vga = dcn10_disable_vga, + .bios_golden_init = dcn10_bios_golden_init, + .plane_atomic_disable = dcn10_plane_atomic_disable, + .plane_atomic_power_down = dcn10_plane_atomic_power_down, + .enable_power_gating_plane = dcn10_enable_power_gating_plane, + .dpp_pg_control = dcn10_dpp_pg_control, + .hubp_pg_control = dcn10_hubp_pg_control, + .dsc_pg_control = NULL, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c index 31d6e79ba2b8..cd101bbd8163 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c @@ -582,7 +582,7 @@ static const struct hubbub_funcs hubbub2_funcs = { .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap, .wm_read_state = hubbub2_wm_read_state, .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, - .program_watermarks = hubbub2_program_watermarks, + .program_watermarks = hubbub2_program_watermarks }; void hubbub2_construct(struct dcn20_hubbub *hubbub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index c11de6f0fe5c..c3635f5cd990 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -64,23 +64,7 @@ #define FN(reg_name, field_name) \ hws->shifts->field_name, hws->masks->field_name -static void bios_golden_init(struct dc *dc) -{ - struct dc_bios *bp = dc->ctx->dc_bios; - int i; - - /* initialize dcn global */ - bp->funcs->enable_disp_power_gating(bp, - CONTROLLER_ID_D0, ASIC_PIPE_INIT); - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - /* initialize dcn per pipe */ - bp->funcs->enable_disp_power_gating(bp, - CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE); - } -} - -static void enable_power_gating_plane( +static void dcn20_enable_power_gating_plane( struct dce_hwseq *hws, bool enable) { @@ -184,7 +168,7 @@ void dcn20_display_init(struct dc *dc) REG_WRITE(AZALIA_CONTROLLER_CLOCK_GATING, 0x1); } -static void disable_vga( +void dcn20_disable_vga( struct dce_hwseq *hws) { REG_WRITE(D1VGA_CONTROL, 0); @@ -487,29 +471,6 @@ static void dcn20_hubp_pg_control( } - -static void dcn20_plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx) -{ - struct dce_hwseq *hws = dc->hwseq; - struct dpp *dpp = pipe_ctx->plane_res.dpp; - - DC_LOGGER_INIT(dc->ctx->logger); - - if (REG(DC_IP_REQUEST_CNTL)) { - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 1); - dcn20_dpp_pg_control(hws, dpp->inst, false); - dcn20_hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, false); - dpp->funcs->dpp_reset(dpp); - REG_SET(DC_IP_REQUEST_CNTL, 0, - IP_REQUEST_EN, 0); - DC_LOG_DEBUG( - "Power gated front end %d\n", pipe_ctx->pipe_idx); - } -} - - - /* disable HW used by plane. * note: cannot disable until disconnect is complete */ @@ -535,7 +496,9 @@ static void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx) hubp->power_gated = true; dc->optimized_required = false; /* We're powering off, no need to optimize */ - dcn20_plane_atomic_power_down(dc, pipe_ctx); + dc->hwss.plane_atomic_power_down(dc, + pipe_ctx->plane_res.dpp, + pipe_ctx->plane_res.hubp); pipe_ctx->stream = NULL; memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res)); @@ -559,204 +522,6 @@ void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) pipe_ctx->pipe_idx); } -static void dcn20_init_hw(struct dc *dc) -{ - int i, j; - struct abm *abm = dc->res_pool->abm; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct dce_hwseq *hws = dc->hwseq; - struct dc_bios *dcb = dc->ctx->dc_bios; - struct resource_pool *res_pool = dc->res_pool; - struct dc_state *context = dc->current_state; - - if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) - dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); - - // Initialize the dccg - if (res_pool->dccg->funcs->dccg_init) - res_pool->dccg->funcs->dccg_init(res_pool->dccg); - - //Enable ability to power gate / don't force power on permanently - enable_power_gating_plane(dc->hwseq, true); - - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF); - REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF); - - dcn20_dccg_init(hws); - - REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2); - REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); - REG_WRITE(REFCLK_CNTL, 0); - } else { - if (!dcb->funcs->is_accelerated_mode(dcb)) { - bios_golden_init(dc); - if (dc->ctx->dc_bios->fw_info_valid) { - res_pool->ref_clocks.xtalin_clock_inKhz = - dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; - - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - if (res_pool->dccg && res_pool->hubbub) { - - (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg, - dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, - &res_pool->ref_clocks.dccg_ref_clock_inKhz); - - (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, - res_pool->ref_clocks.dccg_ref_clock_inKhz, - &res_pool->ref_clocks.dchub_ref_clock_inKhz); - } else { - // Not all ASICs have DCCG sw component - res_pool->ref_clocks.dccg_ref_clock_inKhz = - res_pool->ref_clocks.xtalin_clock_inKhz; - res_pool->ref_clocks.dchub_ref_clock_inKhz = - res_pool->ref_clocks.xtalin_clock_inKhz; - } - } - } else - ASSERT_CRITICAL(false); - disable_vga(dc->hwseq); - } - - for (i = 0; i < dc->link_count; i++) { - /* Power up AND update implementation according to the - * required signal (which may be different from the - * default signal on connector). - */ - struct dc_link *link = dc->links[i]; - - link->link_enc->funcs->hw_init(link->link_enc); - } - } - -#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT - /* Power gate DSCs */ - for (i = 0; i < res_pool->res_cap->num_dsc; i++) - dcn20_dsc_pg_control(hws, res_pool->dscs[i]->inst, false); -#endif - - /* Blank pixel data with OPP DPG */ - for (i = 0; i < dc->res_pool->timing_generator_count; i++) { - struct timing_generator *tg = dc->res_pool->timing_generators[i]; - - if (tg->funcs->is_tg_enabled(tg)) { - dcn20_init_blank(dc, tg); - } - } - - for (i = 0; i < res_pool->timing_generator_count; i++) { - struct timing_generator *tg = dc->res_pool->timing_generators[i]; - - if (tg->funcs->is_tg_enabled(tg)) - tg->funcs->lock(tg); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct dpp *dpp = res_pool->dpps[i]; - - dpp->funcs->dpp_reset(dpp); - } - - /* Reset all MPCC muxes */ - res_pool->mpc->funcs->mpc_init(res_pool->mpc); - - /* initialize OPP mpc_tree parameter */ - for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) { - res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst; - res_pool->opps[i]->mpc_tree_params.opp_list = NULL; - for (j = 0; j < MAX_PIPES; j++) - res_pool->opps[i]->mpcc_disconnect_pending[j] = false; - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct timing_generator *tg = dc->res_pool->timing_generators[i]; - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct hubp *hubp = dc->res_pool->hubps[i]; - struct dpp *dpp = dc->res_pool->dpps[i]; - - pipe_ctx->stream_res.tg = tg; - pipe_ctx->pipe_idx = i; - - pipe_ctx->plane_res.hubp = hubp; - pipe_ctx->plane_res.dpp = dpp; - pipe_ctx->plane_res.mpcc_inst = dpp->inst; - hubp->mpcc_id = dpp->inst; - hubp->opp_id = OPP_ID_INVALID; - hubp->power_gated = false; - pipe_ctx->stream_res.opp = NULL; - - hubp->funcs->hubp_init(hubp); - - //dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; - //dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; - dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; - pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; - /*to do*/ - hwss1_plane_atomic_disconnect(dc, pipe_ctx); - } - - /* initialize DWB pointer to MCIF_WB */ - for (i = 0; i < res_pool->res_cap->num_dwb; i++) - res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i]; - - for (i = 0; i < dc->res_pool->timing_generator_count; i++) { - struct timing_generator *tg = dc->res_pool->timing_generators[i]; - - if (tg->funcs->is_tg_enabled(tg)) - tg->funcs->unlock(tg); - } - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - dc->hwss.disable_plane(dc, pipe_ctx); - - pipe_ctx->stream_res.tg = NULL; - pipe_ctx->plane_res.hubp = NULL; - } - - for (i = 0; i < dc->res_pool->timing_generator_count; i++) { - struct timing_generator *tg = dc->res_pool->timing_generators[i]; - - tg->funcs->tg_init(tg); - } - - /* end of FPGA. Below if real ASIC */ - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - return; - - - for (i = 0; i < res_pool->audio_count; i++) { - struct audio *audio = res_pool->audios[i]; - - audio->funcs->hw_init(audio); - } - - if (abm != NULL) { - abm->funcs->init_backlight(abm); - abm->funcs->abm_init(abm); - } - - if (dmcu != NULL) - dmcu->funcs->dmcu_init(dmcu); - - if (abm != NULL && dmcu != NULL) - abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu); - - /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); - - if (!dc->debug.disable_clock_gate) { - /* enable all DCN clock gating */ - REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); - - REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); - - REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); - } - -} - enum dc_status dcn20_enable_stream_timing( struct pipe_ctx *pipe_ctx, struct dc_state *context, @@ -1409,7 +1174,7 @@ static void dcn20_apply_ctx_for_surface( if (old_pipe_ctx->stream_res.tg == tg && old_pipe_ctx->plane_res.hubp && old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID) - dcn20_disable_plane(dc, old_pipe_ctx); + dc->hwss.disable_plane(dc, old_pipe_ctx); } if ((!pipe_ctx->plane_state || @@ -2169,14 +1934,126 @@ static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx) hubp->inst, mode); } +static void dcn20_fpga_init_hw(struct dc *dc) +{ + int i, j; + struct dce_hwseq *hws = dc->hwseq; + struct resource_pool *res_pool = dc->res_pool; + struct dc_state *context = dc->current_state; + + if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) + dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); + + // Initialize the dccg + if (res_pool->dccg->funcs->dccg_init) + res_pool->dccg->funcs->dccg_init(res_pool->dccg); + + //Enable ability to power gate / don't force power on permanently + dc->hwss.enable_power_gating_plane(hws, true); + + // Specific to FPGA dccg and registers + REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF); + REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF); + + dcn20_dccg_init(hws); + + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2); + REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); + REG_WRITE(REFCLK_CNTL, 0); + // + + + /* Blank pixel data with OPP DPG */ + for (i = 0; i < dc->res_pool->timing_generator_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + if (tg->funcs->is_tg_enabled(tg)) + dcn20_init_blank(dc, tg); + } + + for (i = 0; i < res_pool->timing_generator_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + if (tg->funcs->is_tg_enabled(tg)) + tg->funcs->lock(tg); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct dpp *dpp = res_pool->dpps[i]; + + dpp->funcs->dpp_reset(dpp); + } + + /* Reset all MPCC muxes */ + res_pool->mpc->funcs->mpc_init(res_pool->mpc); + + /* initialize OPP mpc_tree parameter */ + for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) { + res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst; + res_pool->opps[i]->mpc_tree_params.opp_list = NULL; + for (j = 0; j < MAX_PIPES; j++) + res_pool->opps[i]->mpcc_disconnect_pending[j] = false; + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct hubp *hubp = dc->res_pool->hubps[i]; + struct dpp *dpp = dc->res_pool->dpps[i]; + + pipe_ctx->stream_res.tg = tg; + pipe_ctx->pipe_idx = i; + + pipe_ctx->plane_res.hubp = hubp; + pipe_ctx->plane_res.dpp = dpp; + pipe_ctx->plane_res.mpcc_inst = dpp->inst; + hubp->mpcc_id = dpp->inst; + hubp->opp_id = OPP_ID_INVALID; + hubp->power_gated = false; + pipe_ctx->stream_res.opp = NULL; + + hubp->funcs->hubp_init(hubp); + + //dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst; + //dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; + dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true; + pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; + /*to do*/ + hwss1_plane_atomic_disconnect(dc, pipe_ctx); + } + + /* initialize DWB pointer to MCIF_WB */ + for (i = 0; i < res_pool->res_cap->num_dwb; i++) + res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i]; + + for (i = 0; i < dc->res_pool->timing_generator_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + if (tg->funcs->is_tg_enabled(tg)) + tg->funcs->unlock(tg); + } + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + dc->hwss.disable_plane(dc, pipe_ctx); + + pipe_ctx->stream_res.tg = NULL; + pipe_ctx->plane_res.hubp = NULL; + } + + for (i = 0; i < dc->res_pool->timing_generator_count; i++) { + struct timing_generator *tg = dc->res_pool->timing_generators[i]; + + tg->funcs->tg_init(tg); + } +} + void dcn20_hw_sequencer_construct(struct dc *dc) { dcn10_hw_sequencer_construct(dc); - dc->hwss.init_hw = dcn20_init_hw; - dc->hwss.init_pipes = NULL; dc->hwss.unblank_stream = dcn20_unblank_stream; dc->hwss.update_plane_addr = dcn20_update_plane_addr; - dc->hwss.disable_plane = dcn20_disable_plane, dc->hwss.enable_stream_timing = dcn20_enable_stream_timing; dc->hwss.program_triplebuffer = dcn20_program_tripleBuffer; dc->hwss.set_input_transfer_func = dcn20_set_input_transfer_func; @@ -2204,5 +2081,19 @@ void dcn20_hw_sequencer_construct(struct dc *dc) dc->hwss.reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap; dc->hwss.update_mpcc = dcn20_update_mpcc; dc->hwss.set_flip_control_gsl = dcn20_set_flip_control_gsl; - dc->hwss.did_underflow_occur = dcn10_did_underflow_occur; + dc->hwss.init_blank = dcn20_init_blank; + dc->hwss.disable_plane = dcn20_disable_plane; + dc->hwss.plane_atomic_disable = dcn20_plane_atomic_disable; + dc->hwss.enable_power_gating_plane = dcn20_enable_power_gating_plane; + dc->hwss.dpp_pg_control = dcn20_dpp_pg_control; + dc->hwss.hubp_pg_control = dcn20_hubp_pg_control; + dc->hwss.dsc_pg_control = dcn20_dsc_pg_control; + dc->hwss.disable_vga = dcn20_disable_vga; + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + dc->hwss.init_hw = dcn20_fpga_init_hw; + dc->hwss.init_pipes = NULL; + } + + } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 9502478c4a1b..c1f29b1654d9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -141,6 +141,10 @@ struct hubbub_funcs { struct dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); + + bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub); + void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow); + }; struct hubbub { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 28645e10f854..80de2febd7cb 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -78,6 +78,8 @@ struct stream_resource; struct dc_phy_addr_space_config; struct dc_virtual_addr_space_config; #endif +struct hubp; +struct dpp; struct hw_sequencer_funcs { @@ -280,6 +282,36 @@ struct hw_sequencer_funcs { void (*setup_vupdate_interrupt)(struct pipe_ctx *pipe_ctx); bool (*did_underflow_occur)(struct dc *dc, struct pipe_ctx *pipe_ctx); + void (*init_blank)(struct dc *dc, struct timing_generator *tg); + void (*disable_vga)(struct dce_hwseq *hws); + void (*bios_golden_init)(struct dc *dc); + void (*plane_atomic_power_down)(struct dc *dc, + struct dpp *dpp, + struct hubp *hubp); + + void (*plane_atomic_disable)( + struct dc *dc, struct pipe_ctx *pipe_ctx); + + void (*enable_power_gating_plane)( + struct dce_hwseq *hws, + bool enable); + + void (*dpp_pg_control)( + struct dce_hwseq *hws, + unsigned int dpp_inst, + bool power_on); + + void (*hubp_pg_control)( + struct dce_hwseq *hws, + unsigned int hubp_inst, + bool power_on); + + void (*dsc_pg_control)( + struct dce_hwseq *hws, + unsigned int dsc_inst, + bool power_on); + + #if defined(CONFIG_DRM_AMD_DC_DCN2_0) void (*update_odm)(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); void (*program_all_writeback_pipes_in_tree)( -- cgit v1.2.3 From 574304041bb9508a4e73533e8d1702b0e713d321 Mon Sep 17 00:00:00 2001 From: Su Sung Chung Date: Thu, 25 Jul 2019 14:43:55 -0400 Subject: drm/amd/display: fix audio endpoint not getting disabled issue [Why] Disable_audio_stream gets enum option as a paramenter which will decide if we free acquired resources or not. However checks for the option is guarded by the other condition which check if audio stream is getting diabled more than once. With both conditions combined, if we attempt to disable audio stream twice in a row, first with keep and second with free as an option, we will never free any resources, which will make system think there is audio endpoint connected even after we plug out the device [How] Get rid of option as parameter to disable_audio_stream and move the part of the code that free acquired resources to outside where to keep or to free resources is actually determined Signed-off-by: Su Sung Chung Reviewed-by: Jun Lei Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +++- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +-- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 4 ++- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 40 +++++++++++++--------- .../amd/display/dc/dce110/dce110_hw_sequencer.h | 4 +-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 20 ++++++++--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 24 ++++++++++--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 7 +--- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 ++- 10 files changed, 74 insertions(+), 42 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f09811c0bf02..84f12e13c900 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1918,7 +1918,11 @@ static void commit_planes_do_stream_update(struct dc *dc, dc->hwss.pipe_control_lock(dc, pipe_ctx, true); if (*stream_update->dpms_off) { - core_link_disable_stream(pipe_ctx, KEEP_ACQUIRED_RESOURCE); + core_link_disable_stream(pipe_ctx); + /* for dpms, keep acquired resources*/ + if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) + pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); + dc->hwss.optimize_bandwidth(dc, dc->current_state); } else { if (!dc->optimize_seamless_boot) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 70dbdb381446..ca20b150afcc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2804,7 +2804,7 @@ void core_link_enable_stream( #endif } -void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) +void core_link_disable_stream(struct pipe_ctx *pipe_ctx) { struct dc *core_dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; @@ -2839,7 +2839,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) write_i2c_redriver_setting(pipe_ctx, false); } } - core_dc->hwss.disable_stream(pipe_ctx, option); + core_dc->hwss.disable_stream(pipe_ctx); disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index fe9a4e4b9d1f..79438c4f1e20 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -289,7 +289,9 @@ void dp_retrain_link_dp_test(struct dc_link *link, dp_receiver_power_ctrl(link, false); - link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE); + link->dc->hwss.disable_stream(&pipes[i]); + if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only) + (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio); link->link_enc->funcs->disable_output( link->link_enc, diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index e475a6488234..d2d887972956 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -981,7 +981,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) } } -void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) +void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) { struct dc *dc; struct pp_smu_funcs *pp_smu = NULL; @@ -1004,24 +1004,13 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) if (dc->res_pool->pp_smu) pp_smu = dc->res_pool->pp_smu; - if (option != KEEP_ACQUIRED_RESOURCE || - !dc->debug.az_endpoint_mute_only) - /*only disalbe az_endpoint if power down or free*/ - pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); - if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( pipe_ctx->stream_res.stream_enc); else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); - /*don't free audio if it is from retrain or internal disable stream*/ - if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) { - /*we have to dynamic arbitrate the audio endpoints*/ - /*we free the resource, need reset is_audio_acquired*/ - update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false); - pipe_ctx->stream_res.audio = NULL; - } + if (clk_mgr->funcs->enable_pme_wa) /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ clk_mgr->funcs->enable_pme_wa(clk_mgr); @@ -1034,7 +1023,7 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) } } -void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) +void dce110_disable_stream(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; @@ -1051,7 +1040,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.stream_enc); - dc->hwss.disable_audio_stream(pipe_ctx, option); + dc->hwss.disable_audio_stream(pipe_ctx); link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, @@ -1914,8 +1903,25 @@ static void dce110_reset_hw_ctx_wrap( /* Disable if new stream is null. O/w, if stream is * disabled already, no need to disable again. */ - if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) - core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); + if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) { + core_link_disable_stream(pipe_ctx_old); + + /* free acquired resources*/ + if (pipe_ctx_old->stream_res.audio) { + /*disable az_endpoint*/ + pipe_ctx_old->stream_res.audio->funcs-> + az_disable(pipe_ctx_old->stream_res.audio); + + /*free audio*/ + if (dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, + pipe_ctx_old->stream_res.audio, false); + pipe_ctx_old->stream_res.audio = NULL; + } + } + } pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h index 668feb0d169d..2f9b7dbdf415 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h @@ -42,7 +42,7 @@ enum dc_status dce110_apply_ctx_to_hw( void dce110_enable_stream(struct pipe_ctx *pipe_ctx); -void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option); +void dce110_disable_stream(struct pipe_ctx *pipe_ctx); void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); @@ -50,7 +50,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_blank_stream(struct pipe_ctx *pipe_ctx); void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx); -void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option); +void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx); void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 283915b2c2b1..f61f59ac1e00 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -828,11 +828,23 @@ static void dcn10_reset_back_end_for_pipe( if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { /* DPMS may already disable */ if (!pipe_ctx->stream->dpms_off) - core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); - else if (pipe_ctx->stream_res.audio) { - dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + core_link_disable_stream(pipe_ctx); + else if (pipe_ctx->stream_res.audio) + dc->hwss.disable_audio_stream(pipe_ctx); + + if (pipe_ctx->stream_res.audio) { + /*disable az_endpoint*/ + pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); + + /*free audio*/ + if (dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, + pipe_ctx->stream_res.audio, false); + pipe_ctx->stream_res.audio = NULL; + } } - } /* by upper caller loop, parent pipe: pipe0, will be reset last. diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index e49325940fd3..e9d8a7610160 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1461,9 +1461,9 @@ void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx) hubp->funcs->dmdata_set_attributes(hubp, &attr); } -void dcn20_disable_stream(struct pipe_ctx *pipe_ctx, int option) +void dcn20_disable_stream(struct pipe_ctx *pipe_ctx) { - dce110_disable_stream(pipe_ctx, option); + dce110_disable_stream(pipe_ctx); } static void dcn20_init_vm_ctx( @@ -1617,9 +1617,23 @@ static void dcn20_reset_back_end_for_pipe( if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { /* DPMS may already disable */ if (!pipe_ctx->stream->dpms_off) - core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); - else if (pipe_ctx->stream_res.audio) { - dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + core_link_disable_stream(pipe_ctx); + else if (pipe_ctx->stream_res.audio) + dc->hwss.disable_audio_stream(pipe_ctx); + + /* free acquired resources */ + if (pipe_ctx->stream_res.audio) { + /*disable az_endpoint*/ + pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); + + /*free audio*/ + if (dc->caps.dynamic_audio == true) { + /*we have to dynamic arbitrate the audio endpoints*/ + /*we free the resource, need reset is_audio_acquired*/ + update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, + pipe_ctx->stream_res.audio, false); + pipe_ctx->stream_res.audio = NULL; + } } } #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 689c2765b071..92ab3dd91814 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -75,7 +75,7 @@ bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx); void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx); -void dcn20_disable_stream(struct pipe_ctx *pipe_ctx, int option); +void dcn20_disable_stream(struct pipe_ctx *pipe_ctx); void dcn20_program_tripleBuffer( const struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index bfe0d06d1c20..df28fbc4c63c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -63,11 +63,6 @@ struct link_init_data { TODO: remove it when DC is complete. */ }; -enum { - FREE_ACQUIRED_RESOURCE = 0, - KEEP_ACQUIRED_RESOURCE = 1, -}; - struct dc_link *link_create(const struct link_init_data *init_params); void link_destroy(struct dc_link **link); @@ -82,7 +77,7 @@ void core_link_enable_stream( struct dc_state *state, struct pipe_ctx *pipe_ctx); -void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option); +void core_link_disable_stream(struct pipe_ctx *pipe_ctx); void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); /********** DAL Core*********************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 80de2febd7cb..68b1185f0636 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -196,8 +196,7 @@ struct hw_sequencer_funcs { void (*enable_stream)(struct pipe_ctx *pipe_ctx); - void (*disable_stream)(struct pipe_ctx *pipe_ctx, - int option); + void (*disable_stream)(struct pipe_ctx *pipe_ctx); void (*unblank_stream)(struct pipe_ctx *pipe_ctx, struct dc_link_settings *link_settings); @@ -206,7 +205,7 @@ struct hw_sequencer_funcs { void (*enable_audio_stream)(struct pipe_ctx *pipe_ctx); - void (*disable_audio_stream)(struct pipe_ctx *pipe_ctx, int option); + void (*disable_audio_stream)(struct pipe_ctx *pipe_ctx); void (*pipe_control_lock)( struct dc *dc, -- cgit v1.2.3 From 470e2ca569bf780f832e3020ceb5afdef16a9084 Mon Sep 17 00:00:00 2001 From: Bayan Zabihiyan Date: Thu, 8 Aug 2019 11:08:52 -0400 Subject: drm/amd/display: Expose OTG_V_TOTAL_MID for HW Diags [Why] Existing HW Features, HW Diags test requested that the registers be exposed. [How] Add V_TOTAL_MID to existing DC structures. Make sure values are passed down throughout DC Add Register definition. Program the additional registers Add additional Logic for V_TOTAL_CONTROL. Signed-off-by: Bayan Zabihiyan Reviewed-by: Charlene Liu Acked-by: Anthony Koo Acked-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 2 ++ drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 3 ++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 ++++- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 12 ++++++++++++ drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 8 ++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | 2 ++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 3 ++- 9 files changed, 37 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 82c07d82e937..87ca5a290d12 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -291,7 +291,9 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, dc->hwss.set_drr(&pipe, 1, adjust->v_total_min, - adjust->v_total_max); + adjust->v_total_max, + adjust->v_total_mid, + adjust->v_total_mid_frame_num); ret = true; } diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index f35826d5d1e5..0b8700a8a94a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -757,6 +757,8 @@ struct crtc_trigger_info { struct dc_crtc_timing_adjust { uint32_t v_total_min; uint32_t v_total_max; + uint32_t v_total_mid; + uint32_t v_total_mid_frame_num; }; #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index d2d887972956..01a924bf477a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1719,7 +1719,8 @@ void dce110_set_safe_displaymarks( ******************************************************************************/ static void set_drr(struct pipe_ctx **pipe_ctx, - int num_pipes, int vmin, int vmax) + int num_pipes, unsigned int vmin, unsigned int vmax, + unsigned int vmid, unsigned int vmid_frame_number) { int i = 0; struct drr_params params = {0}; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 4970543b7f05..bd2a83e05625 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2747,7 +2747,8 @@ static void dcn10_optimize_bandwidth( } static void dcn10_set_drr(struct pipe_ctx **pipe_ctx, - int num_pipes, int vmin, int vmax) + int num_pipes, unsigned int vmin, unsigned int vmax, + unsigned int vmid, unsigned int vmid_frame_number) { int i = 0; struct drr_params params = {0}; @@ -2756,6 +2757,8 @@ static void dcn10_set_drr(struct pipe_ctx **pipe_ctx, params.vertical_total_max = vmax; params.vertical_total_min = vmin; + params.vertical_total_mid = vmid; + params.vertical_total_mid_frame_num = vmid_frame_number; /* TODO: If multiple pipes are to be supported, you need * some GSL stuff. Static screen triggers may be programmed differently diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index e98e6bab4808..e74a07d03fde 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -850,6 +850,18 @@ void optc1_set_drr( params->vertical_total_max > 0 && params->vertical_total_min > 0) { + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + REG_SET(OTG_V_TOTAL_MAX, 0, OTG_V_TOTAL_MAX, params->vertical_total_max - 1); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 82d91ab54ba5..83575599672e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -54,6 +54,7 @@ SRI(OTG_3D_STRUCTURE_CONTROL, OTG, inst),\ SRI(OTG_STEREO_STATUS, OTG, inst),\ SRI(OTG_V_TOTAL_MAX, OTG, inst),\ + SRI(OTG_V_TOTAL_MID, OTG, inst),\ SRI(OTG_V_TOTAL_MIN, OTG, inst),\ SRI(OTG_V_TOTAL_CONTROL, OTG, inst),\ SRI(OTG_TRIGA_CNTL, OTG, inst),\ @@ -125,6 +126,7 @@ struct dcn_optc_registers { uint32_t OTG_3D_STRUCTURE_CONTROL; uint32_t OTG_STEREO_STATUS; uint32_t OTG_V_TOTAL_MAX; + uint32_t OTG_V_TOTAL_MID; uint32_t OTG_V_TOTAL_MIN; uint32_t OTG_V_TOTAL_CONTROL; uint32_t OTG_TRIGA_CNTL; @@ -214,12 +216,15 @@ struct dcn_optc_registers { SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\ SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_MID, OTG_V_TOTAL_MID, mask_sh),\ SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK_EN, mask_sh),\ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\ + SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_FRAME_NUM, mask_sh),\ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\ @@ -348,9 +353,12 @@ struct dcn_optc_registers { type OTG_3D_STRUCTURE_V_UPDATE_MODE;\ type OTG_3D_STRUCTURE_STEREO_SEL_OVR;\ type OTG_V_TOTAL_MAX;\ + type OTG_V_TOTAL_MID;\ type OTG_V_TOTAL_MIN;\ type OTG_V_TOTAL_MIN_SEL;\ type OTG_V_TOTAL_MAX_SEL;\ + type OTG_VTOTAL_MID_REPLACING_MAX_EN;\ + type OTG_VTOTAL_MID_FRAME_NUM;\ type OTG_FORCE_LOCK_ON_EVENT;\ type OTG_SET_V_TOTAL_MIN_MASK_EN;\ type OTG_SET_V_TOTAL_MIN_MASK;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 0fb0a356323b..161805bb89d3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -597,6 +597,8 @@ enum dc_status dcn20_enable_stream_timing( params.vertical_total_min = stream->adjust.v_total_min; params.vertical_total_max = stream->adjust.v_total_max; + params.vertical_total_mid = stream->adjust.v_total_mid; + params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num; if (pipe_ctx->stream_res.tg->funcs->set_drr) pipe_ctx->stream_res.tg->funcs->set_drr( pipe_ctx->stream_res.tg, ¶ms); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index e0713d6d6c8d..6196cc32356e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -59,6 +59,8 @@ struct gsl_params { struct drr_params { uint32_t vertical_total_min; uint32_t vertical_total_max; + uint32_t vertical_total_mid; + uint32_t vertical_total_mid_frame_num; bool immediate_flip; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 68b1185f0636..732a93df1844 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -237,7 +237,8 @@ struct hw_sequencer_funcs { #endif void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, - int vmin, int vmax); + unsigned int vmin, unsigned int vmax, + unsigned int vmid, unsigned int vmid_frame_number); void (*get_position)(struct pipe_ctx **pipe_ctx, int num_pipes, struct crtc_position *position); -- cgit v1.2.3 From aa91916770d07cafafd24905b20e5350eb2dee30 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 26 Jul 2019 17:16:47 -0400 Subject: drm/amd/display: add dcn21 core DC changes Add missing parameters, to make dcn21 compile without errors Acked-by: Harry Wentland Signed-off-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ drivers/gpu/drm/amd/display/dc/inc/core_types.h | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 1 + 4 files changed, 11 insertions(+) (limited to 'drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 42b6a6e41c0b..a82352a87808 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -385,6 +385,9 @@ struct dc_debug_options { struct dc_bw_validation_profile bw_val_profile; #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT bool disable_fec; +#endif +#ifdef CONFIG_DRM_AMD_DC_DCN2_1 + bool disable_48mhz_pwrdwn; #endif /* This forces a hard min on the DCFCLK requested to SMU/PP * watermarks are not affected. diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 8726bd7dd910..f189307750ab 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -87,6 +87,9 @@ void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); struct resource_pool; struct dc_state; struct resource_context; +#if defined(CONFIG_DRM_AMD_DC_DCN2_1) +struct clk_bw_params; +#endif struct resource_funcs { void (*destroy)(struct resource_pool **pool); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 7193acfcd779..e8668388581b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -40,6 +40,10 @@ struct cstate_pstate_watermarks_st { struct dcn_watermarks { uint32_t pte_meta_urgent_ns; uint32_t urgent_ns; +#if defined(CONFIG_DRM_AMD_DC_DCN2_1) + uint32_t frac_urg_bw_nom; + uint32_t frac_urg_bw_flip; +#endif struct cstate_pstate_watermarks_st cstate_pstate; }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 732a93df1844..3a938cd414ea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -48,6 +48,7 @@ struct dce_hwseq_wa { bool DEGVIDCN10_253; bool false_optc_underflow; bool DEGVIDCN10_254; + bool DEGVIDCN21; }; struct hwseq_wa_state { -- cgit v1.2.3