From 5298eea7ed209ff14aebce70ae11f212bab37f9f Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Mon, 27 Oct 2025 15:40:01 +0200 Subject: [PATCH] drm/i915/xe3p_lpd: use pixel normalizer for fp16 formats for FBC There is a hw restriction that we could enable the FBC for FP16 formats only if the pixel normalization block is enabled. Hence enable the pixel normalizer block with normalzation factor as 1.0 for the supported FP16 formats to get the FBC enabled. Two existing helper function definitions are moved up to avoid the forward declarations as part of this patch as well. v2: sw/hw state differentiation on handling pixel normalizer (Jani) Bspec: 69863, 68881 Cc: Shekhar Chauhan Signed-off-by: Vinod Govindapillai Signed-off-by: Gustavo Sousa Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20251027134001.325064-5-vinod.govindapillai@intel.com --- drivers/gpu/drm/i915/display/intel_fbc.c | 9 +++ drivers/gpu/drm/i915/display/intel_fbc.h | 2 + .../drm/i915/display/skl_universal_plane.c | 65 ++++++++++++++----- .../i915/display/skl_universal_plane_regs.h | 12 ++++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 0f697c7b1d466..54b23116ea3c3 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1119,6 +1119,15 @@ static bool xe3p_lpd_fbc_pixel_format_is_valid(const struct intel_plane_state *p } } +bool +intel_fbc_is_enable_pixel_normalizer(const struct intel_plane_state *plane_state) +{ + struct intel_display *display = to_intel_display(plane_state); + + return DISPLAY_VER(display) >= 35 && + xe3p_lpd_fbc_fp16_format_is_valid(plane_state); +} + static bool pixel_format_is_valid(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state->uapi.plane->dev); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.h b/drivers/gpu/drm/i915/display/intel_fbc.h index c86562404a001..91424563206a3 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.h +++ b/drivers/gpu/drm/i915/display/intel_fbc.h @@ -53,5 +53,7 @@ void intel_fbc_prepare_dirty_rect(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_fbc_dirty_rect_update_noarm(struct intel_dsb *dsb, struct intel_plane *plane); +bool +intel_fbc_is_enable_pixel_normalizer(const struct intel_plane_state *plane_state); #endif /* __INTEL_FBC_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index d24070d61c0e1..ba1bf0bd4c55f 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -439,6 +439,23 @@ static int skl_plane_max_height(const struct drm_framebuffer *fb, return 4096; } +static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) +{ + return pipe - PIPE_A + INTEL_FBC_A; +} + +static bool skl_plane_has_fbc(struct intel_display *display, + enum intel_fbc_id fbc_id, enum plane_id plane_id) +{ + if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) + return false; + + if (DISPLAY_VER(display) >= 20) + return icl_is_hdr_plane(display, plane_id); + else + return plane_id == PLANE_1; +} + static int icl_plane_max_height(const struct drm_framebuffer *fb, int color_plane, unsigned int rotation) @@ -874,6 +891,25 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb, intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); } +static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb, + struct intel_plane *plane, + bool enable) +{ + struct intel_display *display = to_intel_display(plane); + enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe); + u32 val; + + /* Only HDR planes have pixel normalizer and don't matter if no FBC */ + if (!skl_plane_has_fbc(display, fbc_id, plane->id)) + return; + + val = enable ? PLANE_PIXEL_NORMALIZE_NORM_FACTOR(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0) | + PLANE_PIXEL_NORMALIZE_ENABLE : 0; + + intel_de_write_dsb(display, dsb, + PLANE_PIXEL_NORMALIZE(plane->pipe, plane->id), val); +} + static void icl_plane_disable_arm(struct intel_dsb *dsb, struct intel_plane *plane, @@ -889,6 +925,10 @@ icl_plane_disable_arm(struct intel_dsb *dsb, skl_write_plane_wm(dsb, plane, crtc_state); icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); + + if (DISPLAY_VER(display) >= 35) + x3p_lpd_plane_update_pixel_normalizer(dsb, plane, false); + intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0); intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0); } @@ -1618,6 +1658,14 @@ icl_plane_update_arm(struct intel_dsb *dsb, icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); + /* + * In order to have FBC for fp16 formats pixel normalizer block must be + * active. Check if pixel normalizer block need to be enabled for FBC. + * If needed, use normalization factor as 1.0 and enable the block. + */ + if (intel_fbc_is_enable_pixel_normalizer(plane_state)) + x3p_lpd_plane_update_pixel_normalizer(dsb, plane, true); + /* * The control register self-arms if the plane was previously * disabled. Try to make the plane enable atomic by writing @@ -2390,23 +2438,6 @@ void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state, } } -static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) -{ - return pipe - PIPE_A + INTEL_FBC_A; -} - -static bool skl_plane_has_fbc(struct intel_display *display, - enum intel_fbc_id fbc_id, enum plane_id plane_id) -{ - if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) - return false; - - if (DISPLAY_VER(display) >= 20) - return icl_is_hdr_plane(display, plane_id); - else - return plane_id == PLANE_1; -} - static struct intel_fbc *skl_plane_fbc(struct intel_display *display, enum pipe pipe, enum plane_id plane_id) { diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h b/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h index ca9fdfbbe57cf..7c944d3ca8555 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h +++ b/drivers/gpu/drm/i915/display/skl_universal_plane_regs.h @@ -455,4 +455,16 @@ _SEL_FETCH_PLANE_OFFSET_5_A, _SEL_FETCH_PLANE_OFFSET_5_B, \ _SEL_FETCH_PLANE_OFFSET_6_A, _SEL_FETCH_PLANE_OFFSET_6_B) +#define _PLANE_PIXEL_NORMALIZE_1_A 0x701a8 +#define _PLANE_PIXEL_NORMALIZE_2_A 0x702a8 +#define _PLANE_PIXEL_NORMALIZE_1_B 0x711a8 +#define _PLANE_PIXEL_NORMALIZE_2_B 0x712a8 +#define PLANE_PIXEL_NORMALIZE(pipe, plane) _MMIO_SKL_PLANE((pipe), (plane), \ + _PLANE_PIXEL_NORMALIZE_1_A, _PLANE_PIXEL_NORMALIZE_1_B, \ + _PLANE_PIXEL_NORMALIZE_2_A, _PLANE_PIXEL_NORMALIZE_2_B) +#define PLANE_PIXEL_NORMALIZE_ENABLE REG_BIT(31) +#define PLANE_PIXEL_NORMALIZE_NORM_FACTOR_MASK REG_GENMASK(15, 0) +#define PLANE_PIXEL_NORMALIZE_NORM_FACTOR(val) REG_FIELD_PREP(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_MASK, (val)) +#define PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0 0x3c00 + #endif /* __SKL_UNIVERSAL_PLANE_REGS_H__ */ -- 2.47.3