drm/amd/display: Defer LUT memory powerdown until LUT bypass latches
[WHY] Blnd, 3dlut, and shaper LUT select registers are double buffered, however their accompanying LUT memory shutdown registers are not. As a result, shutting down LUT memory immediately after setting a block to bypass causes corruption as bypass only happens at next Vupdate. [HOW] Re-enable mem low power for CM block Force optimization on next flip and disable LUT memory during optimization sequence if LUT select field is then set to bypass v2: squash in CONFIG_DRM_AMD_DC_DCN fix (Alex) Reviewed-by: Eric Yang <Eric.Yang2@amd.com> Acked-by: Anson Jacob <Anson.Jacob@amd.com> Signed-off-by: Michael Strauss <michael.strauss@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
87e9585b36
commit
028a998c62
@ -1793,6 +1793,25 @@ static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Perform updates here which need to be deferred until next vupdate
|
||||
*
|
||||
* i.e. blnd lut, 3dlut, and shaper lut bypass regs are double buffered
|
||||
* but forcing lut memory to shutdown state is immediate. This causes
|
||||
* single frame corruption as lut gets disabled mid-frame unless shutdown
|
||||
* is deferred until after entering bypass.
|
||||
*/
|
||||
static void process_deferred_updates(struct dc *dc)
|
||||
{
|
||||
#ifdef CONFIG_DRM_AMD_DC_DCN
|
||||
int i;
|
||||
|
||||
if (dc->debug.enable_mem_low_power.bits.cm)
|
||||
for (i = 0; i < dc->dcn_ip->max_num_dpp; i++)
|
||||
if (dc->res_pool->dpps[i]->funcs->dpp_deferred_update)
|
||||
dc->res_pool->dpps[i]->funcs->dpp_deferred_update(dc->res_pool->dpps[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dc_post_update_surfaces_to_stream(struct dc *dc)
|
||||
{
|
||||
int i;
|
||||
@ -1818,6 +1837,8 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
|
||||
dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
|
||||
}
|
||||
|
||||
process_deferred_updates(dc);
|
||||
|
||||
dc->hwss.optimize_bandwidth(dc, context);
|
||||
|
||||
dc->optimized_required = false;
|
||||
|
@ -488,6 +488,40 @@ void dpp3_cnv_set_bias_scale(
|
||||
REG_UPDATE(FCNV_FP_SCALE_B, FCNV_FP_SCALE_B, bias_and_scale->scale_blue);
|
||||
}
|
||||
|
||||
void dpp3_deferred_update(
|
||||
struct dpp *dpp_base)
|
||||
{
|
||||
int bypass_state;
|
||||
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
|
||||
|
||||
if (dpp_base->deferred_reg_writes.bits.disable_blnd_lut) {
|
||||
REG_GET(CM_BLNDGAM_CONTROL, CM_BLNDGAM_MODE_CURRENT, &bypass_state);
|
||||
if (bypass_state == 0) { // only program if bypass was latched
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, 3);
|
||||
} else
|
||||
ASSERT(0); // LUT select was updated again before vupdate
|
||||
dpp_base->deferred_reg_writes.bits.disable_blnd_lut = false;
|
||||
}
|
||||
|
||||
if (dpp_base->deferred_reg_writes.bits.disable_3dlut) {
|
||||
REG_GET(CM_3DLUT_MODE, CM_3DLUT_MODE_CURRENT, &bypass_state);
|
||||
if (bypass_state == 0) { // only program if bypass was latched
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, 3);
|
||||
} else
|
||||
ASSERT(0); // LUT select was updated again before vupdate
|
||||
dpp_base->deferred_reg_writes.bits.disable_3dlut = false;
|
||||
}
|
||||
|
||||
if (dpp_base->deferred_reg_writes.bits.disable_shaper) {
|
||||
REG_GET(CM_SHAPER_CONTROL, CM_SHAPER_MODE_CURRENT, &bypass_state);
|
||||
if (bypass_state == 0) { // only program if bypass was latched
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, 3);
|
||||
} else
|
||||
ASSERT(0); // LUT select was updated again before vupdate
|
||||
dpp_base->deferred_reg_writes.bits.disable_shaper = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void dpp3_power_on_blnd_lut(
|
||||
struct dpp *dpp_base,
|
||||
bool power_on)
|
||||
@ -495,9 +529,13 @@ static void dpp3_power_on_blnd_lut(
|
||||
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
|
||||
|
||||
if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, power_on ? 0 : 3);
|
||||
if (power_on)
|
||||
if (power_on) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL, BLNDGAM_MEM_PWR_FORCE, 0);
|
||||
REG_WAIT(CM_MEM_PWR_STATUS, BLNDGAM_MEM_PWR_STATE, 0, 1, 5);
|
||||
} else {
|
||||
dpp_base->ctx->dc->optimized_required = true;
|
||||
dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true;
|
||||
}
|
||||
} else {
|
||||
REG_SET(CM_MEM_PWR_CTRL, 0,
|
||||
BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0 : 1);
|
||||
@ -511,9 +549,13 @@ static void dpp3_power_on_hdr3dlut(
|
||||
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
|
||||
|
||||
if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, power_on ? 0 : 3);
|
||||
if (power_on)
|
||||
if (power_on) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL2, HDR3DLUT_MEM_PWR_FORCE, 0);
|
||||
REG_WAIT(CM_MEM_PWR_STATUS2, HDR3DLUT_MEM_PWR_STATE, 0, 1, 5);
|
||||
} else {
|
||||
dpp_base->ctx->dc->optimized_required = true;
|
||||
dpp_base->deferred_reg_writes.bits.disable_3dlut = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -524,9 +566,13 @@ static void dpp3_power_on_shaper(
|
||||
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
|
||||
|
||||
if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, power_on ? 0 : 3);
|
||||
if (power_on)
|
||||
if (power_on) {
|
||||
REG_UPDATE(CM_MEM_PWR_CTRL2, SHAPER_MEM_PWR_FORCE, 0);
|
||||
REG_WAIT(CM_MEM_PWR_STATUS2, SHAPER_MEM_PWR_STATE, 0, 1, 5);
|
||||
} else {
|
||||
dpp_base->ctx->dc->optimized_required = true;
|
||||
dpp_base->deferred_reg_writes.bits.disable_shaper = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1400,6 +1446,7 @@ static struct dpp_funcs dcn30_dpp_funcs = {
|
||||
.dpp_program_blnd_lut = dpp3_program_blnd_lut,
|
||||
.dpp_program_shaper_lut = dpp3_program_shaper,
|
||||
.dpp_program_3dlut = dpp3_program_3dlut,
|
||||
.dpp_deferred_update = dpp3_deferred_update,
|
||||
.dpp_program_bias_and_scale = NULL,
|
||||
.dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer,
|
||||
.set_cursor_attributes = dpp3_set_cursor_attributes,
|
||||
|
@ -1013,7 +1013,7 @@ static const struct dc_debug_options debug_defaults_drv = {
|
||||
.i2c = true,
|
||||
.dmcu = false, // This is previously known to cause hang on S3 cycles if enabled
|
||||
.dscl = true,
|
||||
.cm = false, // visible flicker on OLED eDPs
|
||||
.cm = true,
|
||||
.mpc = true,
|
||||
.optc = true,
|
||||
.vpg = true,
|
||||
|
@ -29,6 +29,15 @@
|
||||
|
||||
#include "transform.h"
|
||||
|
||||
union defer_reg_writes {
|
||||
struct {
|
||||
bool disable_blnd_lut:1;
|
||||
bool disable_3dlut:1;
|
||||
bool disable_shaper:1;
|
||||
} bits;
|
||||
uint32_t raw;
|
||||
};
|
||||
|
||||
struct dpp {
|
||||
const struct dpp_funcs *funcs;
|
||||
struct dc_context *ctx;
|
||||
@ -43,6 +52,7 @@ struct dpp {
|
||||
struct pwl_params regamma_params;
|
||||
struct pwl_params degamma_params;
|
||||
struct dpp_cursor_attributes cur_attr;
|
||||
union defer_reg_writes deferred_reg_writes;
|
||||
|
||||
struct pwl_params shaper_params;
|
||||
bool cm_bypass_mode;
|
||||
@ -245,6 +255,8 @@ struct dpp_funcs {
|
||||
bool dppclk_div,
|
||||
bool enable);
|
||||
|
||||
void (*dpp_deferred_update)(
|
||||
struct dpp *dpp);
|
||||
bool (*dpp_program_blnd_lut)(
|
||||
struct dpp *dpp,
|
||||
const struct pwl_params *params);
|
||||
|
Loading…
x
Reference in New Issue
Block a user