diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
8 files changed, 188 insertions, 75 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h index f9814cf7bbdb..02bee3b1956d 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_power.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_power.h @@ -328,6 +328,17 @@ bool mod_power_is_abm_active(struct mod_power *mod_power, const struct dc_link *link, unsigned int inst); +bool mod_power_is_abm_supported(struct mod_power *mod_power, + unsigned int inst); + +bool mod_power_abm_set_event(struct mod_power *mod_power, + unsigned int full_screen, unsigned int trans_info, + unsigned int hdr_mode, unsigned int scaling_enable, + unsigned int scaling_strength_map, unsigned int inst); + +bool mod_power_abm_set_strength(struct mod_power *mod_power, + unsigned int strength, + unsigned int inst); bool mod_power_set_psr_event(struct mod_power *mod_power, struct dc_stream_state *stream, bool set_event, diff --git a/drivers/gpu/drm/amd/display/modules/power/Makefile b/drivers/gpu/drm/amd/display/modules/power/Makefile index 3000f392bdbc..0746f671eb4d 100644 --- a/drivers/gpu/drm/amd/display/modules/power/Makefile +++ b/drivers/gpu/drm/amd/display/modules/power/Makefile @@ -23,7 +23,7 @@ # Makefile for the 'power' sub-module of DAL. # -MOD_POWER = power_helpers.o power.o power_abm.o power_psr.o power_replay.o +MOD_POWER = power.o power_abm.o power_psr.o power_replay.o AMD_DAL_MOD_POWER = $(addprefix $(AMDDALPATH)/modules/power/,$(MOD_POWER)) #$(info ************ DAL POWER MODULE MAKEFILE ************) diff --git a/drivers/gpu/drm/amd/display/modules/power/power.c b/drivers/gpu/drm/amd/display/modules/power/power.c index 5659a38b3366..ee15c14a899e 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power.c +++ b/drivers/gpu/drm/amd/display/modules/power/power.c @@ -270,13 +270,11 @@ struct mod_power *mod_power_create(struct dc *dc, fail_bad_brightness_range: fail_alloc_backlight_array: for (inst = 0; inst < edp_num; inst++) - if (core_power->bl_prop[inst].backlight_lut) - kfree(core_power->bl_prop[inst].backlight_lut); + kfree(core_power->bl_prop[inst].backlight_lut); fail_construct: - for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) { - if (core_power->map[i].psr_context) - kfree(core_power->map[i].psr_context); - } + for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) + kfree(core_power->map[i].psr_context); + kfree(core_power->map); fail_alloc_map: @@ -295,8 +293,7 @@ void mod_power_destroy(struct mod_power *mod_power) MOD_POWER_TO_CORE(mod_power); for (i = 0; i < MOD_POWER_MAX_CONCURRENT_STREAMS; i++) - if (core_power->map[i].psr_context) - kfree(core_power->map[i].psr_context); + kfree(core_power->map[i].psr_context); for (i = 0; i < core_power->num_entities; i++) if (core_power->map[i].stream) @@ -305,8 +302,7 @@ void mod_power_destroy(struct mod_power *mod_power) kfree(core_power->map); for (i = 0; i < MAX_NUM_EDP; i++) - if (core_power->bl_prop[i].backlight_lut) - kfree(core_power->bl_prop[i].backlight_lut); + kfree(core_power->bl_prop[i].backlight_lut); kfree(core_power); } @@ -483,12 +479,7 @@ bool mod_power_notify_mode_change(struct mod_power *mod_power, link = dc_stream_get_link(stream); if (link != NULL && dc_get_edp_link_panel_inst(dc, link, &panel_inst)) { - if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { - aux_inst = (uint8_t)link->aux_hw_inst; - } else { - ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF); - aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel; - } + aux_inst = link->dc->link_srv->get_ddc_aux_inst(link); mod_power_update_backlight_on_mode_change(core_power, link, panel_inst, aux_inst, is_hdr); @@ -501,3 +492,8 @@ bool mod_power_notify_mode_change(struct mod_power *mod_power, return true; } + +bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_state *stream) +{ + return context && context->stream_count == 1 && dc_is_embedded_signal(stream->signal); +} diff --git a/drivers/gpu/drm/amd/display/modules/power/power_abm.c b/drivers/gpu/drm/amd/display/modules/power/power_abm.c index a1a0563598b5..b26ceaba940d 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_abm.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_abm.c @@ -716,8 +716,9 @@ void mod_power_update_backlight_on_mode_change( { struct set_backlight_level_params backlight_level_params = { 0 }; - if (link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || - link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) + if ((link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || + link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) && + link->backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX) dc_link_set_backlight_level_nits(link, core_power->bl_state[panel_inst].isHDR, core_power->bl_state[panel_inst].backlight_millinit, 0); @@ -746,6 +747,11 @@ static bool set_backlight_millinits_aux(struct core_power *core_power, link = dc_stream_get_link(stream); + // only use internal backlight control if dmub capabilities are not present + if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX && + link->dc->caps.dmub_caps.aux_backlight_support) + return true; + return dc_link_set_backlight_level_nits(link, core_power->bl_state[inst].isHDR, backlight_millinits, transition_time_millisec); } @@ -849,12 +855,7 @@ bool mod_power_set_backlight_nits(struct mod_power *mod_power, core_power = MOD_POWER_TO_CORE(mod_power); link = dc_stream_get_link(stream); - if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { - aux_inst = (uint8_t)link->aux_hw_inst; - } else { - ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF); - aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel; - } + aux_inst = link->dc->link_srv->get_ddc_aux_inst(link); if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst)) return false; @@ -941,12 +942,7 @@ bool mod_power_set_backlight_percent(struct mod_power *mod_power, core_power = MOD_POWER_TO_CORE(mod_power); link = dc_stream_get_link(stream); - if (link->ctx->dc->config.dp_connector_no_native_i2c && link->no_ddc_pin) { - aux_inst = (uint8_t)link->aux_hw_inst; - } else { - ASSERT(link->ddc->ddc_pin->hw_info.ddc_channel <= 0xFF); - aux_inst = (uint8_t)link->ddc->ddc_pin->hw_info.ddc_channel; - } + aux_inst = link->dc->link_srv->get_ddc_aux_inst(link); if (!dc_get_edp_link_panel_inst(core_power->dc, stream->link, &panel_inst)) return false; @@ -1463,6 +1459,76 @@ bool mod_power_is_abm_active(struct mod_power *mod_power, return is_active; } +bool mod_power_is_abm_supported(struct mod_power *mod_power, + unsigned int inst) +{ + struct core_power *core_power = NULL; + struct dc *dc = NULL; + + if (mod_power == NULL) + return false; + + core_power = MOD_POWER_TO_CORE(mod_power); + dc = core_power->dc; + + // It's only implemented on dmcub. + if (dc->ctx->dmub_srv) { + if (!dmub_is_abm_supported(dc->res_pool, inst)) + return false; + } else + return false; + + return true; +} + +bool mod_power_abm_set_event(struct mod_power *mod_power, + unsigned int full_screen, unsigned int trans_info, + unsigned int hdr_mode, unsigned int scaling_enable, + unsigned int scaling_strength_map, unsigned int inst) +{ + struct core_power *core_power = NULL; + struct dc *dc = NULL; + + if (mod_power == NULL) + return false; + + core_power = MOD_POWER_TO_CORE(mod_power); + dc = core_power->dc; + + // It's only implemented on dmcub. + if (dc->ctx->dmub_srv) { + if (!dmub_set_abm_event(dc->res_pool, full_screen, trans_info, + hdr_mode, scaling_enable, scaling_strength_map, inst)) + return false; + } else + return false; + + return true; +} + +bool mod_power_abm_set_strength(struct mod_power *mod_power, + unsigned int strength, + unsigned int inst) +{ + struct core_power *core_power = NULL; + struct dc *dc = NULL; + + if (mod_power == NULL) + return false; + + core_power = MOD_POWER_TO_CORE(mod_power); + dc = core_power->dc; + + // It's only implemented on dmcub. + if (dc->ctx->dmub_srv) { + if (!dmub_set_abm_strength(dc->res_pool, strength, inst)) + return false; + } else + return false; + + return true; +} + static void fill_backlight_transform_table(struct dmcu_iram_parameters params, struct iram_table_v_2 *table) { @@ -2000,6 +2066,62 @@ bool dmub_init_abm_config(struct resource_pool *res_pool, return result; } +bool dmub_is_abm_supported(struct resource_pool *res_pool, unsigned int inst) +{ + + if (res_pool->abm == NULL && res_pool->multiple_abms[inst] == NULL) + return false; + + return true; +} + +bool dmub_set_abm_event(struct resource_pool *res_pool, + unsigned int full_screen, unsigned int trans_info, + unsigned int hdr_mode, unsigned int scaling_enable, unsigned int scaling_strength_map, + unsigned int inst) +{ + bool result = false; + + if (res_pool->abm == NULL && res_pool->multiple_abms[inst] == NULL) + return false; + + if (res_pool->multiple_abms[inst]) { + if (res_pool->multiple_abms[inst]->funcs->set_abm_event) + result = res_pool->multiple_abms[inst]->funcs->set_abm_event( + res_pool->multiple_abms[inst], full_screen, trans_info, + hdr_mode, scaling_enable, scaling_strength_map, inst); + } else { + if (res_pool->abm->funcs->set_abm_event) + result = res_pool->abm->funcs->set_abm_event( + res_pool->abm, full_screen, trans_info, + hdr_mode, scaling_enable, scaling_strength_map, inst); + } + + return result; +} + +bool dmub_set_abm_strength(struct resource_pool *res_pool, + unsigned int strength, + unsigned int inst) +{ + bool result = false; + + if (res_pool->abm == NULL && res_pool->multiple_abms[inst] == NULL) + return false; + + if (res_pool->multiple_abms[inst]) { + if (res_pool->multiple_abms[inst]->funcs->set_abm_level) + result = res_pool->multiple_abms[inst]->funcs->set_abm_level( + res_pool->multiple_abms[inst], strength); + } else { + if (res_pool->abm->funcs->set_abm_level) + result = res_pool->abm->funcs->set_abm_level( + res_pool->abm, strength); + } + + return result; +} + bool dmcu_load_iram(struct dmcu *dmcu, struct dmcu_iram_parameters params) { diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c deleted file mode 100644 index bf0c5901b4ee..000000000000 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2018 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 "power_helpers.h" -#include "dc/inc/hw/dmcu.h" -#include "dc/inc/hw/abm.h" -#include "dc.h" -#include "core_types.h" -#include "dmub_cmd.h" - -#define DIV_ROUNDUP(a, b) (((a)+((b)/2))/(b)) -#define bswap16_based_on_endian(big_endian, value) \ - ((big_endian) ? cpu_to_be16(value) : cpu_to_le16(value)) - -bool mod_power_only_edp(const struct dc_state *context, const struct dc_stream_state *stream) -{ - return context && context->stream_count == 1 && dc_is_embedded_signal(stream->signal); -} diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h index 600da3e33126..548c8ff6ddb4 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h @@ -146,6 +146,16 @@ bool dmub_init_abm_config(struct resource_pool *res_pool, struct dmcu_iram_parameters params, unsigned int inst); +bool dmub_is_abm_supported(struct resource_pool *res_pool, + unsigned int inst); +bool dmub_set_abm_event(struct resource_pool *res_pool, + unsigned int full_screen, unsigned int trans_info, + unsigned int hdr_mode, unsigned int scaling_enable, + unsigned int scaling_strength_map, unsigned int inst); +bool dmub_set_abm_strength(struct resource_pool *res_pool, + unsigned int strength, + unsigned int inst); + void init_replay_config(struct dc_link *link, struct replay_config *pr_config); void set_replay_coasting_vtotal(struct dc_link *link, enum replay_coasting_vtotal_type type, diff --git a/drivers/gpu/drm/amd/display/modules/power/power_psr.c b/drivers/gpu/drm/amd/display/modules/power/power_psr.c index 5ecb570c204e..0ad4c4924696 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_psr.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_psr.c @@ -58,6 +58,13 @@ bool mod_power_psr_notify_mode_change(struct mod_power *mod_power, // stream_index is passed as validated parameter active_psr_events = core_power->map[stream_index].psr_events; + /* DMSS holds the panel in a forced PSR freeze (e.g. during HDR/SDR toggle). + * Re-running edp_setup_psr would reprogram DPCD 0x170 and disturb the freeze, + * so skip the PSR re-setup until DMSS releases the override. + */ + if (active_psr_events & psr_event_os_override_hold) + return false; + /* Calculate PSR configurations */ mod_power_calc_psr_configs(&psr_config, link, stream); diff --git a/drivers/gpu/drm/amd/display/modules/power/power_replay.c b/drivers/gpu/drm/amd/display/modules/power/power_replay.c index 983be9759e74..1ad2ee01d560 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_replay.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_replay.c @@ -175,11 +175,10 @@ static bool mod_power_update_replay_active_status(unsigned int active_replay_eve if (link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]) *coasting_vtotal = link->replay_settings.coasting_vtotal_table[PR_COASTING_TYPE_TEST_HARNESS]; - if (link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]) { - ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF); - *frame_skip_number = - (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]; - } + + ASSERT(link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS] <= 0xFFFF); + *frame_skip_number = + (uint16_t)link->replay_settings.frame_skip_number_table[PR_COASTING_TYPE_TEST_HARNESS]; /* During the ultra sleep mode testing, disable the timing sync in short vblank mode */ if (active_replay_events & (replay_event_test_harness_enable_replay)) { @@ -806,6 +805,13 @@ void mod_power_replay_notify_mode_change(struct mod_power *mod_power, core_power = MOD_POWER_TO_CORE(mod_power); active_replay_events = core_power->map[stream_index].replay_events; + /* DMSS holds the panel in a forced freeze (e.g. during HDR/SDR toggle). + * Re-running dp_setup_replay would reprogram DPCD 0x37B and disturb the + * freeze, so skip the replay re-setup until DMSS releases the override. + */ + if (active_replay_events & replay_event_os_override_hold) + return; + link->replay_settings.replay_smu_opt_enable = (link->replay_settings.config.replay_smu_opt_supported && mod_power_only_edp(dc->current_state, stream)); |
