linux/drivers/gpu/drm/i915/display/intel_fbc.c

/*
 * Copyright © 2014 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * DOC: Frame Buffer Compression (FBC)
 *
 * FBC tries to save memory bandwidth (and so power consumption) by
 * compressing the amount of memory used by the display. It is total
 * transparent to user space and completely handled in the kernel.
 *
 * The benefits of FBC are mostly visible with solid backgrounds and
 * variation-less patterns. It comes from keeping the memory footprint small
 * and having fewer memory pages opened and accessed for refreshing the display.
 *
 * i915 is responsible to reserve stolen memory for FBC and configure its
 * offset on proper registers. The hardware takes care of all
 * compress/decompress. However there are many known cases where we have to
 * forcibly disable it to allow proper screen updates.
 */

#include <linux/string_helpers.h>

#include <drm/drm_blend.h>
#include <drm/drm_fourcc.h>

#include "gem/i915_gem_stolen.h"
#include "gt/intel_gt_types.h"
#include "i915_drv.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "i915_vgpu.h"
#include "i915_vma.h"
#include "i9xx_plane_regs.h"
#include "intel_cdclk.h"
#include "intel_de.h"
#include "intel_display_device.h"
#include "intel_display_trace.h"
#include "intel_display_types.h"
#include "intel_display_wa.h"
#include "intel_fbc.h"
#include "intel_fbc_regs.h"
#include "intel_frontbuffer.h"

#define for_each_fbc_id(__display, __fbc_id)

#define for_each_intel_fbc(__display, __fbc, __fbc_id)

struct intel_fbc_funcs {};

struct intel_fbc_state {};

struct intel_fbc {};

/* plane stride in pixels */
static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
{}

static unsigned int intel_fbc_cfb_cpp(void)
{}

/* plane stride based cfb stride in bytes, assuming 1:1 compression limit */
static unsigned int intel_fbc_plane_cfb_stride(const struct intel_plane_state *plane_state)
{}

/* minimum acceptable cfb stride in bytes, assuming 1:1 compression limit */
static unsigned int skl_fbc_min_cfb_stride(struct intel_display *display,
					   unsigned int cpp, unsigned int width)
{}

/* properly aligned cfb stride in bytes, assuming 1:1 compression limit */
static unsigned int _intel_fbc_cfb_stride(struct intel_display *display,
					  unsigned int cpp, unsigned int width,
					  unsigned int stride)
{}

static unsigned int intel_fbc_cfb_stride(const struct intel_plane_state *plane_state)
{}

/*
 * Maximum height the hardware will compress, on HSW+
 * additional lines (up to the actual plane height) will
 * remain uncompressed.
 */
static unsigned int intel_fbc_max_cfb_height(struct intel_display *display)
{}

static unsigned int _intel_fbc_cfb_size(struct intel_display *display,
					unsigned int height, unsigned int stride)
{}

static unsigned int intel_fbc_cfb_size(const struct intel_plane_state *plane_state)
{}

static u16 intel_fbc_override_cfb_stride(const struct intel_plane_state *plane_state)
{}

static bool intel_fbc_has_fences(struct intel_display *display)
{}

static u32 i8xx_fbc_ctl(struct intel_fbc *fbc)
{}

static u32 i965_fbc_ctl2(struct intel_fbc *fbc)
{}

static void i8xx_fbc_deactivate(struct intel_fbc *fbc)
{}

static void i8xx_fbc_activate(struct intel_fbc *fbc)
{}

static bool i8xx_fbc_is_active(struct intel_fbc *fbc)
{}

static bool i8xx_fbc_is_compressing(struct intel_fbc *fbc)
{}

static void i8xx_fbc_nuke(struct intel_fbc *fbc)
{}

static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
{}

static const struct intel_fbc_funcs i8xx_fbc_funcs =;

static void i965_fbc_nuke(struct intel_fbc *fbc)
{}

static const struct intel_fbc_funcs i965_fbc_funcs =;

static u32 g4x_dpfc_ctl_limit(struct intel_fbc *fbc)
{}

static u32 g4x_dpfc_ctl(struct intel_fbc *fbc)
{}

static void g4x_fbc_activate(struct intel_fbc *fbc)
{}

static void g4x_fbc_deactivate(struct intel_fbc *fbc)
{}

static bool g4x_fbc_is_active(struct intel_fbc *fbc)
{}

static bool g4x_fbc_is_compressing(struct intel_fbc *fbc)
{}

static void g4x_fbc_program_cfb(struct intel_fbc *fbc)
{}

static const struct intel_fbc_funcs g4x_fbc_funcs =;

static void ilk_fbc_activate(struct intel_fbc *fbc)
{}

static void ilk_fbc_deactivate(struct intel_fbc *fbc)
{}

static bool ilk_fbc_is_active(struct intel_fbc *fbc)
{}

static bool ilk_fbc_is_compressing(struct intel_fbc *fbc)
{}

static void ilk_fbc_program_cfb(struct intel_fbc *fbc)
{}

static const struct intel_fbc_funcs ilk_fbc_funcs =;

static void snb_fbc_program_fence(struct intel_fbc *fbc)
{}

static void snb_fbc_activate(struct intel_fbc *fbc)
{}

static void snb_fbc_nuke(struct intel_fbc *fbc)
{}

static const struct intel_fbc_funcs snb_fbc_funcs =;

static void glk_fbc_program_cfb_stride(struct intel_fbc *fbc)
{}

static void skl_fbc_program_cfb_stride(struct intel_fbc *fbc)
{}

static u32 ivb_dpfc_ctl(struct intel_fbc *fbc)
{}

static void ivb_fbc_activate(struct intel_fbc *fbc)
{}

static bool ivb_fbc_is_compressing(struct intel_fbc *fbc)
{}

static void ivb_fbc_set_false_color(struct intel_fbc *fbc,
				    bool enable)
{}

static const struct intel_fbc_funcs ivb_fbc_funcs =;

static bool intel_fbc_hw_is_active(struct intel_fbc *fbc)
{}

static void intel_fbc_hw_activate(struct intel_fbc *fbc)
{}

static void intel_fbc_hw_deactivate(struct intel_fbc *fbc)
{}

static bool intel_fbc_is_compressing(struct intel_fbc *fbc)
{}

static void intel_fbc_nuke(struct intel_fbc *fbc)
{}

static void intel_fbc_activate(struct intel_fbc *fbc)
{}

static void intel_fbc_deactivate(struct intel_fbc *fbc, const char *reason)
{}

static u64 intel_fbc_cfb_base_max(struct intel_display *display)
{}

static u64 intel_fbc_stolen_end(struct intel_display *display)
{}

static int intel_fbc_min_limit(const struct intel_plane_state *plane_state)
{}

static int intel_fbc_max_limit(struct intel_display *display)
{}

static int find_compression_limit(struct intel_fbc *fbc,
				  unsigned int size, int min_limit)
{}

static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,
			       unsigned int size, int min_limit)
{}

static void intel_fbc_program_cfb(struct intel_fbc *fbc)
{}

static void intel_fbc_program_workarounds(struct intel_fbc *fbc)
{}

static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)
{}

void intel_fbc_cleanup(struct intel_display *display)
{}

static bool i8xx_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
{}

static bool i965_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
{}

static bool g4x_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
{}

static bool skl_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
{}

static bool icl_fbc_stride_is_valid(const struct intel_plane_state *plane_state)
{}

static bool stride_is_valid(const struct intel_plane_state *plane_state)
{}

static bool i8xx_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
{}

static bool g4x_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
{}

static bool lnl_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state)
{}

static bool pixel_format_is_valid(const struct intel_plane_state *plane_state)
{}

static bool i8xx_fbc_rotation_is_valid(const struct intel_plane_state *plane_state)
{}

static bool g4x_fbc_rotation_is_valid(const struct intel_plane_state *plane_state)
{}

static bool skl_fbc_rotation_is_valid(const struct intel_plane_state *plane_state)
{}

static bool rotation_is_valid(const struct intel_plane_state *plane_state)
{}

static void intel_fbc_max_surface_size(struct intel_display *display,
				       unsigned int *w, unsigned int *h)
{}

/*
 * For some reason, the hardware tracking starts looking at whatever we
 * programmed as the display plane base address register. It does not look at
 * the X and Y offset registers. That's why we include the src x/y offsets
 * instead of just looking at the plane size.
 */
static bool intel_fbc_surface_size_ok(const struct intel_plane_state *plane_state)
{}

static void intel_fbc_max_plane_size(struct intel_display *display,
				     unsigned int *w, unsigned int *h)
{}

static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state)
{}

static bool i8xx_fbc_tiling_valid(const struct intel_plane_state *plane_state)
{}

static bool skl_fbc_tiling_valid(const struct intel_plane_state *plane_state)
{}

static bool tiling_is_valid(const struct intel_plane_state *plane_state)
{}

static void intel_fbc_update_state(struct intel_atomic_state *state,
				   struct intel_crtc *crtc,
				   struct intel_plane *plane)
{}

static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
{}

static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state)
{}

static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state)
{}

static int intel_fbc_check_plane(struct intel_atomic_state *state,
				 struct intel_plane *plane)
{}


static bool intel_fbc_can_flip_nuke(struct intel_atomic_state *state,
				    struct intel_crtc *crtc,
				    struct intel_plane *plane)
{}

static bool __intel_fbc_pre_update(struct intel_atomic_state *state,
				   struct intel_crtc *crtc,
				   struct intel_plane *plane)
{}

bool intel_fbc_pre_update(struct intel_atomic_state *state,
			  struct intel_crtc *crtc)
{}

static void __intel_fbc_disable(struct intel_fbc *fbc)
{}

static void __intel_fbc_post_update(struct intel_fbc *fbc)
{}

void intel_fbc_post_update(struct intel_atomic_state *state,
			   struct intel_crtc *crtc)
{}

static unsigned int intel_fbc_get_frontbuffer_bit(struct intel_fbc *fbc)
{}

static void __intel_fbc_invalidate(struct intel_fbc *fbc,
				   unsigned int frontbuffer_bits,
				   enum fb_op_origin origin)
{}

void intel_fbc_invalidate(struct drm_i915_private *i915,
			  unsigned int frontbuffer_bits,
			  enum fb_op_origin origin)
{}

static void __intel_fbc_flush(struct intel_fbc *fbc,
			      unsigned int frontbuffer_bits,
			      enum fb_op_origin origin)
{}

void intel_fbc_flush(struct drm_i915_private *i915,
		     unsigned int frontbuffer_bits,
		     enum fb_op_origin origin)
{}

int intel_fbc_atomic_check(struct intel_atomic_state *state)
{}

static void __intel_fbc_enable(struct intel_atomic_state *state,
			       struct intel_crtc *crtc,
			       struct intel_plane *plane)
{}

/**
 * intel_fbc_disable - disable FBC if it's associated with crtc
 * @crtc: the CRTC
 *
 * This function disables FBC if it's associated with the provided CRTC.
 */
void intel_fbc_disable(struct intel_crtc *crtc)
{}

void intel_fbc_update(struct intel_atomic_state *state,
		      struct intel_crtc *crtc)
{}

static void intel_fbc_underrun_work_fn(struct work_struct *work)
{}

static void __intel_fbc_reset_underrun(struct intel_fbc *fbc)
{}

/*
 * intel_fbc_reset_underrun - reset FBC fifo underrun status.
 * @display: display
 *
 * See intel_fbc_handle_fifo_underrun_irq(). For automated testing we
 * want to re-enable FBC after an underrun to increase test coverage.
 */
void intel_fbc_reset_underrun(struct intel_display *display)
{}

static void __intel_fbc_handle_fifo_underrun_irq(struct intel_fbc *fbc)
{}

/**
 * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
 * @display: display
 *
 * Without FBC, most underruns are harmless and don't really cause too many
 * problems, except for an annoying message on dmesg. With FBC, underruns can
 * become black screens or even worse, especially when paired with bad
 * watermarks. So in order for us to be on the safe side, completely disable FBC
 * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe
 * already suggests that watermarks may be bad, so try to be as safe as
 * possible.
 *
 * This function is called from the IRQ handler.
 */
void intel_fbc_handle_fifo_underrun_irq(struct intel_display *display)
{}

/*
 * The DDX driver changes its behavior depending on the value it reads from
 * i915.enable_fbc, so sanitize it by translating the default value into either
 * 0 or 1 in order to allow it to know what's going on.
 *
 * Notice that this is done at driver initialization and we still allow user
 * space to change the value during runtime without sanitizing it again. IGT
 * relies on being able to change i915.enable_fbc at runtime.
 */
static int intel_sanitize_fbc_option(struct intel_display *display)
{}

void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)
{}

static struct intel_fbc *intel_fbc_create(struct intel_display *display,
					  enum intel_fbc_id fbc_id)
{}

/**
 * intel_fbc_init - Initialize FBC
 * @display: display
 *
 * This function might be called during PM init process.
 */
void intel_fbc_init(struct intel_display *display)
{}

/**
 * intel_fbc_sanitize - Sanitize FBC
 * @display: display
 *
 * Make sure FBC is initially disabled since we have no
 * idea eg. into which parts of stolen it might be scribbling
 * into.
 */
void intel_fbc_sanitize(struct intel_display *display)
{}

static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
{}

DEFINE_SHOW_ATTRIBUTE();

static int intel_fbc_debugfs_false_color_get(void *data, u64 *val)
{}

static int intel_fbc_debugfs_false_color_set(void *data, u64 val)
{}

DEFINE_DEBUGFS_ATTRIBUTE();

static void intel_fbc_debugfs_add(struct intel_fbc *fbc,
				  struct dentry *parent)
{}

void intel_fbc_crtc_debugfs_add(struct intel_crtc *crtc)
{}

/* FIXME: remove this once igt is on board with per-crtc stuff */
void intel_fbc_debugfs_register(struct intel_display *display)
{}