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 */
static unsigned int intel_fbc_plane_stride(const struct intel_plane_state *plane_state)
{
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;
mutex_lock(&fbc->lock);
__intel_fbc_cleanup_cfb(fbc);
mutex_unlock(&fbc->lock);
+
+ kfree(fbc);
}
static bool stride_is_valid(const struct intel_plane_state *plane_state)
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;
if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE)
void intel_fbc_flush(struct drm_i915_private *i915,
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;
mutex_lock(&fbc->lock);
*/
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;
mutex_lock(&fbc->lock);
static void intel_fbc_underrun_work_fn(struct work_struct *work)
{
- struct drm_i915_private *i915 =
- container_of(work, struct drm_i915_private, fbc.underrun_work);
- struct intel_fbc *fbc = &i915->fbc;
+ struct intel_fbc *fbc = container_of(work, typeof(*fbc), underrun_work);
+ struct drm_i915_private *i915 = fbc->i915;
mutex_lock(&fbc->lock);
*/
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;
cancel_work_sync(&fbc->underrun_work);
*/
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;
/* There's no guarantee that underrun_detected won't be set to true
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
* @i915: the i915 device
*/
void intel_fbc_init(struct drm_i915_private *i915)
{
- struct intel_fbc *fbc = &i915->fbc;
-
- fbc->i915 = i915;
- INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
- mutex_init(&fbc->lock);
- fbc->active = false;
+ struct intel_fbc *fbc;
if (!drm_mm_initialized(&i915->mm.stolen))
mkwrite_device_info(i915)->display.has_fbc = false;
drm_dbg_kms(&i915->drm, "Sanitized enable_fbc value: %d\n",
i915->params.enable_fbc);
- if (!HAS_FBC(i915)) {
- fbc->no_fbc_reason = "unsupported by this chipset";
+ if (!HAS_FBC(i915))
return;
- }
- 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;
+ fbc = intel_fbc_create(i915);
+ if (!fbc)
+ return;
/* 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
* matches the hardware state. */
if (intel_fbc_hw_is_active(fbc))
intel_fbc_hw_deactivate(fbc);
+
+ i915->fbc = fbc;
}
static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused)
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);
}
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 */
-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
* LOW_RR is the lowest eDP panel refresh rate found from EDID
#define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8)
struct intel_fbdev;
-struct intel_fbc_work;
struct intel_gmbus {
struct i2c_adapter adapter;
u32 pipestat_irq_mask[I915_MAX_PIPES];
struct i915_hotplug hotplug;
- struct intel_fbc fbc;
+ struct intel_fbc *fbc;
struct i915_drrs drrs;
struct intel_opregion opregion;
struct intel_vbt_data vbt;