summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbdev.c28
-rw-r--r--include/drm/drm_fb_helper.h14
3 files changed, 38 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 87bb25648d929..0703fddd750f0 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -757,7 +757,12 @@ EXPORT_SYMBOL(drm_fb_helper_deferred_io);
*/
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend)
{
- if (fb_helper && fb_helper->info)
+ if (!fb_helper || !fb_helper->info)
+ return;
+
+ if (fb_helper->funcs->fb_set_suspend)
+ fb_helper->funcs->fb_set_suspend(fb_helper, suspend);
+ else
fb_set_suspend(fb_helper->info, suspend);
}
EXPORT_SYMBOL(drm_fb_helper_set_suspend);
@@ -803,7 +808,7 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
}
}
- fb_set_suspend(fb_helper->info, suspend);
+ drm_fb_helper_set_suspend(fb_helper, suspend);
console_unlock();
}
EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked);
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 408e44251c479..a99793723695f 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -285,10 +285,27 @@ static void intelfb_restore(struct drm_fb_helper *fb_helper)
intel_fbdev_invalidate(ifbdev);
}
+static void intelfb_set_suspend(struct drm_fb_helper *fb_helper, bool suspend)
+{
+ struct fb_info *info = fb_helper->info;
+
+ /*
+ * When resuming from hibernation, Linux restores the object's
+ * content from swap if the buffer is backed by shmemfs. If the
+ * object is stolen however, it will be full of whatever garbage
+ * was left in there. Clear it to zero in this case.
+ */
+ if (!suspend && !intel_bo_is_shmem(intel_fb_bo(fb_helper->fb)))
+ memset_io(info->screen_base, 0, info->screen_size);
+
+ fb_set_suspend(info, suspend);
+}
+
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.fb_probe = intelfb_create,
.fb_dirty = intelfb_dirty,
.fb_restore = intelfb_restore,
+ .fb_set_suspend = intelfb_set_suspend,
};
/*
@@ -457,7 +474,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
- struct fb_info *info;
if (!ifbdev)
return;
@@ -468,8 +484,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
if (!ifbdev->vma)
return;
- info = ifbdev->helper.info;
-
if (synchronous) {
/* Flush any pending work to turn the console on, and then
* wait to turn it off. It must be synchronous as we are
@@ -499,14 +513,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
}
}
- /* On resume from hibernation: If the object is shmemfs backed, it has
- * been restored from swap. If the object is stolen however, it will be
- * full of whatever garbage was left in there.
- */
- if (state == FBINFO_STATE_RUNNING &&
- !intel_bo_is_shmem(intel_fb_bo(&ifbdev->fb->base)))
- memset_io(info->screen_base, 0, info->screen_size);
-
drm_fb_helper_set_suspend(&ifbdev->helper, state);
console_unlock();
}
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index a7d7a3b945ea3..ddce2408ca2b5 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -112,6 +112,20 @@ struct drm_fb_helper_funcs {
* TODO: Fix i915 to not require this callback.
*/
void (*fb_restore)(struct drm_fb_helper *helper);
+
+ /**
+ * @fb_set_suspend:
+ *
+ * Driver callback to suspend or resume, if set, fbdev emulation will
+ * invoke this callback during suspend and resume. Driver should call
+ * fb_set_suspend() from their implementation. If not set, fbdev
+ * emulation will invoke fb_set_suspend() directly.
+ *
+ * Only for i915. Do not use in new code.
+ *
+ * TODO: Fix i915 to not require this callback.
+ */
+ void (*fb_set_suspend)(struct drm_fb_helper *helper, bool suspend);
};
/**