diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/display/i9xx_plane.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_fbc.c | 148 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/display/skl_universal_plane.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 59 |
4 files changed, 113 insertions, 98 deletions
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 84f50c90728f..85950ff67609 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -125,7 +125,7 @@ static struct intel_fbc *i9xx_plane_fbc(struct drm_i915_private *dev_priv, enum i9xx_plane_id i9xx_plane) { if (i9xx_plane_has_fbc(dev_priv, i9xx_plane)) - return &dev_priv->fbc; + return dev_priv->fbc; else return NULL; } diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 9be8e7dcaab6..1daf4f7b5d80 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -59,6 +59,63 @@ struct intel_fbc_funcs { 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) { @@ -762,14 +819,16 @@ static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) 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) @@ -1319,9 +1378,9 @@ void intel_fbc_invalidate(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; if (origin == ORIGIN_FLIP || origin == ORIGIN_CURSOR_UPDATE) @@ -1340,9 +1399,9 @@ void intel_fbc_invalidate(struct drm_i915_private *i915, 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); @@ -1484,9 +1543,9 @@ void intel_fbc_update(struct intel_atomic_state *state, */ 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); @@ -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) { - 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); @@ -1524,9 +1582,9 @@ out: */ 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); @@ -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) { - 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 @@ -1621,6 +1679,34 @@ void intel_fbc_add_plane(struct intel_fbc *fbc, struct intel_plane *plane) 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 @@ -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) { - 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; @@ -1646,29 +1727,20 @@ void intel_fbc_init(struct drm_i915_private *i915) 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) @@ -1743,8 +1815,8 @@ static void intel_fbc_debugfs_add(struct intel_fbc *fbc) 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); } diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 253d69a08614..699672d49a32 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -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) { if (skl_plane_has_fbc(dev_priv, pipe, plane_id)) - return &dev_priv->fbc; + return dev_priv->fbc; else return NULL; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 493522ce9953..820e6e920d4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -378,64 +378,8 @@ struct drm_i915_display_funcs { 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 @@ -472,7 +416,6 @@ struct i915_drrs { #define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8) struct intel_fbdev; -struct intel_fbc_work; struct intel_gmbus { struct i2c_adapter adapter; @@ -808,7 +751,7 @@ struct drm_i915_private { 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; |