Commit 606754fd authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/fbc: Allocate intel_fbc dynamically

In the future we may have more than one FBC instance on some
platforms. So let's just allocate it dynamically. This also
lets us fully hide the implementation from prying eyes.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211124113652.22090-14-ville.syrjala@linux.intel.comReviewed-by: default avatarMika Kahola <mika.kahola@intel.com>
parent 825bd833
...@@ -125,7 +125,7 @@ static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv, ...@@ -125,7 +125,7 @@ static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv,
enum i9xx_plane_id i9xx_plane) enum i9xx_plane_id i9xx_plane)
{ {
if (i9xx_plane_has_fbc(dev_priv, i9xx_plane)) if (i9xx_plane_has_fbc(dev_priv, i9xx_plane))
return &dev_priv->fbc; return dev_priv->fbc;
else else
return NULL; return NULL;
} }
......
...@@ -59,6 +59,63 @@ struct intel_fbc_funcs { ...@@ -59,6 +59,63 @@ struct intel_fbc_funcs {
void (*set_false_color)(struct intel_fbc *fbc, bool enable); void (*set_false_color)(struct intel_fbc *fbc, bool enable);
}; };
struct intel_fbc_state {
const char *no_fbc_reason;
enum i9xx_plane_id i9xx_plane;
unsigned int cfb_stride;
unsigned int cfb_size;
unsigned int fence_y_offset;
u16 override_cfb_stride;
u16 interval;
s8 fence_id;
};
struct intel_fbc {
struct drm_i915_private *i915;
const struct intel_fbc_funcs *funcs;
/*
* This is always the inner lock when overlapping with
* struct_mutex and it's the outer lock when overlapping
* with stolen_lock.
*/
struct mutex lock;
unsigned int possible_framebuffer_bits;
unsigned int busy_bits;
struct intel_plane *plane;
struct drm_mm_node compressed_fb;
struct drm_mm_node compressed_llb;
u8 limit;
bool false_color;
bool active;
bool activated;
bool flip_pending;
bool underrun_detected;
struct work_struct underrun_work;
/*
* Due to the atomic rules we can't access some structures without the
* appropriate locking, so we cache information here in order to avoid
* these problems.
*/
struct intel_fbc_state state_cache;
/*
* This structure contains everything that's relevant to program the
* hardware registers. When we want to figure out if we need to disable
* and re-enable FBC for a new configuration we just check if there's
* something different in the struct. The genx_fbc_activate functions
* are supposed to read from it in order to program the registers.
*/
struct intel_fbc_state params;
const char *no_fbc_reason;
};
/* plane stride in pixels */ /* plane stride in pixels */
static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state) static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
{ {
...@@ -762,14 +819,16 @@ static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) ...@@ -762,14 +819,16 @@ static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)
void intel_fbc_cleanup(struct drm_i915_private *i915) void intel_fbc_cleanup(struct drm_i915_private *i915)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (!HAS_FBC(i915)) if (!fbc)
return; return;
mutex_lock(&fbc->lock); mutex_lock(&fbc->lock);
__intel_fbc_cleanup_cfb(fbc); __intel_fbc_cleanup_cfb(fbc);
mutex_unlock(&fbc->lock); mutex_unlock(&fbc->lock);
kfree(fbc);
} }
static bool stride_is_valid(const struct intel_plane_state *plane_state) static bool stride_is_valid(const struct intel_plane_state *plane_state)
...@@ -1319,9 +1378,9 @@ void intel_fbc_invalidate(struct drm_i915_private *i915, ...@@ -1319,9 +1378,9 @@ void intel_fbc_invalidate(struct drm_i915_private *i915,
unsigned int frontbuffer_bits, unsigned int frontbuffer_bits,
enum fb_op_origin origin) enum fb_op_origin origin)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (!HAS_FBC(i915)) if (!fbc)
return; return;
if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE) if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE)
...@@ -1340,9 +1399,9 @@ void intel_fbc_invalidate(struct drm_i915_private *i915, ...@@ -1340,9 +1399,9 @@ void intel_fbc_invalidate(struct drm_i915_private *i915,
void intel_fbc_flush(struct drm_i915_private *i915, void intel_fbc_flush(struct drm_i915_private *i915,
unsigned int frontbuffer_bits, enum fb_op_origin origin) unsigned int frontbuffer_bits, enum fb_op_origin origin)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (!HAS_FBC(i915)) if (!fbc)
return; return;
mutex_lock(&fbc->lock); mutex_lock(&fbc->lock);
...@@ -1484,9 +1543,9 @@ void intel_fbc_update(struct intel_atomic_state *state, ...@@ -1484,9 +1543,9 @@ void intel_fbc_update(struct intel_atomic_state *state,
*/ */
void intel_fbc_global_disable(struct drm_i915_private *i915) void intel_fbc_global_disable(struct drm_i915_private *i915)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (!HAS_FBC(i915)) if (!fbc)
return; return;
mutex_lock(&fbc->lock); mutex_lock(&fbc->lock);
...@@ -1497,9 +1556,8 @@ void intel_fbc_global_disable(struct drm_i915_private *i915) ...@@ -1497,9 +1556,8 @@ void intel_fbc_global_disable(struct drm_i915_private *i915)
static void intel_fbc_underrun_work_fn(struct work_struct *work) static void intel_fbc_underrun_work_fn(struct work_struct *work)
{ {
struct drm_i915_private *i915 = struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work);
container_of(work, struct drm_i915_private, fbc.underrun_work); struct drm_i915_private *i915 = fbc->i915;
struct intel_fbc *fbc = &i915->fbc;
mutex_lock(&fbc->lock); mutex_lock(&fbc->lock);
...@@ -1524,9 +1582,9 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work) ...@@ -1524,9 +1582,9 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work)
*/ */
void intel_fbc_reset_underrun(struct drm_i915_private *i915) void intel_fbc_reset_underrun(struct drm_i915_private *i915)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (!HAS_FBC(i915)) if (!fbc)
return; return;
cancel_work_sync(&fbc->underrun_work); cancel_work_sync(&fbc->underrun_work);
...@@ -1559,9 +1617,9 @@ void intel_fbc_reset_underrun(struct drm_i915_private *i915) ...@@ -1559,9 +1617,9 @@ void intel_fbc_reset_underrun(struct drm_i915_private *i915)
*/ */
void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915) void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *i915)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (!HAS_FBC(i915)) if (!fbc)
return; return;
/* There's no guarantee that underrun_detected won't be set to true /* There's no guarantee that underrun_detected won't be set to true
...@@ -1621,6 +1679,34 @@ void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane) ...@@ -1621,6 +1679,34 @@ void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)
fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
} }
static struct intel_fbc *intel_fbc_create(struct drm_i915_private *i915)
{
struct intel_fbc *fbc;
fbc = kzalloc(sizeof(*fbc), GFP_KERNEL);
if (!fbc)
return NULL;
fbc->i915 = i915;
INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
mutex_init(&fbc->lock);
if (DISPLAY_VER(i915) >= 7)
fbc->funcs = &ivb_fbc_funcs;
else if (DISPLAY_VER(i915) == 6)
fbc->funcs = &snb_fbc_funcs;
else if (DISPLAY_VER(i915) == 5)
fbc->funcs = &ilk_fbc_funcs;
else if (IS_G4X(i915))
fbc->funcs = &g4x_fbc_funcs;
else if (DISPLAY_VER(i915) == 4)
fbc->funcs = &i965_fbc_funcs;
else
fbc->funcs = &i8xx_fbc_funcs;
return fbc;
}
/** /**
* intel_fbc_init - Initialize FBC * intel_fbc_init - Initialize FBC
* @i915: the i915 device * @i915: the i915 device
...@@ -1629,12 +1715,7 @@ void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane) ...@@ -1629,12 +1715,7 @@ void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane)
*/ */
void intel_fbc_init(struct drm_i915_private *i915) void intel_fbc_init(struct drm_i915_private *i915)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc;
fbc->i915 = i915;
INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
mutex_init(&fbc->lock);
fbc->active = false;
if (!drm_mm_initialized(&i915->mm.stolen)) if (!drm_mm_initialized(&i915->mm.stolen))
mkwrite_device_info(i915)->display.has_fbc = false; mkwrite_device_info(i915)->display.has_fbc = false;
...@@ -1646,29 +1727,20 @@ void intel_fbc_init(struct drm_i915_private *i915) ...@@ -1646,29 +1727,20 @@ void intel_fbc_init(struct drm_i915_private *i915)
drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n", drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n",
i915->params.enable_fbc); i915->params.enable_fbc);
if (!HAS_FBC(i915)) { if (!HAS_FBC(i915))
fbc->no_fbc_reason = "unsupported by this chipset";
return; return;
}
if (DISPLAY_VER(i915) >= 7) fbc = intel_fbc_create(i915);
fbc->funcs = &ivb_fbc_funcs; if (!fbc)
else if (DISPLAY_VER(i915) == 6) return;
fbc->funcs = &snb_fbc_funcs;
else if (DISPLAY_VER(i915) == 5)
fbc->funcs = &ilk_fbc_funcs;
else if (IS_G4X(i915))
fbc->funcs = &g4x_fbc_funcs;
else if (DISPLAY_VER(i915) == 4)
fbc->funcs = &i965_fbc_funcs;
else
fbc->funcs = &i8xx_fbc_funcs;
/* We still don't have any sort of hardware state readout for FBC, so /* We still don't have any sort of hardware state readout for FBC, so
* deactivate it in case the BIOS activated it to make sure software * deactivate it in case the BIOS activated it to make sure software
* matches the hardware state. */ * matches the hardware state. */
if (intel_fbc_hw_is_active(fbc)) if (intel_fbc_hw_is_active(fbc))
intel_fbc_hw_deactivate(fbc); intel_fbc_hw_deactivate(fbc);
i915->fbc = fbc;
} }
static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused) static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
...@@ -1743,8 +1815,8 @@ static void intel_fbc_debugfs_add(struct intel_fbc *fbc) ...@@ -1743,8 +1815,8 @@ static void intel_fbc_debugfs_add(struct intel_fbc *fbc)
void intel_fbc_debugfs_register(struct drm_i915_private *i915) void intel_fbc_debugfs_register(struct drm_i915_private *i915)
{ {
struct intel_fbc *fbc = &i915->fbc; struct intel_fbc *fbc = i915->fbc;
if (HAS_FBC(i915)) if (fbc)
intel_fbc_debugfs_add(fbc); intel_fbc_debugfs_add(fbc);
} }
...@@ -1833,7 +1833,7 @@ static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv, ...@@ -1833,7 +1833,7 @@ static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv,
enum pipe pipe, enum plane_id plane_id) enum pipe pipe, enum plane_id plane_id)
{ {
if (skl_plane_has_fbc(dev_priv, pipe, plane_id)) if (skl_plane_has_fbc(dev_priv, pipe, plane_id))
return &dev_priv->fbc; return dev_priv->fbc;
else else
return NULL; return NULL;
} }
......
...@@ -378,64 +378,8 @@ struct drm_i915_display_funcs { ...@@ -378,64 +378,8 @@ struct drm_i915_display_funcs {
void (*commit_modeset_enables)(struct intel_atomic_state *state); void (*commit_modeset_enables)(struct intel_atomic_state *state);
}; };
struct intel_fbc_funcs;
#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */
struct intel_fbc_state {
const char *no_fbc_reason;
enum i9xx_plane_id i9xx_plane;
unsigned int cfb_stride;
unsigned int cfb_size;
unsigned int fence_y_offset;
u16 override_cfb_stride;
u16 interval;
s8 fence_id;
};
struct intel_fbc {
struct drm_i915_private *i915;
const struct intel_fbc_funcs *funcs;
/* This is always the inner lock when overlapping with struct_mutex and
* it's the outer lock when overlapping with stolen_lock. */
struct mutex lock;
unsigned int possible_framebuffer_bits;
unsigned int busy_bits;
struct intel_plane *plane;
struct drm_mm_node compressed_fb;
struct drm_mm_node compressed_llb;
u8 limit;
bool false_color;
bool active;
bool activated;
bool flip_pending;
bool underrun_detected;
struct work_struct underrun_work;
/*
* Due to the atomic rules we can't access some structures without the
* appropriate locking, so we cache information here in order to avoid
* these problems.
*/
struct intel_fbc_state state_cache;
/*
* This structure contains everything that's relevant to program the
* hardware registers. When we want to figure out if we need to disable
* and re-enable FBC for a new configuration we just check if there's
* something different in the struct. The genx_fbc_activate functions
* are supposed to read from it in order to program the registers.
*/
struct intel_fbc_state params;
const char *no_fbc_reason;
};
/* /*
* HIGH_RR is the highest eDP panel refresh rate read from EDID * HIGH_RR is the highest eDP panel refresh rate read from EDID
* LOW_RR is the lowest eDP panel refresh rate found from EDID * LOW_RR is the lowest eDP panel refresh rate found from EDID
...@@ -472,7 +416,6 @@ struct i915_drrs { ...@@ -472,7 +416,6 @@ struct i915_drrs {
#define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8) #define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8)
struct intel_fbdev; struct intel_fbdev;
struct intel_fbc_work;
struct intel_gmbus { struct intel_gmbus {
struct i2c_adapter adapter; struct i2c_adapter adapter;
...@@ -808,7 +751,7 @@ struct drm_i915_private { ...@@ -808,7 +751,7 @@ struct drm_i915_private {
u32 pipestat_irq_mask[I915_MAX_PIPES]; u32 pipestat_irq_mask[I915_MAX_PIPES];
struct i915_hotplug hotplug; struct i915_hotplug hotplug;
struct intel_fbc fbc; struct intel_fbc *fbc;
struct i915_drrs drrs; struct i915_drrs drrs;
struct intel_opregion opregion; struct intel_opregion opregion;
struct intel_vbt_data vbt; struct intel_vbt_data vbt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment