summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/modules
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules')
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_power.h11
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power.c28
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_abm.c150
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c39
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.h10
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_psr.c7
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_replay.c16
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));