mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 06:31:58 +02:00
drm/amd/display: Clear the CUR_ENABLE register on DCN314 w/out DPP PG
[Why&How] ON DCN314, clearing DPP SW structure without power gating it can cause a double cursor in full screen with non-native scaling. A W/A that clears CURSOR0_CONTROL cursor_enable flag if dcn10_plane_atomic_power_down is called and DPP power gating is disabled. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4168 Reviewed-by: Sun peng (Leo) Li <sunpeng.li@amd.com> Signed-off-by: Ivan Lipski <ivan.lipski@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
306cbcc6f6
commit
645f74f1dc
|
|
@ -520,6 +520,15 @@ void dpp1_dppclk_control(
|
|||
REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 0);
|
||||
}
|
||||
|
||||
void dpp_force_disable_cursor(struct dpp *dpp_base)
|
||||
{
|
||||
struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
|
||||
|
||||
/* Force disable cursor */
|
||||
REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, 0);
|
||||
dpp_base->pos.cur0_ctl.bits.cur0_enable = 0;
|
||||
}
|
||||
|
||||
static const struct dpp_funcs dcn10_dpp_funcs = {
|
||||
.dpp_read_state = dpp_read_state,
|
||||
.dpp_reset = dpp_reset,
|
||||
|
|
|
|||
|
|
@ -1525,4 +1525,6 @@ void dpp1_construct(struct dcn10_dpp *dpp1,
|
|||
|
||||
void dpp1_cm_get_gamut_remap(struct dpp *dpp_base,
|
||||
struct dpp_grph_csc_adjustment *adjust);
|
||||
void dpp_force_disable_cursor(struct dpp *dpp_base);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1494,6 +1494,7 @@ static struct dpp_funcs dcn30_dpp_funcs = {
|
|||
.dpp_dppclk_control = dpp1_dppclk_control,
|
||||
.dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier,
|
||||
.dpp_get_gamut_remap = dpp3_cm_get_gamut_remap,
|
||||
.dpp_force_disable_cursor = dpp_force_disable_cursor,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -528,3 +528,75 @@ void dcn314_disable_link_output(struct dc_link *link,
|
|||
|
||||
apply_symclk_on_tx_off_wa(link);
|
||||
}
|
||||
|
||||
/**
|
||||
* dcn314_dpp_pg_control - DPP power gate control.
|
||||
*
|
||||
* @hws: dce_hwseq reference.
|
||||
* @dpp_inst: DPP instance reference.
|
||||
* @power_on: true if we want to enable power gate, false otherwise.
|
||||
*
|
||||
* Enable or disable power gate in the specific DPP instance.
|
||||
* If power gating is disabled, will force disable cursor in the DPP instance.
|
||||
*/
|
||||
void dcn314_dpp_pg_control(
|
||||
struct dce_hwseq *hws,
|
||||
unsigned int dpp_inst,
|
||||
bool power_on)
|
||||
{
|
||||
uint32_t power_gate = power_on ? 0 : 1;
|
||||
uint32_t pwr_status = power_on ? 0 : 2;
|
||||
|
||||
|
||||
if (hws->ctx->dc->debug.disable_dpp_power_gate) {
|
||||
/* Workaround for DCN314 with disabled power gating */
|
||||
if (!power_on) {
|
||||
|
||||
/* Force disable cursor if power gating is disabled */
|
||||
struct dpp *dpp = hws->ctx->dc->res_pool->dpps[dpp_inst];
|
||||
if (dpp && dpp->funcs->dpp_force_disable_cursor)
|
||||
dpp->funcs->dpp_force_disable_cursor(dpp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (REG(DOMAIN1_PG_CONFIG) == 0)
|
||||
return;
|
||||
|
||||
switch (dpp_inst) {
|
||||
case 0: /* DPP0 */
|
||||
REG_UPDATE(DOMAIN1_PG_CONFIG,
|
||||
DOMAIN1_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN1_PG_STATUS,
|
||||
DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 1: /* DPP1 */
|
||||
REG_UPDATE(DOMAIN3_PG_CONFIG,
|
||||
DOMAIN3_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN3_PG_STATUS,
|
||||
DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 2: /* DPP2 */
|
||||
REG_UPDATE(DOMAIN5_PG_CONFIG,
|
||||
DOMAIN5_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN5_PG_STATUS,
|
||||
DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 3: /* DPP3 */
|
||||
REG_UPDATE(DOMAIN7_PG_CONFIG,
|
||||
DOMAIN7_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN7_PG_STATUS,
|
||||
DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,4 +47,6 @@ void dcn314_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst,
|
|||
|
||||
void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal);
|
||||
|
||||
void dcn314_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on);
|
||||
|
||||
#endif /* __DC_HWSS_DCN314_H__ */
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ static const struct hwseq_private_funcs dcn314_private_funcs = {
|
|||
.enable_power_gating_plane = dcn314_enable_power_gating_plane,
|
||||
.dpp_root_clock_control = dcn314_dpp_root_clock_control,
|
||||
.hubp_pg_control = dcn31_hubp_pg_control,
|
||||
.dpp_pg_control = dcn314_dpp_pg_control,
|
||||
.program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
|
||||
.update_odm = dcn314_update_odm,
|
||||
.dsc_pg_control = dcn314_dsc_pg_control,
|
||||
|
|
|
|||
|
|
@ -349,6 +349,9 @@ struct dpp_funcs {
|
|||
struct dpp *dpp_base,
|
||||
enum dc_color_space color_space,
|
||||
struct dc_csc_transform cursor_csc_color_matrix);
|
||||
|
||||
void (*dpp_force_disable_cursor)(struct dpp *dpp_base);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user