Commit 737b2b53 authored by Nicholas Kazlauskas's avatar Nicholas Kazlauskas Committed by Alex Deucher

drm/amd/display: Fix MPC OGAM power on/off sequence

[Why]
Color corruption can occur on bootup into a login
manager that applies a non-linear gamma LUT because
the LUT may not actually be powered on before writing.

It's cleared on the next full pipe reprogramming as
we switch to LUTB from LUTA and the pipe accessing
the LUT has taken it out of light sleep mode.

[How]
The MPCC_OGAM_MEM_PWR_FORCE register does not force
the current power mode when set to 0. It only forces
when set light sleep, deep sleep or shutdown.

The register to actually force power on and ignore
sleep modes is MPCC_OGAM_MEM_PWR_DIS - a value of 0
will enable power requests and a value of 1 will
disable them.

When PWR_FORCE!=0 is combined with PWR_DIS=0 then
MPCC OGAM memory is forced into the state specified
by the force bits.

If PWR_FORCE is 0 then it respects the mode specified
by MPCC_OGAM_MEM_LOW_PWR_MODE if the RAM LUT is not
in use.

We set that bit to shutdown on low power, but otherwise
it inherits from bootup defaults.

So for the fix:

1. Update the sequence to "force" power on when needed

We can use MPCC_OGAM_MEM_PWR_DIS for this to turn on the
memory even when the block is in bypass and pending to be
enabled for the next frame.

We need this for both low power enabled or disabled.

If we don't set this then we can run into issues when we
first program the LUT from bootup.

2. Don't apply FORCE_SEL

Once we enable power requests with DIS=0 we run into the
issue of the RAM being forced into light sleep and being
unusable for display output. Leave this 0 like we used to
for DCN20.

3. Rely on MPCC OGAM init to determine light sleep/deep sleep

MPC low power debug mode isn't enabled on any ASIC currently
but we'll respect the setting determined during init if it
is.

Lightly tested as working with IGT tests and desktop color
adjustment.

4. Change the MPC resource default for DCN30

It was interleaving the dcn20 and dcn30 versions before
depending on the sequence.

5. REG_WAIT for it to be on whenever we're powering up the
memory

Otherwise we can write register values too early and we'll
get corruption.
Signed-off-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Reviewed-by: default avatarEric Yang <eric.yang2@amd.com>
Acked-by: default avatarQingqing Zhuo <Qingqing.Zhuo@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ecdfc5c9
......@@ -143,16 +143,18 @@ static void mpc3_power_on_ogam_lut(
{
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
// Force power on
REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_DIS, power_on == true ? 1:0);
// Wait for confirmation when powering on
if (power_on)
REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10);
} else {
REG_SET(MPCC_MEM_PWR_CTRL[mpcc_id], 0,
MPCC_OGAM_MEM_PWR_FORCE, power_on == true ? 0 : 1);
}
/*
* Powering on: force memory active so the LUT can be updated.
* Powering off: allow entering memory low power mode
*
* Memory low power mode is controlled during MPC OGAM LUT init.
*/
REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id],
MPCC_OGAM_MEM_PWR_DIS, power_on != 0);
/* Wait for memory to be powered on - we won't be able to write to it otherwise. */
if (power_on)
REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10);
}
static void mpc3_configure_ogam_lut(
......@@ -1427,7 +1429,7 @@ const struct mpc_funcs dcn30_mpc_funcs = {
.acquire_rmu = mpcc3_acquire_rmu,
.program_3dlut = mpc3_program_3dlut,
.release_rmu = mpcc3_release_rmu,
.power_on_mpc_mem_pwr = mpc20_power_on_ogam_lut,
.power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
.get_mpc_out_mux = mpc1_get_mpc_out_mux,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment