diff options
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 47 |
1 files changed, 37 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 6cd687a20cd5..bdee6eb0b24a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -49,10 +49,11 @@ static LIST_HEAD(kernel_fb_helper_list); * helper functions used by many drivers to implement the kernel mode setting * interfaces. * - * Initialization is done as a three-step process with drm_fb_helper_init(), - * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). - * Drivers with fancier requirements than the default behaviour can override the - * second step with their own code. Teardown is done with drm_fb_helper_fini(). + * Initialization is done as a four-step process with drm_fb_helper_prepare(), + * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and + * drm_fb_helper_initial_config(). Drivers with fancier requirements than the + * default behaviour can override the third step with their own code. + * Teardown is done with drm_fb_helper_fini(). * * At runtime drivers should restore the fbdev console by calling * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They @@ -63,6 +64,19 @@ static LIST_HEAD(kernel_fb_helper_list); * * All other functions exported by the fb helper library can be used to * implement the fbdev driver interface by the driver. + * + * It is possible, though perhaps somewhat tricky, to implement race-free + * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare() + * helper must be called first to initialize the minimum required to make + * hotplug detection work. Drivers also need to make sure to properly set up + * the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init() + * it is safe to enable interrupts and start processing hotplug events. At the + * same time, drivers should initialize all modeset objects such as CRTCs, + * encoders and connectors. To finish up the fbdev helper initialization, the + * drm_fb_helper_init() function is called. To probe for all attached displays + * and set up an initial configuration using the detected hardware, drivers + * should call drm_fb_helper_single_add_all_connectors() followed by + * drm_fb_helper_initial_config(). */ /** @@ -528,6 +542,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) } /** + * drm_fb_helper_prepare - setup a drm_fb_helper structure + * @dev: DRM device + * @helper: driver-allocated fbdev helper structure to set up + * @funcs: pointer to structure of functions associate with this helper + * + * Sets up the bare minimum to make the framebuffer helper usable. This is + * useful to implement race-free initialization of the polling helpers. + */ +void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, + const struct drm_fb_helper_funcs *funcs) +{ + INIT_LIST_HEAD(&helper->kernel_fb_list); + helper->funcs = funcs; + helper->dev = dev; +} +EXPORT_SYMBOL(drm_fb_helper_prepare); + +/** * drm_fb_helper_init - initialize a drm_fb_helper structure * @dev: drm device * @fb_helper: driver-allocated fbdev helper structure to initialize @@ -539,8 +571,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) * nor register the fbdev. This is only done in drm_fb_helper_initial_config() * to allow driver writes more control over the exact init sequence. * - * Drivers must set fb_helper->funcs before calling - * drm_fb_helper_initial_config(). + * Drivers must call drm_fb_helper_prepare() before calling this function. * * RETURNS: * Zero if everything went ok, nonzero otherwise. @@ -555,10 +586,6 @@ int drm_fb_helper_init(struct drm_device *dev, if (!max_conn_count) return -EINVAL; - fb_helper->dev = dev; - - INIT_LIST_HEAD(&fb_helper->kernel_fb_list); - fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); if (!fb_helper->crtc_info) return -ENOMEM; |