From 79af598a5baefc3a92b31ebc5b7aff00b38dc633 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 17 Mar 2021 19:01:46 -0400 Subject: drm/nouveau/kms/nv50-: Always validate LUTs in nv50_head_atomic_check_lut() When it comes to gamma or degamma luts, nouveau will actually skip the calculation of certain LUTs depending on the head and plane states. For instance, when the head is disabled we don't perform any error checking on the gamma LUT, and likewise if no planes are present and enabled in our atomic state we will skip error checking the degamma LUT. This is a bit of a problem though, since the per-head gamma and degamma props in DRM can be changed even while a head is disabled - a situation which can be triggered by the igt testcase mentioned down below. Originally I thought this was a bit silly and was tempted to just fix the igt test to only set gamma/degamma with the head enabled. After a bit of thinking though I realized we should fix this in nouveau. This is because if a program decides to set an invalid LUT for a head before enabling the head, such a property change would succeed while also making it impossible to turn the head back on until the LUT is removed or corrected - something that could be painful for a user to figure out. So, fix this checking both degamma and gamma LUTs unconditionally during atomic checks. We start by calling nv50_head_atomic_check_lut() regardless of whether the head is active or not in nv50_head_atomic_check(). Then we move the ilut error checking into nv50_head_atomic_check_lut() and add a per-head hook for it, primarily because as a per-CRTC property DRM we want the LUT to be error checked by the head any time it's included in an atomic state. Of course though, actual programming of the degamma lut to hardware is still handled in each plane's atomic check and commit. Signed-off-by: Lyude Paul Testcase: igt/kms_color/pipe-invalid-*-lut-sizes Signed-off-by: Ben Skeggs Reviewed-by: Karol Herbst Signed-off-by: Karol Herbst Link: https://gitlab.freedesktop.org/drm/nouveau/-/merge_requests/10 --- drivers/gpu/drm/nouveau/dispnv50/wndw.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/nouveau/dispnv50/wndw.h') diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index f4e0c5080034..9c9f2c2a71a5 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -64,7 +64,7 @@ struct nv50_wndw_func { int (*ntfy_clr)(struct nv50_wndw *); int (*ntfy_wait_begun)(struct nouveau_bo *, u32 offset, struct nvif_device *); - bool (*ilut)(struct nv50_wndw *, struct nv50_wndw_atom *, int); + void (*ilut)(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyh, int size); void (*csc)(struct nv50_wndw *, struct nv50_wndw_atom *, const struct drm_color_ctm *); int (*csc_set)(struct nv50_wndw *, struct nv50_wndw_atom *); @@ -129,7 +129,7 @@ int wndwc37e_update(struct nv50_wndw *, u32 *); int wndwc57e_new(struct nouveau_drm *, enum drm_plane_type, int, s32, struct nv50_wndw **); -bool wndwc57e_ilut(struct nv50_wndw *, struct nv50_wndw_atom *, int); +void wndwc57e_ilut(struct nv50_wndw *, struct nv50_wndw_atom *, int); int wndwc57e_ilut_set(struct nv50_wndw *, struct nv50_wndw_atom *); int wndwc57e_ilut_clr(struct nv50_wndw *); int wndwc57e_csc_set(struct nv50_wndw *, struct nv50_wndw_atom *); -- cgit v1.2.3