[PATCH v3 2/3] drm/nouveau/kms/nv50-: Introduce nv50_wndw_default_state()

From: Lyude Paul

Date: Mon Jul 20 2026 - 17:54:25 EST


While we don't currently read-in the hardware state of planes, now that
we're about to start exposing blend properties for all planes that can
support alpha channels: We need to make sure that the initial atomic state
for a wndw always starts off with a supported value in pixel_blend_mode.

The easiest way to do this is to introduce a nv50_wndw_default_state()
function, and use it in nv50_display_read_hw_state() - and use that
function to enforce a valid value for pixel_blend_mode during driver
startup.

Signed-off-by: Lyude Paul <lyude@xxxxxxxxxx>
Fixes: 860e748bddcc ("drm: ensure blend mode supported if pixel format with alpha exposed")
---
V3:
* Fix incorrect bitmask checking in nv50_wndw_default_state()

drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 ++++
drivers/gpu/drm/nouveau/dispnv50/wndw.c | 22 ++++++++++++++++++++++
drivers/gpu/drm/nouveau/dispnv50/wndw.h | 1 +
3 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 364227f5456f1..2c66e480b5116 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -2768,6 +2768,7 @@ nv50_display_read_hw_state(struct nouveau_drm *drm)
{
struct drm_device *dev = drm->dev;
struct drm_encoder *encoder;
+ struct drm_plane *plane;
struct drm_modeset_acquire_ctx ctx;
struct nv50_disp *disp = nv50_disp(dev);
int ret;
@@ -2781,6 +2782,9 @@ nv50_display_read_hw_state(struct nouveau_drm *drm)
nv50_display_read_hw_or_state(dev, disp, nouveau_encoder(encoder));
}

+ drm_for_each_plane(plane, dev)
+ nv50_wndw_default_state(nv50_wndw(plane));
+
DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
}

diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 2635458d52acc..dfa1ba45acd99 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -848,6 +848,28 @@ static const u64 nv50_cursor_format_modifiers[] = {
DRM_FORMAT_MOD_INVALID,
};

+/*
+ * Setup defaults for the atomic wndw state
+ */
+void
+nv50_wndw_default_state(struct nv50_wndw *wndw)
+{
+ struct nv50_wndw_atom *armw = nv50_wndw_atom(wndw->plane.state);
+ const unsigned int blend_modes = wndw->func->blend_modes;
+
+ drm_modeset_lock_assert_held(&wndw->plane.mutex);
+
+ /* Ensure the plane's atomic state didn't default to a pixel_blend_mode we don't support */
+ if (blend_modes && (!(BIT(armw->state.pixel_blend_mode) & blend_modes))) {
+ if (blend_modes & BIT(DRM_MODE_BLEND_COVERAGE))
+ armw->state.pixel_blend_mode = DRM_MODE_BLEND_COVERAGE;
+ else if (blend_modes & BIT(DRM_MODE_BLEND_PREMULTI))
+ armw->state.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI;
+ else if (blend_modes & BIT(DRM_MODE_BLEND_PIXEL_NONE))
+ armw->state.pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
+ }
+}
+
int
nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
enum drm_plane_type type, const char *name, int index,
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
index 81af5c3369d4c..13f06b7b67611 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h
@@ -46,6 +46,7 @@ void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush,
struct nv50_wndw_atom *);
void nv50_wndw_ntfy_enable(struct nv50_wndw *, struct nv50_wndw_atom *);
int nv50_wndw_wait_armed(struct nv50_wndw *, struct nv50_wndw_atom *);
+void nv50_wndw_default_state(struct nv50_wndw *wndw);

struct nv50_wndw_func {
int (*acquire)(struct nv50_wndw *, struct nv50_wndw_atom *asyw,
--
2.55.0