From: Hans de Goede <hdegoede@redhat.com>
To: Ville Syrjala <ville.syrjala@linux.intel.com>,
intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH] drm/i915: Preload LUTs if the hw isn't currently using them
Date: Tue, 5 Nov 2019 21:41:58 +0100 [thread overview]
Message-ID: <d76a7724-be92-f464-de57-48ee93d7b1d0@redhat.com> (raw)
In-Reply-To: <20191030190815.7359-1-ville.syrjala@linux.intel.com>
Hi,
On 30-10-2019 20:08, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The LUTs are single buffered so in order to program them without
> tearing we'd have to do it during vblank (actually to be 100%
> effective it has to happen between start of vblank and frame start).
> We have no proper mechanism for that at the moment so we just
> defer loading them after the vblank waits have happened. That
> is not quite sufficient (especially when committing multiple pipes
> whose vblanks don't line up) so the LUT load will often leak into
> the following frame causing tearing.
>
> However in case the hardware wasn't previously using the LUT we
> can preload it before setting the enable bit (which is double
> buffered so won't tear). Let's determine if we can do such
> preloading and make it happen. Slight variation between the
> hardware requires some platforms specifics in the checks.
>
> Hans is seeing ugly colored flash on VLV/CHV macchines (GPD win
> and Asus T100HA) when the gamma LUT gets loaded for the first
> time as the BIOS has left some junk in the LUT memory.
>
> Cc: Hans de Goede <hdegoede@redhat.com>
> Fixes: 051a6d8d3ca0 ("drm/i915: Move LUT programming to happen after vblank waits")
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Thank you very much for this fix.
I've given it a test run and it fixes the flash. The code also looks good to me:
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
> ---
> drivers/gpu/drm/i915/display/intel_atomic.c | 1 +
> drivers/gpu/drm/i915/display/intel_color.c | 61 +++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_display.c | 6 ++
> .../drm/i915/display/intel_display_types.h | 1 +
> 4 files changed, 69 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
> index 9cd6d2348a1e..c2875b10adf9 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> @@ -200,6 +200,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
> crtc_state->update_wm_pre = false;
> crtc_state->update_wm_post = false;
> crtc_state->fifo_changed = false;
> + crtc_state->preload_luts = false;
> crtc_state->wm.need_postvbl_update = false;
> crtc_state->fb_bits = 0;
> crtc_state->update_planes = 0;
> diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
> index fa44eb73d088..d33676e82140 100644
> --- a/drivers/gpu/drm/i915/display/intel_color.c
> +++ b/drivers/gpu/drm/i915/display/intel_color.c
> @@ -1022,6 +1022,55 @@ void intel_color_commit(const struct intel_crtc_state *crtc_state)
> dev_priv->display.color_commit(crtc_state);
> }
>
> +static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> + struct intel_atomic_state *state =
> + to_intel_atomic_state(new_crtc_state->base.state);
> + const struct intel_crtc_state *old_crtc_state =
> + intel_atomic_get_old_crtc_state(state, crtc);
> +
> + return !old_crtc_state->base.gamma_lut &&
> + !old_crtc_state->base.degamma_lut;
> +}
> +
> +static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> + struct intel_atomic_state *state =
> + to_intel_atomic_state(new_crtc_state->base.state);
> + const struct intel_crtc_state *old_crtc_state =
> + intel_atomic_get_old_crtc_state(state, crtc);
> +
> + /*
> + * CGM_PIPE_MODE is itself single buffered. We'd have to
> + * somehow split it out from chv_load_luts() if we wanted
> + * the ability to preload the GCM LUTs/CSC without tearing.
> + */
> + if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode)
> + return false;
> +
> + return !old_crtc_state->base.gamma_lut;
> +}
> +
> +static bool glk_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> + struct intel_atomic_state *state =
> + to_intel_atomic_state(new_crtc_state->base.state);
> + const struct intel_crtc_state *old_crtc_state =
> + intel_atomic_get_old_crtc_state(state, crtc);
> +
> + /*
> + * The hardware degamma is active whenever the pipe
> + * CSC is active. Thus even if the old state has no
> + * software degamma we need to avoid clobbering the
> + * linear hardware degamma mid scanout.
> + */
> + return !old_crtc_state->csc_enable &&
> + !old_crtc_state->base.gamma_lut;
> +}
> +
> int intel_color_check(struct intel_crtc_state *crtc_state)
> {
> struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> @@ -1165,6 +1214,8 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1217,6 +1268,8 @@ static int chv_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = chv_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1271,6 +1324,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1328,6 +1383,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1366,6 +1423,8 @@ static int glk_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = glk_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1415,6 +1474,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state)
>
> crtc_state->csc_mode = icl_csc_mode(crtc_state);
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index a23375621185..dd655ba3560c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -14201,6 +14201,11 @@ static void intel_update_crtc(struct intel_crtc *crtc,
> /* vblanks work again, re-enable pipe CRC. */
> intel_crtc_enable_pipe_crc(crtc);
> } else {
> + if (new_crtc_state->preload_luts &&
> + (new_crtc_state->base.color_mgmt_changed ||
> + new_crtc_state->update_pipe))
> + intel_color_load_luts(new_crtc_state);
> +
> intel_pre_plane_update(old_crtc_state, new_crtc_state);
>
> if (new_crtc_state->update_pipe)
> @@ -14713,6 +14718,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> if (new_crtc_state->base.active &&
> !needs_modeset(new_crtc_state) &&
> + !new_crtc_state->preload_luts &&
> (new_crtc_state->base.color_mgmt_changed ||
> new_crtc_state->update_pipe))
> intel_color_load_luts(new_crtc_state);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 40184e823c84..ae332115daee 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -775,6 +775,7 @@ struct intel_crtc_state {
> bool disable_cxsr;
> bool update_wm_pre, update_wm_post; /* watermarks are updated */
> bool fifo_changed; /* FIFO split is changed */
> + bool preload_luts;
>
> /* Pipe source size (ie. panel fitter input size)
> * All planes will be positioned inside this space,
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
WARNING: multiple messages have this Message-ID (diff)
From: Hans de Goede <hdegoede@redhat.com>
To: Ville Syrjala <ville.syrjala@linux.intel.com>,
intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH] drm/i915: Preload LUTs if the hw isn't currently using them
Date: Tue, 5 Nov 2019 21:41:58 +0100 [thread overview]
Message-ID: <d76a7724-be92-f464-de57-48ee93d7b1d0@redhat.com> (raw)
Message-ID: <20191105204158.uGqxZhTLZjI27SlWISVH-4FBbbOmoV43kNq_LvfJaMs@z> (raw)
In-Reply-To: <20191030190815.7359-1-ville.syrjala@linux.intel.com>
Hi,
On 30-10-2019 20:08, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The LUTs are single buffered so in order to program them without
> tearing we'd have to do it during vblank (actually to be 100%
> effective it has to happen between start of vblank and frame start).
> We have no proper mechanism for that at the moment so we just
> defer loading them after the vblank waits have happened. That
> is not quite sufficient (especially when committing multiple pipes
> whose vblanks don't line up) so the LUT load will often leak into
> the following frame causing tearing.
>
> However in case the hardware wasn't previously using the LUT we
> can preload it before setting the enable bit (which is double
> buffered so won't tear). Let's determine if we can do such
> preloading and make it happen. Slight variation between the
> hardware requires some platforms specifics in the checks.
>
> Hans is seeing ugly colored flash on VLV/CHV macchines (GPD win
> and Asus T100HA) when the gamma LUT gets loaded for the first
> time as the BIOS has left some junk in the LUT memory.
>
> Cc: Hans de Goede <hdegoede@redhat.com>
> Fixes: 051a6d8d3ca0 ("drm/i915: Move LUT programming to happen after vblank waits")
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Thank you very much for this fix.
I've given it a test run and it fixes the flash. The code also looks good to me:
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
> ---
> drivers/gpu/drm/i915/display/intel_atomic.c | 1 +
> drivers/gpu/drm/i915/display/intel_color.c | 61 +++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_display.c | 6 ++
> .../drm/i915/display/intel_display_types.h | 1 +
> 4 files changed, 69 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
> index 9cd6d2348a1e..c2875b10adf9 100644
> --- a/drivers/gpu/drm/i915/display/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/display/intel_atomic.c
> @@ -200,6 +200,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
> crtc_state->update_wm_pre = false;
> crtc_state->update_wm_post = false;
> crtc_state->fifo_changed = false;
> + crtc_state->preload_luts = false;
> crtc_state->wm.need_postvbl_update = false;
> crtc_state->fb_bits = 0;
> crtc_state->update_planes = 0;
> diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
> index fa44eb73d088..d33676e82140 100644
> --- a/drivers/gpu/drm/i915/display/intel_color.c
> +++ b/drivers/gpu/drm/i915/display/intel_color.c
> @@ -1022,6 +1022,55 @@ void intel_color_commit(const struct intel_crtc_state *crtc_state)
> dev_priv->display.color_commit(crtc_state);
> }
>
> +static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> + struct intel_atomic_state *state =
> + to_intel_atomic_state(new_crtc_state->base.state);
> + const struct intel_crtc_state *old_crtc_state =
> + intel_atomic_get_old_crtc_state(state, crtc);
> +
> + return !old_crtc_state->base.gamma_lut &&
> + !old_crtc_state->base.degamma_lut;
> +}
> +
> +static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> + struct intel_atomic_state *state =
> + to_intel_atomic_state(new_crtc_state->base.state);
> + const struct intel_crtc_state *old_crtc_state =
> + intel_atomic_get_old_crtc_state(state, crtc);
> +
> + /*
> + * CGM_PIPE_MODE is itself single buffered. We'd have to
> + * somehow split it out from chv_load_luts() if we wanted
> + * the ability to preload the GCM LUTs/CSC without tearing.
> + */
> + if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode)
> + return false;
> +
> + return !old_crtc_state->base.gamma_lut;
> +}
> +
> +static bool glk_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
> +{
> + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
> + struct intel_atomic_state *state =
> + to_intel_atomic_state(new_crtc_state->base.state);
> + const struct intel_crtc_state *old_crtc_state =
> + intel_atomic_get_old_crtc_state(state, crtc);
> +
> + /*
> + * The hardware degamma is active whenever the pipe
> + * CSC is active. Thus even if the old state has no
> + * software degamma we need to avoid clobbering the
> + * linear hardware degamma mid scanout.
> + */
> + return !old_crtc_state->csc_enable &&
> + !old_crtc_state->base.gamma_lut;
> +}
> +
> int intel_color_check(struct intel_crtc_state *crtc_state)
> {
> struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
> @@ -1165,6 +1214,8 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1217,6 +1268,8 @@ static int chv_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = chv_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1271,6 +1324,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1328,6 +1383,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1366,6 +1423,8 @@ static int glk_color_check(struct intel_crtc_state *crtc_state)
> if (ret)
> return ret;
>
> + crtc_state->preload_luts = glk_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> @@ -1415,6 +1474,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state)
>
> crtc_state->csc_mode = icl_csc_mode(crtc_state);
>
> + crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index a23375621185..dd655ba3560c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -14201,6 +14201,11 @@ static void intel_update_crtc(struct intel_crtc *crtc,
> /* vblanks work again, re-enable pipe CRC. */
> intel_crtc_enable_pipe_crc(crtc);
> } else {
> + if (new_crtc_state->preload_luts &&
> + (new_crtc_state->base.color_mgmt_changed ||
> + new_crtc_state->update_pipe))
> + intel_color_load_luts(new_crtc_state);
> +
> intel_pre_plane_update(old_crtc_state, new_crtc_state);
>
> if (new_crtc_state->update_pipe)
> @@ -14713,6 +14718,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
> for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
> if (new_crtc_state->base.active &&
> !needs_modeset(new_crtc_state) &&
> + !new_crtc_state->preload_luts &&
> (new_crtc_state->base.color_mgmt_changed ||
> new_crtc_state->update_pipe))
> intel_color_load_luts(new_crtc_state);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 40184e823c84..ae332115daee 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -775,6 +775,7 @@ struct intel_crtc_state {
> bool disable_cxsr;
> bool update_wm_pre, update_wm_post; /* watermarks are updated */
> bool fifo_changed; /* FIFO split is changed */
> + bool preload_luts;
>
> /* Pipe source size (ie. panel fitter input size)
> * All planes will be positioned inside this space,
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2019-11-05 20:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-30 19:08 [PATCH] drm/i915: Preload LUTs if the hw isn't currently using them Ville Syrjala
2019-10-30 19:08 ` [Intel-gfx] " Ville Syrjala
2019-10-30 20:00 ` ✓ Fi.CI.BAT: success for " Patchwork
2019-10-30 20:00 ` [Intel-gfx] " Patchwork
2019-10-31 23:40 ` ✓ Fi.CI.IGT: " Patchwork
2019-10-31 23:40 ` [Intel-gfx] " Patchwork
2019-11-05 20:41 ` Hans de Goede [this message]
2019-11-05 20:41 ` [Intel-gfx] [PATCH] " Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d76a7724-be92-f464-de57-48ee93d7b1d0@redhat.com \
--to=hdegoede@redhat.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=ville.syrjala@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox