On Sat, 15 Nov 2025, Vinod Govindapillai <[email protected]> wrote:
> One of the FBC instances can utilize the reserved area of SoC
> level cache for the fbc transactions to benefit reduced memory
> system power especially in idle scenarios. Reserved area of the
> system cache can be assigned to an fbc instance by configuring
> the cacheability configuration register with offset of the
> compressed frame buffer in stolen memoty of that fbc. There is
> a limit to this reserved area which is programmable and for
> xe3p_lpd the limit is defined as 2MB.
>
> v2: - better to track fbc sys cache usage from intel_display level,
>       sanitize the cacheability config register on probe (Matt)
>     - limit this for integrated graphics solutions, confirmed that
>       no default value set for cache range by hw (Gustavo)
>
> Bspec: 68881, 74722
> Signed-off-by: Vinod Govindapillai <[email protected]>
> ---
>  .../gpu/drm/i915/display/intel_display_core.h |  3 +
>  .../drm/i915/display/intel_display_device.h   |  1 +
>  drivers/gpu/drm/i915/display/intel_fbc.c      | 76 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_fbc_regs.h |  9 +++
>  4 files changed, 89 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h 
> b/drivers/gpu/drm/i915/display/intel_display_core.h
> index 9b8414b77c15..15b9e4c62c77 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -588,6 +588,9 @@ struct intel_display {
>               u32 bxt_phy_grc;
>       } state;
>  
> +     /* FBC instance utlizing the system cache */
> +     int sys_cache_fbc;

Everything in struct intel_display is in sub-structs. Nothing is in top
level individual members, because that has lead to chaos in all of our
other big structs.

Since we already have:

        struct intel_fbc *fbc[I915_MAX_FBCS];

IMO you need to move that under a new fbc sub-struct, and relocate in
the right place:

        struct {
                struct intel_fbc *fbc[I915_MAX_FBCS];
        } fbc;

Maybe the array should be named instances instead of fbc, dunno.

And then you can add sys_cache_id under fbc.

BR,
Jani.




> +
>       struct {
>               unsigned int hpll_freq;
>               unsigned int czclk_freq;
> diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h 
> b/drivers/gpu/drm/i915/display/intel_display_device.h
> index b559ef43d547..b74cb69ccc85 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_device.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_device.h
> @@ -173,6 +173,7 @@ struct intel_display_platforms {
>  #define HAS_DSC_MST(__display)               (DISPLAY_VER(__display) >= 12 
> && HAS_DSC(__display))
>  #define HAS_FBC(__display)           
> (DISPLAY_RUNTIME_INFO(__display)->fbc_mask != 0)
>  #define HAS_FBC_DIRTY_RECT(__display)        (DISPLAY_VER(__display) >= 30)
> +#define HAS_FBC_SYS_CACHE(__display) (DISPLAY_VER(__display) >= 35 && 
> !(__display)->platform.dgfx)
>  #define HAS_FPGA_DBG_UNCLAIMED(__display)    
> (DISPLAY_INFO(__display)->has_fpga_dbg)
>  #define HAS_FW_BLC(__display)                (DISPLAY_VER(__display) >= 3)
>  #define HAS_GMBUS_BURST_READ(__display)      (DISPLAY_VER(__display) >= 10 
> || (__display)->platform.kabylake)
> diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c 
> b/drivers/gpu/drm/i915/display/intel_fbc.c
> index 16cd99db2978..b85f24147a01 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbc.c
> +++ b/drivers/gpu/drm/i915/display/intel_fbc.c
> @@ -73,6 +73,9 @@
>       for_each_fbc_id((__display), (__fbc_id)) \
>               for_each_if((__fbc) = (__display)->fbc[(__fbc_id)])
>  
> +#define SYS_CACHE_FBC_UNASSIGNED             -1
> +#define IS_SYS_CACHE_FBC_UNASSIGNED(__display)       
> ((__display)->sys_cache_fbc == SYS_CACHE_FBC_UNASSIGNED)
> +
>  struct intel_fbc_funcs {
>       void (*activate)(struct intel_fbc *fbc);
>       void (*deactivate)(struct intel_fbc *fbc);
> @@ -945,6 +948,66 @@ static void intel_fbc_program_workarounds(struct 
> intel_fbc *fbc)
>               fbc_compressor_clkgate_disable_wa(fbc, true);
>  }
>  
> +static int xe3p_lpd_fbc_get_cache_limit(void)
> +{
> +     /* Default 2MB for xe3p_lpd */
> +     return 2 * 1024 * 1024;
> +}
> +
> +static void xe3p_lpd_fbc_clear_sys_cache_usage(struct intel_display *display)
> +{
> +     /* Clear all the fields except the default fields */
> +     intel_de_rmw(display, XE3P_LPD_FBC_SYS_CACHE_USAGE_CFG,
> +                  FBC_SYS_CACHE_TAG_MASK | FBC_SYS_CACHEABLE_RANGE_MASK |
> +                  FBC_SYS_CACHE_START_BASE_MASK, 0);
> +
> +     /* Mark that no FBC instance utilize the system cache */
> +     display->sys_cache_fbc = SYS_CACHE_FBC_UNASSIGNED;
> +}
> +
> +static void xe3p_lpd_fbc_set_sys_cache_usage(const struct intel_fbc *fbc)
> +{
> +     struct intel_display *display = fbc->display;
> +     /* limit to be configured to the register in 64k byte chunks */
> +     int range = xe3p_lpd_fbc_get_cache_limit() / (64 * 1024);
> +     /* offset to be configured to the register in 4K byte chunks */
> +     int offset = i915_gem_stolen_node_offset(fbc->compressed_fb) / (4 * 
> 1024);
> +     u32 usage = FBC_SYS_CACHE_TAG_USE_RES_SPACE |
> +                 FBC_SYS_CACHEABLE_RANGE(range) |
> +                 FBC_SYS_CACHE_START_BASE(offset);
> +
> +     lockdep_assert_held(&fbc->lock);
> +
> +     intel_de_rmw(display, XE3P_LPD_FBC_SYS_CACHE_USAGE_CFG,
> +                  FBC_SYS_CACHE_TAG_MASK | FBC_SYS_CACHEABLE_RANGE_MASK |
> +                  FBC_SYS_CACHE_START_BASE_MASK, usage);
> +
> +     display->sys_cache_fbc = fbc->id;
> +}
> +
> +static void xe3p_lpd_fbc_update_sys_cache_usage(const struct intel_fbc *fbc, 
> bool set)
> +{
> +     struct intel_display *display = fbc->display;
> +
> +     lockdep_assert_held(&fbc->lock);
> +
> +     /* system cache for fbc already reserved */
> +     if (set && !IS_SYS_CACHE_FBC_UNASSIGNED(display))
> +             return;
> +
> +     /* cannot clear if "fbc" did not reserve the cache */
> +     if (!set && display->sys_cache_fbc != fbc->id)
> +             return;
> +
> +     if (set)
> +             xe3p_lpd_fbc_set_sys_cache_usage(fbc);
> +     else
> +             xe3p_lpd_fbc_clear_sys_cache_usage(display);
> +
> +     drm_dbg_kms(display->drm, "System cacheability usage for FBC[%d] %s\n",
> +                 fbc->id, set ? "configured" : "cleared");
> +}
> +
>  static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)
>  {
>       if (WARN_ON(intel_fbc_hw_is_active(fbc)))
> @@ -971,6 +1034,9 @@ void intel_fbc_cleanup(struct intel_display *display)
>  
>               kfree(fbc);
>       }
> +
> +     if (HAS_FBC_SYS_CACHE(display))
> +             xe3p_lpd_fbc_clear_sys_cache_usage(display);
>  }
>  
>  static bool i8xx_fbc_stride_is_valid(const struct intel_plane_state 
> *plane_state)
> @@ -1785,6 +1851,9 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
>  
>       __intel_fbc_cleanup_cfb(fbc);
>  
> +     if (HAS_FBC_SYS_CACHE(display))
> +             xe3p_lpd_fbc_update_sys_cache_usage(fbc, false);
> +
>       /* wa_18038517565 Enable DPFC clock gating after FBC disable */
>       if (display->platform.dg2 || DISPLAY_VER(display) >= 14)
>               fbc_compressor_clkgate_disable_wa(fbc, false);
> @@ -1977,6 +2046,9 @@ static void __intel_fbc_enable(struct 
> intel_atomic_state *state,
>  
>       intel_fbc_program_workarounds(fbc);
>       intel_fbc_program_cfb(fbc);
> +
> +     if (HAS_FBC_SYS_CACHE(display))
> +             xe3p_lpd_fbc_update_sys_cache_usage(fbc, true);
>  }
>  
>  /**
> @@ -2236,6 +2308,10 @@ void intel_fbc_sanitize(struct intel_display *display)
>               if (intel_fbc_hw_is_active(fbc))
>                       intel_fbc_hw_deactivate(fbc);
>       }
> +
> +     /* Ensure the sys cache usage register gets cleared */
> +     if (HAS_FBC_SYS_CACHE(display))
> +             xe3p_lpd_fbc_clear_sys_cache_usage(display);
>  }
>  
>  static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
> diff --git a/drivers/gpu/drm/i915/display/intel_fbc_regs.h 
> b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> index b1d0161a3196..9c9fe6355acd 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> +++ b/drivers/gpu/drm/i915/display/intel_fbc_regs.h
> @@ -126,4 +126,13 @@
>  #define   FBC_REND_NUKE                      REG_BIT(2)
>  #define   FBC_REND_CACHE_CLEAN               REG_BIT(1)
>  
> +#define XE3P_LPD_FBC_SYS_CACHE_USAGE_CFG     _MMIO(0x1344E0)
> +#define   FBC_SYS_CACHE_START_BASE_MASK              REG_GENMASK(31, 16)
> +#define   FBC_SYS_CACHE_START_BASE(base)     
> REG_FIELD_PREP(FBC_SYS_CACHE_START_BASE_MASK, (base))
> +#define   FBC_SYS_CACHEABLE_RANGE_MASK               REG_GENMASK(15, 4)
> +#define   FBC_SYS_CACHEABLE_RANGE(range)     
> REG_FIELD_PREP(FBC_SYS_CACHEABLE_RANGE_MASK, (range))
> +#define   FBC_SYS_CACHE_TAG_MASK             REG_GENMASK(3, 2)
> +#define   FBC_SYS_CACHE_TAG_DONT_CACHE               
> REG_FIELD_PREP(FBC_SYS_CACHE_TAG_MASK, 0)
> +#define   FBC_SYS_CACHE_TAG_USE_RES_SPACE    
> REG_FIELD_PREP(FBC_SYS_CACHE_TAG_MASK, 3)
> +
>  #endif /* __INTEL_FBC_REGS__ */

-- 
Jani Nikula, Intel

Reply via email to