aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-06-27 11:19:24 -0400
committerDave Airlie <airlied@redhat.com>2014-07-07 21:31:28 -0400
commit10a231026574f9ec9761b6435394b8830b485e4e (patch)
treeae55c7173758db2778f02bb98954e7efceee5ec0
parent3a4938799dec32783759b0c66ee3bb8c82dd9937 (diff)
drm: Introduce drm_fb_helper_prepare()
To implement hotplug detection in a race-free manner, drivers must call drm_kms_helper_poll_init() before hotplug events can be triggered. Such events can be triggered right after any of the encoders or connectors are initialized. At the same time, if the drm_fb_helper_hotplug_event() helper is used by a driver, then the poll helper requires some parts of the FB helper to be initialized to prevent a crash. At the same time, drm_fb_helper_init() requires information that is not necessarily available at such an early stage (number of CRTCs and connectors), so it cannot be used yet. Add a new helper, drm_fb_helper_prepare(), that initializes the bare minimum needed to allow drm_kms_helper_poll_init() to execute and any subsequent hotplug events to be processed properly. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c2
-rw-r--r--drivers/gpu/drm/ast/ast_fb.c4
-rw-r--r--drivers/gpu/drm/bochs/bochs_fbdev.c3
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c4
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c3
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c47
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c3
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c3
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c3
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_fb.c3
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c5
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c4
-rw-r--r--drivers/gpu/drm/tegra/fb.c4
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c3
-rw-r--r--include/drm/drm_fb_helper.h2
18 files changed, 72 insertions, 28 deletions
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index a7c947cd9386..7838e731b0de 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -149,7 +149,7 @@ int armada_fbdev_init(struct drm_device *dev)
149 149
150 priv->fbdev = fbh; 150 priv->fbdev = fbh;
151 151
152 fbh->funcs = &armada_fb_helper_funcs; 152 drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
153 153
154 ret = drm_fb_helper_init(dev, fbh, 1, 1); 154 ret = drm_fb_helper_init(dev, fbh, 1, 1);
155 if (ret) { 155 if (ret) {
diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
index 2113894e4ff8..cba45c774552 100644
--- a/drivers/gpu/drm/ast/ast_fb.c
+++ b/drivers/gpu/drm/ast/ast_fb.c
@@ -328,8 +328,10 @@ int ast_fbdev_init(struct drm_device *dev)
328 return -ENOMEM; 328 return -ENOMEM;
329 329
330 ast->fbdev = afbdev; 330 ast->fbdev = afbdev;
331 afbdev->helper.funcs = &ast_fb_helper_funcs;
332 spin_lock_init(&afbdev->dirty_lock); 331 spin_lock_init(&afbdev->dirty_lock);
332
333 drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
334
333 ret = drm_fb_helper_init(dev, &afbdev->helper, 335 ret = drm_fb_helper_init(dev, &afbdev->helper,
334 1, 1); 336 1, 1);
335 if (ret) { 337 if (ret) {
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 17e5c17f2730..19cf3e9413b6 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -189,7 +189,8 @@ int bochs_fbdev_init(struct bochs_device *bochs)
189{ 189{
190 int ret; 190 int ret;
191 191
192 bochs->fb.helper.funcs = &bochs_fb_helper_funcs; 192 drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
193 &bochs_fb_helper_funcs);
193 194
194 ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, 195 ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
195 1, 1); 196 1, 1);
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index 2bd0291168e4..2a135f253e29 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -306,9 +306,11 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)
306 return -ENOMEM; 306 return -ENOMEM;
307 307
308 cdev->mode_info.gfbdev = gfbdev; 308 cdev->mode_info.gfbdev = gfbdev;
309 gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
310 spin_lock_init(&gfbdev->dirty_lock); 309 spin_lock_init(&gfbdev->dirty_lock);
311 310
311 drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
312 &cirrus_fb_helper_funcs);
313
312 ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper, 314 ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
313 cdev->num_crtc, CIRRUSFB_CONN_LIMIT); 315 cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
314 if (ret) { 316 if (ret) {
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index cb01e1606384..cc0ae047ed3b 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -354,9 +354,10 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
354 return ERR_PTR(-ENOMEM); 354 return ERR_PTR(-ENOMEM);
355 } 355 }
356 356
357 fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs;
358 helper = &fbdev_cma->fb_helper; 357 helper = &fbdev_cma->fb_helper;
359 358
359 drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
360
360 ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count); 361 ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
361 if (ret < 0) { 362 if (ret < 0) {
362 dev_err(dev->dev, "Failed to initialize drm fb helper.\n"); 363 dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
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);
49 * helper functions used by many drivers to implement the kernel mode setting 49 * helper functions used by many drivers to implement the kernel mode setting
50 * interfaces. 50 * interfaces.
51 * 51 *
52 * Initialization is done as a three-step process with drm_fb_helper_init(), 52 * Initialization is done as a four-step process with drm_fb_helper_prepare(),
53 * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). 53 * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
54 * Drivers with fancier requirements than the default behaviour can override the 54 * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
55 * second step with their own code. Teardown is done with drm_fb_helper_fini(). 55 * default behaviour can override the third step with their own code.
56 * Teardown is done with drm_fb_helper_fini().
56 * 57 *
57 * At runtime drivers should restore the fbdev console by calling 58 * At runtime drivers should restore the fbdev console by calling
58 * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They 59 * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
@@ -63,6 +64,19 @@ static LIST_HEAD(kernel_fb_helper_list);
63 * 64 *
64 * All other functions exported by the fb helper library can be used to 65 * All other functions exported by the fb helper library can be used to
65 * implement the fbdev driver interface by the driver. 66 * implement the fbdev driver interface by the driver.
67 *
68 * It is possible, though perhaps somewhat tricky, to implement race-free
69 * hotplug detection using the fbdev helpers. The drm_fb_helper_prepare()
70 * helper must be called first to initialize the minimum required to make
71 * hotplug detection work. Drivers also need to make sure to properly set up
72 * the dev->mode_config.funcs member. After calling drm_kms_helper_poll_init()
73 * it is safe to enable interrupts and start processing hotplug events. At the
74 * same time, drivers should initialize all modeset objects such as CRTCs,
75 * encoders and connectors. To finish up the fbdev helper initialization, the
76 * drm_fb_helper_init() function is called. To probe for all attached displays
77 * and set up an initial configuration using the detected hardware, drivers
78 * should call drm_fb_helper_single_add_all_connectors() followed by
79 * drm_fb_helper_initial_config().
66 */ 80 */
67 81
68/** 82/**
@@ -528,6 +542,24 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
528} 542}
529 543
530/** 544/**
545 * drm_fb_helper_prepare - setup a drm_fb_helper structure
546 * @dev: DRM device
547 * @helper: driver-allocated fbdev helper structure to set up
548 * @funcs: pointer to structure of functions associate with this helper
549 *
550 * Sets up the bare minimum to make the framebuffer helper usable. This is
551 * useful to implement race-free initialization of the polling helpers.
552 */
553void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
554 const struct drm_fb_helper_funcs *funcs)
555{
556 INIT_LIST_HEAD(&helper->kernel_fb_list);
557 helper->funcs = funcs;
558 helper->dev = dev;
559}
560EXPORT_SYMBOL(drm_fb_helper_prepare);
561
562/**
531 * drm_fb_helper_init - initialize a drm_fb_helper structure 563 * drm_fb_helper_init - initialize a drm_fb_helper structure
532 * @dev: drm device 564 * @dev: drm device
533 * @fb_helper: driver-allocated fbdev helper structure to initialize 565 * @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)
539 * nor register the fbdev. This is only done in drm_fb_helper_initial_config() 571 * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
540 * to allow driver writes more control over the exact init sequence. 572 * to allow driver writes more control over the exact init sequence.
541 * 573 *
542 * Drivers must set fb_helper->funcs before calling 574 * Drivers must call drm_fb_helper_prepare() before calling this function.
543 * drm_fb_helper_initial_config().
544 * 575 *
545 * RETURNS: 576 * RETURNS:
546 * Zero if everything went ok, nonzero otherwise. 577 * Zero if everything went ok, nonzero otherwise.
@@ -555,10 +586,6 @@ int drm_fb_helper_init(struct drm_device *dev,
555 if (!max_conn_count) 586 if (!max_conn_count)
556 return -EINVAL; 587 return -EINVAL;
557 588
558 fb_helper->dev = dev;
559
560 INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
561
562 fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); 589 fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
563 if (!fb_helper->crtc_info) 590 if (!fb_helper->crtc_info)
564 return -ENOMEM; 591 return -ENOMEM;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index fc25fe75aa77..32e63f60e1d1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -266,7 +266,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
266 return -ENOMEM; 266 return -ENOMEM;
267 267
268 private->fb_helper = helper = &fbdev->drm_fb_helper; 268 private->fb_helper = helper = &fbdev->drm_fb_helper;
269 helper->funcs = &exynos_drm_fb_helper_funcs; 269
270 drm_fb_helper_prepare(dev, helper, &exynos_drm_fb_helper_funcs);
270 271
271 num_crtc = dev->mode_config.num_crtc; 272 num_crtc = dev->mode_config.num_crtc;
272 273
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 76e4d777d01d..d0dd3bea8aa5 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -600,7 +600,8 @@ int psb_fbdev_init(struct drm_device *dev)
600 } 600 }
601 601
602 dev_priv->fbdev = fbdev; 602 dev_priv->fbdev = fbdev;
603 fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs; 603
604 drm_fb_helper_prepare(dev, &fbdev->psb_fb_helper, &psb_fb_helper_funcs);
604 605
605 drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs, 606 drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
606 INTELFB_CONN_LIMIT); 607 INTELFB_CONN_LIMIT);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index c942d13cd5cb..347d16220cd0 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -623,7 +623,8 @@ int intel_fbdev_init(struct drm_device *dev)
623 if (ifbdev == NULL) 623 if (ifbdev == NULL)
624 return -ENOMEM; 624 return -ENOMEM;
625 625
626 ifbdev->helper.funcs = &intel_fb_helper_funcs; 626 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
627
627 if (!intel_fbdev_init_bios(dev, ifbdev)) 628 if (!intel_fbdev_init_bios(dev, ifbdev))
628 ifbdev->preferred_bpp = 32; 629 ifbdev->preferred_bpp = 32;
629 630
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
index a4319aba9180..5451dc58eff1 100644
--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
+++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
@@ -293,9 +293,10 @@ int mgag200_fbdev_init(struct mga_device *mdev)
293 return -ENOMEM; 293 return -ENOMEM;
294 294
295 mdev->mfbdev = mfbdev; 295 mdev->mfbdev = mfbdev;
296 mfbdev->helper.funcs = &mga_fb_helper_funcs;
297 spin_lock_init(&mfbdev->dirty_lock); 296 spin_lock_init(&mfbdev->dirty_lock);
298 297
298 drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs);
299
299 ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper, 300 ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
300 mdev->num_crtc, MGAG200FB_CONN_LIMIT); 301 mdev->num_crtc, MGAG200FB_CONN_LIMIT);
301 if (ret) 302 if (ret)
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 7e706c4cf033..c437065933e3 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -197,7 +197,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
197 197
198 helper = &fbdev->base; 198 helper = &fbdev->base;
199 199
200 helper->funcs = &msm_fb_helper_funcs; 200 drm_fb_helper_prepare(dev, helper, &msm_fb_helper_funcs);
201 201
202 ret = drm_fb_helper_init(dev, helper, 202 ret = drm_fb_helper_init(dev, helper,
203 priv->num_crtcs, priv->num_connectors); 203 priv->num_crtcs, priv->num_connectors);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 8e9c07b7fc89..afe706a20f97 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -464,7 +464,8 @@ nouveau_fbcon_init(struct drm_device *dev)
464 464
465 fbcon->dev = dev; 465 fbcon->dev = dev;
466 drm->fbcon = fbcon; 466 drm->fbcon = fbcon;
467 fbcon->helper.funcs = &nouveau_fbcon_helper_funcs; 467
468 drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
468 469
469 ret = drm_fb_helper_init(dev, &fbcon->helper, 470 ret = drm_fb_helper_init(dev, &fbcon->helper,
470 dev->mode_config.num_crtc, 4); 471 dev->mode_config.num_crtc, 4);
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index 4cb12083eb12..8436c6857cda 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -325,7 +325,7 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
325 325
326 helper = &fbdev->base; 326 helper = &fbdev->base;
327 327
328 helper->funcs = &omap_fb_helper_funcs; 328 drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
329 329
330 ret = drm_fb_helper_init(dev, helper, 330 ret = drm_fb_helper_init(dev, helper,
331 priv->num_crtcs, priv->num_connectors); 331 priv->num_crtcs, priv->num_connectors);
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index cf89614c72be..df567888bb1e 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -676,9 +676,12 @@ int qxl_fbdev_init(struct qxl_device *qdev)
676 676
677 qfbdev->qdev = qdev; 677 qfbdev->qdev = qdev;
678 qdev->mode_info.qfbdev = qfbdev; 678 qdev->mode_info.qfbdev = qfbdev;
679 qfbdev->helper.funcs = &qxl_fb_helper_funcs;
680 spin_lock_init(&qfbdev->delayed_ops_lock); 679 spin_lock_init(&qfbdev->delayed_ops_lock);
681 INIT_LIST_HEAD(&qfbdev->delayed_ops); 680 INIT_LIST_HEAD(&qfbdev->delayed_ops);
681
682 drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper,
683 &qxl_fb_helper_funcs);
684
682 ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper, 685 ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper,
683 qxl_num_crtc /* num_crtc - QXL supports just 1 */, 686 qxl_num_crtc /* num_crtc - QXL supports just 1 */,
684 QXLFB_CONN_LIMIT); 687 QXLFB_CONN_LIMIT);
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index ad97afdbc4c7..db598d712901 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -353,7 +353,9 @@ int radeon_fbdev_init(struct radeon_device *rdev)
353 353
354 rfbdev->rdev = rdev; 354 rfbdev->rdev = rdev;
355 rdev->mode_info.rfbdev = rfbdev; 355 rdev->mode_info.rfbdev = rfbdev;
356 rfbdev->helper.funcs = &radeon_fb_helper_funcs; 356
357 drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper,
358 &radeon_fb_helper_funcs);
357 359
358 ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper, 360 ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
359 rdev->num_crtc, 361 rdev->num_crtc,
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index f7cf47bf0afb..d5d53aa79ced 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -276,7 +276,6 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
276 unsigned int num_crtc, 276 unsigned int num_crtc,
277 unsigned int max_connectors) 277 unsigned int max_connectors)
278{ 278{
279 struct drm_fb_helper *helper;
280 struct tegra_fbdev *fbdev; 279 struct tegra_fbdev *fbdev;
281 int err; 280 int err;
282 281
@@ -286,8 +285,7 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
286 return ERR_PTR(-ENOMEM); 285 return ERR_PTR(-ENOMEM);
287 } 286 }
288 287
289 fbdev->base.funcs = &tegra_fb_helper_funcs; 288 drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
290 helper = &fbdev->base;
291 289
292 err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors); 290 err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
293 if (err < 0) { 291 if (err < 0) {
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 0647c8cc368b..d1da339843ca 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -583,7 +583,8 @@ int udl_fbdev_init(struct drm_device *dev)
583 return -ENOMEM; 583 return -ENOMEM;
584 584
585 udl->fbdev = ufbdev; 585 udl->fbdev = ufbdev;
586 ufbdev->helper.funcs = &udl_fb_helper_funcs; 586
587 drm_fb_helper_prepare(dev, &ufbdev->helper, &udl_fb_helper_funcs);
587 588
588 ret = drm_fb_helper_init(dev, &ufbdev->helper, 589 ret = drm_fb_helper_init(dev, &ufbdev->helper,
589 1, 1); 590 1, 1);
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index a47df7ca38e8..1cf587f1f927 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -97,6 +97,8 @@ struct drm_fb_helper {
97 bool delayed_hotplug; 97 bool delayed_hotplug;
98}; 98};
99 99
100void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
101 const struct drm_fb_helper_funcs *funcs);
100int drm_fb_helper_init(struct drm_device *dev, 102int drm_fb_helper_init(struct drm_device *dev,
101 struct drm_fb_helper *helper, int crtc_count, 103 struct drm_fb_helper *helper, int crtc_count,
102 int max_conn); 104 int max_conn);