aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fb_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c69
1 files changed, 56 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e56166334455..09919e8d67f9 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -150,6 +150,9 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
{
int err;
+ if (!fb_helper)
+ return 0;
+
mutex_lock(&fb_helper->lock);
err = __drm_fb_helper_add_one_connector(fb_helper, connector);
mutex_unlock(&fb_helper->lock);
@@ -161,7 +164,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
/**
* drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
* emulation helper
- * @fb_helper: fbdev initialized with drm_fb_helper_init
+ * @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL
*
* This functions adds all the available connectors for use with the given
* fb_helper. This is a separate step to allow drivers to freely assign
@@ -179,7 +182,7 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
struct drm_connector_list_iter conn_iter;
int i, ret = 0;
- if (!drm_fbdev_emulation)
+ if (!drm_fbdev_emulation || !fb_helper)
return 0;
mutex_lock(&fb_helper->lock);
@@ -245,6 +248,9 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
{
int err;
+ if (!fb_helper)
+ return 0;
+
mutex_lock(&fb_helper->lock);
err = __drm_fb_helper_remove_one_connector(fb_helper, connector);
mutex_unlock(&fb_helper->lock);
@@ -484,7 +490,7 @@ static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
/**
* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
- * @fb_helper: fbcon to restore
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
*
* This should be called from driver's drm &drm_driver.lastclose callback
* when implementing an fbcon on top of kms using this helper. This ensures that
@@ -498,7 +504,7 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
bool do_delayed;
int ret;
- if (!drm_fbdev_emulation)
+ if (!drm_fbdev_emulation || !fb_helper)
return -ENODEV;
if (READ_ONCE(fb_helper->deferred_setup))
@@ -793,8 +799,10 @@ int drm_fb_helper_init(struct drm_device *dev,
struct drm_mode_config *config = &dev->mode_config;
int i;
- if (!drm_fbdev_emulation)
+ if (!drm_fbdev_emulation) {
+ dev->fb_helper = fb_helper;
return 0;
+ }
if (!max_conn_count)
return -EINVAL;
@@ -829,6 +837,8 @@ int drm_fb_helper_init(struct drm_device *dev,
i++;
}
+ dev->fb_helper = fb_helper;
+
return 0;
out_free:
drm_fb_helper_crtc_free(fb_helper);
@@ -883,7 +893,7 @@ EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
/**
* drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
*
* A wrapper around unregister_framebuffer, to release the fb_info
* framebuffer device. This must be called before releasing all resources for
@@ -898,7 +908,7 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
/**
* drm_fb_helper_fini - finialize a &struct drm_fb_helper
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
*
* This cleans up all remaining resources associated with @fb_helper. Must be
* called after drm_fb_helper_unlink_fbi() was called.
@@ -907,7 +917,12 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{
struct fb_info *info;
- if (!drm_fbdev_emulation || !fb_helper)
+ if (!fb_helper)
+ return;
+
+ fb_helper->dev->fb_helper = NULL;
+
+ if (!drm_fbdev_emulation)
return;
cancel_work_sync(&fb_helper->resume_work);
@@ -937,7 +952,7 @@ EXPORT_SYMBOL(drm_fb_helper_fini);
/**
* drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
*
* A wrapper around unlink_framebuffer implemented by fbdev core
*/
@@ -1138,7 +1153,7 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
/**
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
* @suspend: whether to suspend or resume
*
* A wrapper around fb_set_suspend implemented by fbdev core.
@@ -1155,7 +1170,7 @@ EXPORT_SYMBOL(drm_fb_helper_set_suspend);
/**
* drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
* takes the console lock
- * @fb_helper: driver-allocated fbdev helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
* @suspend: whether to suspend or resume
*
* A wrapper around fb_set_suspend() that takes the console lock. If the lock
@@ -2576,7 +2591,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
/**
* drm_fb_helper_hotplug_event - respond to a hotplug notification by
* probing all the outputs attached to the fb
- * @fb_helper: the drm_fb_helper
+ * @fb_helper: driver-allocated fbdev helper, can be NULL
*
* Scan the connectors attached to the fb_helper and try to put together a
* setup after notification of a change in output configuration.
@@ -2598,7 +2613,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
{
int err = 0;
- if (!drm_fbdev_emulation)
+ if (!drm_fbdev_emulation || !fb_helper)
return 0;
mutex_lock(&fb_helper->lock);
@@ -2626,6 +2641,34 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
}
EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
+/**
+ * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
+ * @dev: DRM device
+ *
+ * This function can be used as the &drm_driver->lastclose callback for drivers
+ * that only need to call drm_fb_helper_restore_fbdev_mode_unlocked().
+ */
+void drm_fb_helper_lastclose(struct drm_device *dev)
+{
+ drm_fb_helper_restore_fbdev_mode_unlocked(dev->fb_helper);
+}
+EXPORT_SYMBOL(drm_fb_helper_lastclose);
+
+/**
+ * drm_fb_helper_output_poll_changed - DRM mode config \.output_poll_changed
+ * helper for fbdev emulation
+ * @dev: DRM device
+ *
+ * This function can be used as the
+ * &drm_mode_config_funcs.output_poll_changed callback for drivers that only
+ * need to call drm_fb_helper_hotplug_event().
+ */
+void drm_fb_helper_output_poll_changed(struct drm_device *dev)
+{
+ drm_fb_helper_hotplug_event(dev->fb_helper);
+}
+EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
+
/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
* but the module doesn't depend on any fb console symbols. At least
* attempt to load fbcon to avoid leaving the system without a usable console.