aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-12-17 19:10:14 -0500
committerDave Airlie <airlied@redhat.com>2017-12-17 19:10:14 -0500
commita942b3c2cddc4378482a427845d15c78eb50f4d4 (patch)
treea30297864a3cb7015abc3ec6ca2a9649ddf9daad /drivers
parent9428088c90b6f7d5edd2a1b0d742c75339b36f6e (diff)
parentca40cfc85e548424e39dc3aebe61873535ddf7b6 (diff)
Merge tag 'drm-misc-next-2017-12-14' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 4.16: Cross-subsystem Changes: - Documentation for amlogic dt dt-bindings Core Changes: - Update edid-derived drm_display_info fields at edid property set Driver Changes: - A bunch of clean up from Noralf, including the last patches to reduce fbdev emulation footprint. * tag 'drm-misc-next-2017-12-14' of git://anongit.freedesktop.org/drm/drm-misc: (30 commits) drm/atomic-helper: Make zpos property kerneldoc less misleading drm: Update edid-derived drm_display_info fields at edid property set [v2] MAINTAINERS: Remove Jani as drm-misc co-maintainer drm/tinydrm: Use drm_fb_cma_fbdev_init_with_funcs/fini() drm/arm/mali: Use drm_fb_cma_fbdev_init/fini() drm/zte: Use drm_fb_cma_fbdev_init/fini() drm/vc4: Use drm_fb_cma_fbdev_init/fini() drm/tve200: Use drm_fb_cma_fbdev_init/fini() drm/tilcdc: Use drm_fb_cma_fbdev_init/fini() drm/sun4i: Use drm_fb_cma_fbdev_init/fini() drm/stm: Use drm_fb_cma_fbdev_init/fini() drm/sti: Use drm_fb_cma_fbdev_init/fini() drm/pl111: Use drm_fb_cma_fbdev_init/fini() drm/imx: Use drm_fb_cma_fbdev_init/fini() drm/atmel-hlcdc: Use drm_fb_cma_fbdev_init/fini() drm/cma-helper: Add drm_fb_cma_fbdev_init/fini() drm/gem-fb-helper: drm_gem_fbdev_fb_create() make funcs optional drm/tegra: Use drm_fb_helper_lastclose() and _poll_changed() drm/rockchip: Use drm_fb_helper_lastclose() and _poll_changed() drm/omap: Use drm_fb_helper_lastclose() and _poll_changed() ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c39
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h1
-rw-r--r--drivers/gpu/drm/armada/armada_drm.h1
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c8
-rw-r--r--drivers/gpu/drm/armada/armada_fb.c11
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c8
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c26
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h2
-rw-r--r--drivers/gpu/drm/drm_blend.c8
-rw-r--r--drivers/gpu/drm/drm_connector.c13
-rw-r--r--drivers/gpu/drm/drm_edid.c53
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c119
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c6
-rw-r--r--drivers/gpu/drm/drm_mode_config.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c8
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fb.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.h2
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c9
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c15
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c33
-rw-r--r--drivers/gpu/drm/imx/imx-drm.h1
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c9
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.c13
-rw-r--r--drivers/gpu/drm/meson/meson_registers.h4
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c3
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c34
-rw-r--r--drivers/gpu/drm/pl111/pl111_drm.h1
-rw-r--r--drivers/gpu/drm/pl111/pl111_drv.c16
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c9
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c9
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c27
-rw-r--r--drivers/gpu/drm/sti/sti_drv.h1
-rw-r--r--drivers/gpu/drm/stm/drv.c38
-rw-r--r--drivers/gpu/drm/stm/ltdc.h1
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c14
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.h2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_framebuffer.c18
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_framebuffer.h2
-rw-r--r--drivers/gpu/drm/tegra/drm.c13
-rw-r--r--drivers/gpu/drm/tegra/drm.h4
-rw-r--r--drivers/gpu/drm/tegra/fb.c14
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c26
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h2
-rw-r--r--drivers/gpu/drm/tinydrm/core/tinydrm-core.c37
-rw-r--r--drivers/gpu/drm/tinydrm/ili9225.c3
-rw-r--r--drivers/gpu/drm/tinydrm/mi0283qt.c3
-rw-r--r--drivers/gpu/drm/tinydrm/st7586.c3
-rw-r--r--drivers/gpu/drm/tve200/tve200_drm.h1
-rw-r--r--drivers/gpu/drm/tve200/tve200_drv.c16
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c13
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h2
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c18
-rw-r--r--drivers/gpu/drm/zte/zx_drm_drv.c48
59 files changed, 302 insertions, 521 deletions
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index e080e31a8513..3d82712d8002 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -13,7 +13,6 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/component.h> 15#include <linux/component.h>
16#include <linux/console.h>
17#include <linux/of_device.h> 16#include <linux/of_device.h>
18#include <linux/of_graph.h> 17#include <linux/of_graph.h>
19#include <linux/of_reserved_mem.h> 18#include <linux/of_reserved_mem.h>
@@ -24,6 +23,7 @@
24#include <drm/drm_atomic_helper.h> 23#include <drm/drm_atomic_helper.h>
25#include <drm/drm_crtc.h> 24#include <drm/drm_crtc.h>
26#include <drm/drm_crtc_helper.h> 25#include <drm/drm_crtc_helper.h>
26#include <drm/drm_fb_helper.h>
27#include <drm/drm_fb_cma_helper.h> 27#include <drm/drm_fb_cma_helper.h>
28#include <drm/drm_gem_cma_helper.h> 28#include <drm/drm_gem_cma_helper.h>
29#include <drm/drm_gem_framebuffer_helper.h> 29#include <drm/drm_gem_framebuffer_helper.h>
@@ -183,13 +183,6 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm)
183 return (ret > 0) ? 0 : -ETIMEDOUT; 183 return (ret > 0) ? 0 : -ETIMEDOUT;
184} 184}
185 185
186static void malidp_output_poll_changed(struct drm_device *drm)
187{
188 struct malidp_drm *malidp = drm->dev_private;
189
190 drm_fbdev_cma_hotplug_event(malidp->fbdev);
191}
192
193static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state) 186static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
194{ 187{
195 struct drm_pending_vblank_event *event; 188 struct drm_pending_vblank_event *event;
@@ -252,7 +245,7 @@ static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
252 245
253static const struct drm_mode_config_funcs malidp_mode_config_funcs = { 246static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
254 .fb_create = drm_gem_fb_create, 247 .fb_create = drm_gem_fb_create,
255 .output_poll_changed = malidp_output_poll_changed, 248 .output_poll_changed = drm_fb_helper_output_poll_changed,
256 .atomic_check = drm_atomic_helper_check, 249 .atomic_check = drm_atomic_helper_check,
257 .atomic_commit = drm_atomic_helper_commit, 250 .atomic_commit = drm_atomic_helper_commit,
258}; 251};
@@ -317,19 +310,12 @@ static int malidp_irq_init(struct platform_device *pdev)
317 return 0; 310 return 0;
318} 311}
319 312
320static void malidp_lastclose(struct drm_device *drm)
321{
322 struct malidp_drm *malidp = drm->dev_private;
323
324 drm_fbdev_cma_restore_mode(malidp->fbdev);
325}
326
327DEFINE_DRM_GEM_CMA_FOPS(fops); 313DEFINE_DRM_GEM_CMA_FOPS(fops);
328 314
329static struct drm_driver malidp_driver = { 315static struct drm_driver malidp_driver = {
330 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | 316 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
331 DRIVER_PRIME, 317 DRIVER_PRIME,
332 .lastclose = malidp_lastclose, 318 .lastclose = drm_fb_helper_lastclose,
333 .gem_free_object_unlocked = drm_gem_cma_free_object, 319 .gem_free_object_unlocked = drm_gem_cma_free_object,
334 .gem_vm_ops = &drm_gem_cma_vm_ops, 320 .gem_vm_ops = &drm_gem_cma_vm_ops,
335 .dumb_create = drm_gem_cma_dumb_create, 321 .dumb_create = drm_gem_cma_dumb_create,
@@ -623,14 +609,9 @@ static int malidp_bind(struct device *dev)
623 609
624 drm_mode_config_reset(drm); 610 drm_mode_config_reset(drm);
625 611
626 malidp->fbdev = drm_fbdev_cma_init(drm, 32, 612 ret = drm_fb_cma_fbdev_init(drm, 32, 0);
627 drm->mode_config.num_connector); 613 if (ret)
628
629 if (IS_ERR(malidp->fbdev)) {
630 ret = PTR_ERR(malidp->fbdev);
631 malidp->fbdev = NULL;
632 goto fbdev_fail; 614 goto fbdev_fail;
633 }
634 615
635 drm_kms_helper_poll_init(drm); 616 drm_kms_helper_poll_init(drm);
636 617
@@ -641,10 +622,7 @@ static int malidp_bind(struct device *dev)
641 return 0; 622 return 0;
642 623
643register_fail: 624register_fail:
644 if (malidp->fbdev) { 625 drm_fb_cma_fbdev_fini(drm);
645 drm_fbdev_cma_fini(malidp->fbdev);
646 malidp->fbdev = NULL;
647 }
648 drm_kms_helper_poll_fini(drm); 626 drm_kms_helper_poll_fini(drm);
649fbdev_fail: 627fbdev_fail:
650 pm_runtime_get_sync(dev); 628 pm_runtime_get_sync(dev);
@@ -681,10 +659,7 @@ static void malidp_unbind(struct device *dev)
681 struct malidp_drm *malidp = drm->dev_private; 659 struct malidp_drm *malidp = drm->dev_private;
682 660
683 drm_dev_unregister(drm); 661 drm_dev_unregister(drm);
684 if (malidp->fbdev) { 662 drm_fb_cma_fbdev_fini(drm);
685 drm_fbdev_cma_fini(malidp->fbdev);
686 malidp->fbdev = NULL;
687 }
688 drm_kms_helper_poll_fini(drm); 663 drm_kms_helper_poll_fini(drm);
689 pm_runtime_get_sync(dev); 664 pm_runtime_get_sync(dev);
690 malidp_se_irq_fini(drm); 665 malidp_se_irq_fini(drm);
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index 70ed6aeccf05..e0d12c9fc6b8 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -20,7 +20,6 @@
20 20
21struct malidp_drm { 21struct malidp_drm {
22 struct malidp_hw_device *dev; 22 struct malidp_hw_device *dev;
23 struct drm_fbdev_cma *fbdev;
24 struct drm_crtc crtc; 23 struct drm_crtc crtc;
25 wait_queue_head_t wq; 24 wait_queue_head_t wq;
26 atomic_t config_valid; 25 atomic_t config_valid;
diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h
index b064879ecdbd..cc4c557c9f66 100644
--- a/drivers/gpu/drm/armada/armada_drm.h
+++ b/drivers/gpu/drm/armada/armada_drm.h
@@ -84,7 +84,6 @@ void armada_drm_queue_unref_work(struct drm_device *,
84extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs; 84extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs;
85 85
86int armada_fbdev_init(struct drm_device *); 86int armada_fbdev_init(struct drm_device *);
87void armada_fbdev_lastclose(struct drm_device *);
88void armada_fbdev_fini(struct drm_device *); 87void armada_fbdev_fini(struct drm_device *);
89 88
90int armada_overlay_plane_create(struct drm_device *, unsigned long); 89int armada_overlay_plane_create(struct drm_device *, unsigned long);
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e857b88a9799..4b11b6b52f1d 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -10,6 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/of_graph.h> 11#include <linux/of_graph.h>
12#include <drm/drm_crtc_helper.h> 12#include <drm/drm_crtc_helper.h>
13#include <drm/drm_fb_helper.h>
13#include <drm/drm_of.h> 14#include <drm/drm_of.h>
14#include "armada_crtc.h" 15#include "armada_crtc.h"
15#include "armada_drm.h" 16#include "armada_drm.h"
@@ -54,15 +55,10 @@ static struct drm_ioctl_desc armada_ioctls[] = {
54 DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl, 0), 55 DRM_IOCTL_DEF_DRV(ARMADA_GEM_PWRITE, armada_gem_pwrite_ioctl, 0),
55}; 56};
56 57
57static void armada_drm_lastclose(struct drm_device *dev)
58{
59 armada_fbdev_lastclose(dev);
60}
61
62DEFINE_DRM_GEM_FOPS(armada_drm_fops); 58DEFINE_DRM_GEM_FOPS(armada_drm_fops);
63 59
64static struct drm_driver armada_drm_driver = { 60static struct drm_driver armada_drm_driver = {
65 .lastclose = armada_drm_lastclose, 61 .lastclose = drm_fb_helper_lastclose,
66 .gem_free_object_unlocked = armada_gem_free_object, 62 .gem_free_object_unlocked = armada_gem_free_object,
67 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 63 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
68 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 64 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index a38d5a0892a9..ac92bce07ecd 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -154,16 +154,7 @@ static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
154 return ERR_PTR(ret); 154 return ERR_PTR(ret);
155} 155}
156 156
157static void armada_output_poll_changed(struct drm_device *dev)
158{
159 struct armada_private *priv = dev->dev_private;
160 struct drm_fb_helper *fbh = priv->fbdev;
161
162 if (fbh)
163 drm_fb_helper_hotplug_event(fbh);
164}
165
166const struct drm_mode_config_funcs armada_drm_mode_config_funcs = { 157const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
167 .fb_create = armada_fb_create, 158 .fb_create = armada_fb_create,
168 .output_poll_changed = armada_output_poll_changed, 159 .output_poll_changed = drm_fb_helper_output_poll_changed,
169}; 160};
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index a2ce83f84800..2a59db0994b2 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -159,14 +159,6 @@ int armada_fbdev_init(struct drm_device *dev)
159 return ret; 159 return ret;
160} 160}
161 161
162void armada_fbdev_lastclose(struct drm_device *dev)
163{
164 struct armada_private *priv = dev->dev_private;
165
166 if (priv->fbdev)
167 drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
168}
169
170void armada_fbdev_fini(struct drm_device *dev) 162void armada_fbdev_fini(struct drm_device *dev)
171{ 163{
172 struct armada_private *priv = dev->dev_private; 164 struct armada_private *priv = dev->dev_private;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index c6e8061ffcfc..c1ea5c36b006 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -461,13 +461,6 @@ static struct drm_framebuffer *atmel_hlcdc_fb_create(struct drm_device *dev,
461 return drm_gem_fb_create(dev, file_priv, mode_cmd); 461 return drm_gem_fb_create(dev, file_priv, mode_cmd);
462} 462}
463 463
464static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev)
465{
466 struct atmel_hlcdc_dc *dc = dev->dev_private;
467
468 drm_fbdev_cma_hotplug_event(dc->fbdev);
469}
470
471struct atmel_hlcdc_dc_commit { 464struct atmel_hlcdc_dc_commit {
472 struct work_struct work; 465 struct work_struct work;
473 struct drm_device *dev; 466 struct drm_device *dev;
@@ -563,7 +556,7 @@ error:
563 556
564static const struct drm_mode_config_funcs mode_config_funcs = { 557static const struct drm_mode_config_funcs mode_config_funcs = {
565 .fb_create = atmel_hlcdc_fb_create, 558 .fb_create = atmel_hlcdc_fb_create,
566 .output_poll_changed = atmel_hlcdc_fb_output_poll_changed, 559 .output_poll_changed = drm_fb_helper_output_poll_changed,
567 .atomic_check = drm_atomic_helper_check, 560 .atomic_check = drm_atomic_helper_check,
568 .atomic_commit = atmel_hlcdc_dc_atomic_commit, 561 .atomic_commit = atmel_hlcdc_dc_atomic_commit,
569}; 562};
@@ -665,10 +658,7 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
665 658
666 platform_set_drvdata(pdev, dev); 659 platform_set_drvdata(pdev, dev);
667 660
668 dc->fbdev = drm_fbdev_cma_init(dev, 24, 661 drm_fb_cma_fbdev_init(dev, 24, 0);
669 dev->mode_config.num_connector);
670 if (IS_ERR(dc->fbdev))
671 dc->fbdev = NULL;
672 662
673 drm_kms_helper_poll_init(dev); 663 drm_kms_helper_poll_init(dev);
674 664
@@ -688,8 +678,7 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
688{ 678{
689 struct atmel_hlcdc_dc *dc = dev->dev_private; 679 struct atmel_hlcdc_dc *dc = dev->dev_private;
690 680
691 if (dc->fbdev) 681 drm_fb_cma_fbdev_fini(dev);
692 drm_fbdev_cma_fini(dc->fbdev);
693 flush_workqueue(dc->wq); 682 flush_workqueue(dc->wq);
694 drm_kms_helper_poll_fini(dev); 683 drm_kms_helper_poll_fini(dev);
695 drm_mode_config_cleanup(dev); 684 drm_mode_config_cleanup(dev);
@@ -705,13 +694,6 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
705 destroy_workqueue(dc->wq); 694 destroy_workqueue(dc->wq);
706} 695}
707 696
708static void atmel_hlcdc_dc_lastclose(struct drm_device *dev)
709{
710 struct atmel_hlcdc_dc *dc = dev->dev_private;
711
712 drm_fbdev_cma_restore_mode(dc->fbdev);
713}
714
715static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev) 697static int atmel_hlcdc_dc_irq_postinstall(struct drm_device *dev)
716{ 698{
717 struct atmel_hlcdc_dc *dc = dev->dev_private; 699 struct atmel_hlcdc_dc *dc = dev->dev_private;
@@ -744,7 +726,7 @@ static struct drm_driver atmel_hlcdc_dc_driver = {
744 .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | 726 .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
745 DRIVER_MODESET | DRIVER_PRIME | 727 DRIVER_MODESET | DRIVER_PRIME |
746 DRIVER_ATOMIC, 728 DRIVER_ATOMIC,
747 .lastclose = atmel_hlcdc_dc_lastclose, 729 .lastclose = drm_fb_helper_lastclose,
748 .irq_handler = atmel_hlcdc_dc_irq_handler, 730 .irq_handler = atmel_hlcdc_dc_irq_handler,
749 .irq_preinstall = atmel_hlcdc_dc_irq_uninstall, 731 .irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
750 .irq_postinstall = atmel_hlcdc_dc_irq_postinstall, 732 .irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 6833ee253cfa..ab32d5b268d2 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -32,6 +32,7 @@
32#include <drm/drm_atomic_helper.h> 32#include <drm/drm_atomic_helper.h>
33#include <drm/drm_crtc.h> 33#include <drm/drm_crtc.h>
34#include <drm/drm_crtc_helper.h> 34#include <drm/drm_crtc_helper.h>
35#include <drm/drm_fb_helper.h>
35#include <drm/drm_fb_cma_helper.h> 36#include <drm/drm_fb_cma_helper.h>
36#include <drm/drm_gem_cma_helper.h> 37#include <drm/drm_gem_cma_helper.h>
37#include <drm/drm_gem_framebuffer_helper.h> 38#include <drm/drm_gem_framebuffer_helper.h>
@@ -374,7 +375,6 @@ struct atmel_hlcdc_dc {
374 const struct atmel_hlcdc_dc_desc *desc; 375 const struct atmel_hlcdc_dc_desc *desc;
375 struct dma_pool *dscrpool; 376 struct dma_pool *dscrpool;
376 struct atmel_hlcdc *hlcdc; 377 struct atmel_hlcdc *hlcdc;
377 struct drm_fbdev_cma *fbdev;
378 struct drm_crtc *crtc; 378 struct drm_crtc *crtc;
379 struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; 379 struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
380 struct workqueue_struct *wq; 380 struct workqueue_struct *wq;
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index 2e5e089dd912..4c62dff14893 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -214,9 +214,11 @@ EXPORT_SYMBOL(drm_rotation_simplify);
214 * This function initializes generic mutable zpos property and enables support 214 * This function initializes generic mutable zpos property and enables support
215 * for it in drm core. Drivers can then attach this property to planes to enable 215 * for it in drm core. Drivers can then attach this property to planes to enable
216 * support for configurable planes arrangement during blending operation. 216 * support for configurable planes arrangement during blending operation.
217 * Once mutable zpos property has been enabled, the DRM core will automatically 217 * Drivers that attach a mutable zpos property to any plane should call the
218 * calculate &drm_plane_state.normalized_zpos values. Usually min should be set 218 * drm_atomic_normalize_zpos() helper during their implementation of
219 * to 0 and max to maximal number of planes for given crtc - 1. 219 * &drm_mode_config_funcs.atomic_check(), which will update the normalized zpos
220 * values and store them in &drm_plane_state.normalized_zpos. Usually min
221 * should be set to 0 and max to maximal number of planes for given crtc - 1.
220 * 222 *
221 * If zpos of some planes cannot be changed (like fixed background or 223 * If zpos of some planes cannot be changed (like fixed background or
222 * cursor/topmost planes), driver should adjust min/max values and assign those 224 * cursor/topmost planes), driver should adjust min/max values and assign those
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 624edeb5c50d..0bc35545e86a 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1229,6 +1229,19 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
1229 if (edid) 1229 if (edid)
1230 size = EDID_LENGTH * (1 + edid->extensions); 1230 size = EDID_LENGTH * (1 + edid->extensions);
1231 1231
1232 /* Set the display info, using edid if available, otherwise
1233 * reseting the values to defaults. This duplicates the work
1234 * done in drm_add_edid_modes, but that function is not
1235 * consistently called before this one in all drivers and the
1236 * computation is cheap enough that it seems better to
1237 * duplicate it rather than attempt to ensure some arbitrary
1238 * ordering of calls.
1239 */
1240 if (edid)
1241 drm_add_display_info(connector, edid);
1242 else
1243 drm_reset_display_info(connector);
1244
1232 drm_object_property_set_value(&connector->base, 1245 drm_object_property_set_value(&connector->base,
1233 dev->mode_config.non_desktop_property, 1246 dev->mode_config.non_desktop_property,
1234 connector->display_info.non_desktop); 1247 connector->display_info.non_desktop);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 524eace3d460..365901c1c33c 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1731,7 +1731,7 @@ EXPORT_SYMBOL(drm_edid_duplicate);
1731 * 1731 *
1732 * Returns true if @vendor is in @edid, false otherwise 1732 * Returns true if @vendor is in @edid, false otherwise
1733 */ 1733 */
1734static bool edid_vendor(struct edid *edid, const char *vendor) 1734static bool edid_vendor(const struct edid *edid, const char *vendor)
1735{ 1735{
1736 char edid_vendor[3]; 1736 char edid_vendor[3];
1737 1737
@@ -1749,7 +1749,7 @@ static bool edid_vendor(struct edid *edid, const char *vendor)
1749 * 1749 *
1750 * This tells subsequent routines what fixes they need to apply. 1750 * This tells subsequent routines what fixes they need to apply.
1751 */ 1751 */
1752static u32 edid_get_quirks(struct edid *edid) 1752static u32 edid_get_quirks(const struct edid *edid)
1753{ 1753{
1754 const struct edid_quirk *quirk; 1754 const struct edid_quirk *quirk;
1755 int i; 1755 int i;
@@ -2813,7 +2813,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
2813/* 2813/*
2814 * Search EDID for CEA extension block. 2814 * Search EDID for CEA extension block.
2815 */ 2815 */
2816static u8 *drm_find_edid_extension(struct edid *edid, int ext_id) 2816static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id)
2817{ 2817{
2818 u8 *edid_ext = NULL; 2818 u8 *edid_ext = NULL;
2819 int i; 2819 int i;
@@ -2835,12 +2835,12 @@ static u8 *drm_find_edid_extension(struct edid *edid, int ext_id)
2835 return edid_ext; 2835 return edid_ext;
2836} 2836}
2837 2837
2838static u8 *drm_find_cea_extension(struct edid *edid) 2838static u8 *drm_find_cea_extension(const struct edid *edid)
2839{ 2839{
2840 return drm_find_edid_extension(edid, CEA_EXT); 2840 return drm_find_edid_extension(edid, CEA_EXT);
2841} 2841}
2842 2842
2843static u8 *drm_find_displayid_extension(struct edid *edid) 2843static u8 *drm_find_displayid_extension(const struct edid *edid)
2844{ 2844{
2845 return drm_find_edid_extension(edid, DISPLAYID_EXT); 2845 return drm_find_edid_extension(edid, DISPLAYID_EXT);
2846} 2846}
@@ -4378,7 +4378,7 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
4378} 4378}
4379 4379
4380static void drm_parse_cea_ext(struct drm_connector *connector, 4380static void drm_parse_cea_ext(struct drm_connector *connector,
4381 struct edid *edid) 4381 const struct edid *edid)
4382{ 4382{
4383 struct drm_display_info *info = &connector->display_info; 4383 struct drm_display_info *info = &connector->display_info;
4384 const u8 *edid_ext; 4384 const u8 *edid_ext;
@@ -4412,11 +4412,34 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
4412 } 4412 }
4413} 4413}
4414 4414
4415static void drm_add_display_info(struct drm_connector *connector, 4415/* A connector has no EDID information, so we've got no EDID to compute quirks from. Reset
4416 struct edid *edid, u32 quirks) 4416 * all of the values which would have been set from EDID
4417 */
4418void
4419drm_reset_display_info(struct drm_connector *connector)
4420{
4421 struct drm_display_info *info = &connector->display_info;
4422
4423 info->width_mm = 0;
4424 info->height_mm = 0;
4425
4426 info->bpc = 0;
4427 info->color_formats = 0;
4428 info->cea_rev = 0;
4429 info->max_tmds_clock = 0;
4430 info->dvi_dual = false;
4431 info->has_hdmi_infoframe = false;
4432
4433 info->non_desktop = 0;
4434}
4435EXPORT_SYMBOL_GPL(drm_reset_display_info);
4436
4437u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid)
4417{ 4438{
4418 struct drm_display_info *info = &connector->display_info; 4439 struct drm_display_info *info = &connector->display_info;
4419 4440
4441 u32 quirks = edid_get_quirks(edid);
4442
4420 info->width_mm = edid->width_cm * 10; 4443 info->width_mm = edid->width_cm * 10;
4421 info->height_mm = edid->height_cm * 10; 4444 info->height_mm = edid->height_cm * 10;
4422 4445
@@ -4430,11 +4453,13 @@ static void drm_add_display_info(struct drm_connector *connector,
4430 4453
4431 info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP); 4454 info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
4432 4455
4456 DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
4457
4433 if (edid->revision < 3) 4458 if (edid->revision < 3)
4434 return; 4459 return quirks;
4435 4460
4436 if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) 4461 if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
4437 return; 4462 return quirks;
4438 4463
4439 drm_parse_cea_ext(connector, edid); 4464 drm_parse_cea_ext(connector, edid);
4440 4465
@@ -4454,7 +4479,7 @@ static void drm_add_display_info(struct drm_connector *connector,
4454 4479
4455 /* Only defined for 1.4 with digital displays */ 4480 /* Only defined for 1.4 with digital displays */
4456 if (edid->revision < 4) 4481 if (edid->revision < 4)
4457 return; 4482 return quirks;
4458 4483
4459 switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { 4484 switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
4460 case DRM_EDID_DIGITAL_DEPTH_6: 4485 case DRM_EDID_DIGITAL_DEPTH_6:
@@ -4489,7 +4514,9 @@ static void drm_add_display_info(struct drm_connector *connector,
4489 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; 4514 info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
4490 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) 4515 if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
4491 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; 4516 info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
4517 return quirks;
4492} 4518}
4519EXPORT_SYMBOL_GPL(drm_add_display_info);
4493 4520
4494static int validate_displayid(u8 *displayid, int length, int idx) 4521static int validate_displayid(u8 *displayid, int length, int idx)
4495{ 4522{
@@ -4645,8 +4672,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
4645 return 0; 4672 return 0;
4646 } 4673 }
4647 4674
4648 quirks = edid_get_quirks(edid);
4649
4650 drm_edid_to_eld(connector, edid); 4675 drm_edid_to_eld(connector, edid);
4651 4676
4652 /* 4677 /*
@@ -4654,7 +4679,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
4654 * To avoid multiple parsing of same block, lets parse that map 4679 * To avoid multiple parsing of same block, lets parse that map
4655 * from sink info, before parsing CEA modes. 4680 * from sink info, before parsing CEA modes.
4656 */ 4681 */
4657 drm_add_display_info(connector, edid, quirks); 4682 quirks = drm_add_display_info(connector, edid);
4658 4683
4659 /* 4684 /*
4660 * EDID spec says modes should be preferred in this order: 4685 * EDID spec says modes should be preferred in this order:
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 35b56dfba929..186d00adfb5f 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -23,6 +23,7 @@
23#include <drm/drm_gem_cma_helper.h> 23#include <drm/drm_gem_cma_helper.h>
24#include <drm/drm_gem_framebuffer_helper.h> 24#include <drm/drm_gem_framebuffer_helper.h>
25#include <drm/drm_fb_cma_helper.h> 25#include <drm/drm_fb_cma_helper.h>
26#include <drm/drm_print.h>
26#include <linux/module.h> 27#include <linux/module.h>
27 28
28#define DEFAULT_FBDEFIO_DELAY_MS 50 29#define DEFAULT_FBDEFIO_DELAY_MS 50
@@ -42,7 +43,7 @@ struct drm_fbdev_cma {
42 * callback function to create a cma backed framebuffer. 43 * callback function to create a cma backed framebuffer.
43 * 44 *
44 * An fbdev framebuffer backed by cma is also available by calling 45 * An fbdev framebuffer backed by cma is also available by calling
45 * drm_fbdev_cma_init(). drm_fbdev_cma_fini() tears it down. 46 * drm_fb_cma_fbdev_init(). drm_fb_cma_fbdev_fini() tears it down.
46 * If the &drm_framebuffer_funcs.dirty callback is set, fb_deferred_io will be 47 * If the &drm_framebuffer_funcs.dirty callback is set, fb_deferred_io will be
47 * set up automatically. &drm_framebuffer_funcs.dirty is called by 48 * set up automatically. &drm_framebuffer_funcs.dirty is called by
48 * drm_fb_helper_deferred_io() in process context (&struct delayed_work). 49 * drm_fb_helper_deferred_io() in process context (&struct delayed_work).
@@ -68,7 +69,7 @@ struct drm_fbdev_cma {
68 * 69 *
69 * Initialize:: 70 * Initialize::
70 * 71 *
71 * fbdev = drm_fbdev_cma_init_with_funcs(dev, 16, 72 * fbdev = drm_fb_cma_fbdev_init_with_funcs(dev, 16,
72 * dev->mode_config.num_crtc, 73 * dev->mode_config.num_crtc,
73 * dev->mode_config.num_connector, 74 * dev->mode_config.num_connector,
74 * &driver_fb_funcs); 75 * &driver_fb_funcs);
@@ -256,7 +257,7 @@ drm_fbdev_cma_create(struct drm_fb_helper *helper,
256 fbi->screen_size = size; 257 fbi->screen_size = size;
257 fbi->fix.smem_len = size; 258 fbi->fix.smem_len = size;
258 259
259 if (fbdev_cma->fb_funcs->dirty) { 260 if (fb->funcs->dirty) {
260 ret = drm_fbdev_cma_defio_init(fbi, obj); 261 ret = drm_fbdev_cma_defio_init(fbi, obj);
261 if (ret) 262 if (ret)
262 goto err_cma_destroy; 263 goto err_cma_destroy;
@@ -278,6 +279,118 @@ static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
278}; 279};
279 280
280/** 281/**
282 * drm_fb_cma_fbdev_init_with_funcs() - Allocate and initialize fbdev emulation
283 * @dev: DRM device
284 * @preferred_bpp: Preferred bits per pixel for the device.
285 * @dev->mode_config.preferred_depth is used if this is zero.
286 * @max_conn_count: Maximum number of connectors.
287 * @dev->mode_config.num_connector is used if this is zero.
288 * @funcs: Framebuffer functions, in particular a custom dirty() callback.
289 * Can be NULL.
290 *
291 * Returns:
292 * Zero on success or negative error code on failure.
293 */
294int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev,
295 unsigned int preferred_bpp, unsigned int max_conn_count,
296 const struct drm_framebuffer_funcs *funcs)
297{
298 struct drm_fbdev_cma *fbdev_cma;
299 struct drm_fb_helper *fb_helper;
300 int ret;
301
302 if (!preferred_bpp)
303 preferred_bpp = dev->mode_config.preferred_depth;
304 if (!preferred_bpp)
305 preferred_bpp = 32;
306
307 if (!max_conn_count)
308 max_conn_count = dev->mode_config.num_connector;
309
310 fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
311 if (!fbdev_cma)
312 return -ENOMEM;
313
314 fbdev_cma->fb_funcs = funcs;
315 fb_helper = &fbdev_cma->fb_helper;
316
317 drm_fb_helper_prepare(dev, fb_helper, &drm_fb_cma_helper_funcs);
318
319 ret = drm_fb_helper_init(dev, fb_helper, max_conn_count);
320 if (ret < 0) {
321 DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper.\n");
322 goto err_free;
323 }
324
325 ret = drm_fb_helper_single_add_all_connectors(fb_helper);
326 if (ret < 0) {
327 DRM_DEV_ERROR(dev->dev, "Failed to add connectors.\n");
328 goto err_drm_fb_helper_fini;
329 }
330
331 ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp);
332 if (ret < 0) {
333 DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration.\n");
334 goto err_drm_fb_helper_fini;
335 }
336
337 return 0;
338
339err_drm_fb_helper_fini:
340 drm_fb_helper_fini(fb_helper);
341err_free:
342 kfree(fbdev_cma);
343
344 return ret;
345}
346EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init_with_funcs);
347
348/**
349 * drm_fb_cma_fbdev_init() - Allocate and initialize fbdev emulation
350 * @dev: DRM device
351 * @preferred_bpp: Preferred bits per pixel for the device.
352 * @dev->mode_config.preferred_depth is used if this is zero.
353 * @max_conn_count: Maximum number of connectors.
354 * @dev->mode_config.num_connector is used if this is zero.
355 *
356 * Returns:
357 * Zero on success or negative error code on failure.
358 */
359int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
360 unsigned int max_conn_count)
361{
362 return drm_fb_cma_fbdev_init_with_funcs(dev, preferred_bpp,
363 max_conn_count, NULL);
364}
365EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_init);
366
367/**
368 * drm_fb_cma_fbdev_fini() - Teardown fbdev emulation
369 * @dev: DRM device
370 */
371void drm_fb_cma_fbdev_fini(struct drm_device *dev)
372{
373 struct drm_fb_helper *fb_helper = dev->fb_helper;
374
375 if (!fb_helper)
376 return;
377
378 /* Unregister if it hasn't been done already */
379 if (fb_helper->fbdev && fb_helper->fbdev->dev)
380 drm_fb_helper_unregister_fbi(fb_helper);
381
382 if (fb_helper->fbdev)
383 drm_fbdev_cma_defio_fini(fb_helper->fbdev);
384
385 if (fb_helper->fb)
386 drm_framebuffer_remove(fb_helper->fb);
387
388 drm_fb_helper_fini(fb_helper);
389 kfree(to_fbdev_cma(fb_helper));
390}
391EXPORT_SYMBOL_GPL(drm_fb_cma_fbdev_fini);
392
393/**
281 * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct 394 * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct
282 * @dev: DRM device 395 * @dev: DRM device
283 * @preferred_bpp: Preferred bits per pixel for the device 396 * @preferred_bpp: Preferred bits per pixel for the device
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index aa8cb9bfa499..4d682a6e8bcb 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -272,7 +272,8 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb);
272 * @sizes: fbdev size description 272 * @sizes: fbdev size description
273 * @pitch_align: Optional pitch alignment 273 * @pitch_align: Optional pitch alignment
274 * @obj: GEM object backing the framebuffer 274 * @obj: GEM object backing the framebuffer
275 * @funcs: vtable to be used for the new framebuffer object 275 * @funcs: Optional vtable to be used for the new framebuffer object when the
276 * dirty callback is needed.
276 * 277 *
277 * This function creates a framebuffer from a &drm_fb_helper_surface_size 278 * This function creates a framebuffer from a &drm_fb_helper_surface_size
278 * description for use in the &drm_fb_helper_funcs.fb_probe callback. 279 * description for use in the &drm_fb_helper_funcs.fb_probe callback.
@@ -300,6 +301,9 @@ drm_gem_fbdev_fb_create(struct drm_device *dev,
300 if (obj->size < mode_cmd.pitches[0] * mode_cmd.height) 301 if (obj->size < mode_cmd.pitches[0] * mode_cmd.height)
301 return ERR_PTR(-EINVAL); 302 return ERR_PTR(-EINVAL);
302 303
304 if (!funcs)
305 funcs = &drm_gem_fb_funcs;
306
303 return drm_gem_fb_alloc(dev, &mode_cmd, &obj, 1, funcs); 307 return drm_gem_fb_alloc(dev, &mode_cmd, &obj, 1, funcs);
304} 308}
305EXPORT_SYMBOL(drm_gem_fbdev_fb_create); 309EXPORT_SYMBOL(drm_gem_fbdev_fb_create);
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index cda8bfab6d3b..bc5c46306b3d 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -467,6 +467,9 @@ void drm_mode_config_cleanup(struct drm_device *dev)
467 */ 467 */
468 WARN_ON(!list_empty(&dev->mode_config.fb_list)); 468 WARN_ON(!list_empty(&dev->mode_config.fb_list));
469 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { 469 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
470 struct drm_printer p = drm_debug_printer("[leaked fb]");
471 drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
472 drm_framebuffer_print_info(&p, 1, fb);
470 drm_framebuffer_free(&fb->base.refcount); 473 drm_framebuffer_free(&fb->base.refcount);
471 } 474 }
472 475
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 82b72425a42f..2f2bd6e37e62 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -16,6 +16,7 @@
16#include <drm/drm_atomic.h> 16#include <drm/drm_atomic.h>
17#include <drm/drm_atomic_helper.h> 17#include <drm/drm_atomic_helper.h>
18#include <drm/drm_crtc_helper.h> 18#include <drm/drm_crtc_helper.h>
19#include <drm/drm_fb_helper.h>
19 20
20#include <linux/component.h> 21#include <linux/component.h>
21 22
@@ -89,11 +90,6 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
89 file->driver_priv = NULL; 90 file->driver_priv = NULL;
90} 91}
91 92
92static void exynos_drm_lastclose(struct drm_device *dev)
93{
94 exynos_drm_fbdev_restore_mode(dev);
95}
96
97static const struct vm_operations_struct exynos_drm_gem_vm_ops = { 93static const struct vm_operations_struct exynos_drm_gem_vm_ops = {
98 .fault = exynos_drm_gem_fault, 94 .fault = exynos_drm_gem_fault,
99 .open = drm_gem_vm_open, 95 .open = drm_gem_vm_open,
@@ -140,7 +136,7 @@ static struct drm_driver exynos_drm_driver = {
140 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME 136 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
141 | DRIVER_ATOMIC | DRIVER_RENDER, 137 | DRIVER_ATOMIC | DRIVER_RENDER,
142 .open = exynos_drm_open, 138 .open = exynos_drm_open,
143 .lastclose = exynos_drm_lastclose, 139 .lastclose = drm_fb_helper_lastclose,
144 .postclose = exynos_drm_postclose, 140 .postclose = exynos_drm_postclose,
145 .gem_free_object_unlocked = exynos_drm_gem_free_object, 141 .gem_free_object_unlocked = exynos_drm_gem_free_object,
146 .gem_vm_ops = &exynos_drm_gem_vm_ops, 142 .gem_vm_ops = &exynos_drm_gem_vm_ops,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c
index 8208df56a88f..0faaf829f5bf 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fb.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c
@@ -205,7 +205,7 @@ static struct drm_mode_config_helper_funcs exynos_drm_mode_config_helpers = {
205 205
206static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { 206static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
207 .fb_create = exynos_user_fb_create, 207 .fb_create = exynos_user_fb_create,
208 .output_poll_changed = exynos_drm_output_poll_changed, 208 .output_poll_changed = drm_fb_helper_output_poll_changed,
209 .atomic_check = exynos_atomic_check, 209 .atomic_check = exynos_atomic_check,
210 .atomic_commit = drm_atomic_helper_commit, 210 .atomic_commit = drm_atomic_helper_commit,
211}; 211};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index dfb66ecf417b..132dd52d0ac7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -270,24 +270,6 @@ void exynos_drm_fbdev_fini(struct drm_device *dev)
270 private->fb_helper = NULL; 270 private->fb_helper = NULL;
271} 271}
272 272
273void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
274{
275 struct exynos_drm_private *private = dev->dev_private;
276
277 if (!private || !private->fb_helper)
278 return;
279
280 drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper);
281}
282
283void exynos_drm_output_poll_changed(struct drm_device *dev)
284{
285 struct exynos_drm_private *private = dev->dev_private;
286 struct drm_fb_helper *fb_helper = private->fb_helper;
287
288 drm_fb_helper_hotplug_event(fb_helper);
289}
290
291void exynos_drm_fbdev_suspend(struct drm_device *dev) 273void exynos_drm_fbdev_suspend(struct drm_device *dev)
292{ 274{
293 struct exynos_drm_private *private = dev->dev_private; 275 struct exynos_drm_private *private = dev->dev_private;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
index 645d1bb7f665..b33847223a85 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
@@ -19,8 +19,6 @@
19 19
20int exynos_drm_fbdev_init(struct drm_device *dev); 20int exynos_drm_fbdev_init(struct drm_device *dev);
21void exynos_drm_fbdev_fini(struct drm_device *dev); 21void exynos_drm_fbdev_fini(struct drm_device *dev);
22void exynos_drm_fbdev_restore_mode(struct drm_device *dev);
23void exynos_drm_output_poll_changed(struct drm_device *dev);
24void exynos_drm_fbdev_suspend(struct drm_device *drm); 22void exynos_drm_fbdev_suspend(struct drm_device *drm);
25void exynos_drm_fbdev_resume(struct drm_device *drm); 23void exynos_drm_fbdev_resume(struct drm_device *drm);
26 24
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 2570c7f647a6..cb0a2ae916e0 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -576,13 +576,6 @@ static void psb_fbdev_fini(struct drm_device *dev)
576 dev_priv->fbdev = NULL; 576 dev_priv->fbdev = NULL;
577} 577}
578 578
579static void psbfb_output_poll_changed(struct drm_device *dev)
580{
581 struct drm_psb_private *dev_priv = dev->dev_private;
582 struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
583 drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
584}
585
586/** 579/**
587 * psb_user_framebuffer_create_handle - add hamdle to a framebuffer 580 * psb_user_framebuffer_create_handle - add hamdle to a framebuffer
588 * @fb: framebuffer 581 * @fb: framebuffer
@@ -623,7 +616,7 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
623 616
624static const struct drm_mode_config_funcs psb_mode_funcs = { 617static const struct drm_mode_config_funcs psb_mode_funcs = {
625 .fb_create = psb_user_framebuffer_create, 618 .fb_create = psb_user_framebuffer_create,
626 .output_poll_changed = psbfb_output_poll_changed, 619 .output_poll_changed = drm_fb_helper_output_poll_changed,
627}; 620};
628 621
629static void psb_setup_outputs(struct drm_device *dev) 622static void psb_setup_outputs(struct drm_device *dev)
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 8f5cc1f471cd..38d09d4b3ed5 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -107,19 +107,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
107static const struct drm_ioctl_desc psb_ioctls[] = { 107static const struct drm_ioctl_desc psb_ioctls[] = {
108}; 108};
109 109
110static void psb_driver_lastclose(struct drm_device *dev)
111{
112 int ret;
113 struct drm_psb_private *dev_priv = dev->dev_private;
114 struct psb_fbdev *fbdev = dev_priv->fbdev;
115
116 ret = drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->psb_fb_helper);
117 if (ret)
118 DRM_DEBUG("failed to restore crtc mode\n");
119
120 return;
121}
122
123static int psb_do_init(struct drm_device *dev) 110static int psb_do_init(struct drm_device *dev)
124{ 111{
125 struct drm_psb_private *dev_priv = dev->dev_private; 112 struct drm_psb_private *dev_priv = dev->dev_private;
@@ -479,7 +466,7 @@ static struct drm_driver driver = {
479 DRIVER_MODESET | DRIVER_GEM, 466 DRIVER_MODESET | DRIVER_GEM,
480 .load = psb_driver_load, 467 .load = psb_driver_load,
481 .unload = psb_driver_unload, 468 .unload = psb_driver_unload,
482 .lastclose = psb_driver_lastclose, 469 .lastclose = drm_fb_helper_lastclose,
483 470
484 .num_ioctls = ARRAY_SIZE(psb_ioctls), 471 .num_ioctls = ARRAY_SIZE(psb_ioctls),
485 .irq_preinstall = psb_irq_preinstall, 472 .irq_preinstall = psb_irq_preinstall,
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 17d2f3a1c562..3f2b4afcb8a7 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -38,7 +38,6 @@
38struct imx_drm_device { 38struct imx_drm_device {
39 struct drm_device *drm; 39 struct drm_device *drm;
40 unsigned int pipes; 40 unsigned int pipes;
41 struct drm_fbdev_cma *fbhelper;
42 struct drm_atomic_state *state; 41 struct drm_atomic_state *state;
43}; 42};
44 43
@@ -47,13 +46,6 @@ static int legacyfb_depth = 16;
47module_param(legacyfb_depth, int, 0444); 46module_param(legacyfb_depth, int, 0444);
48#endif 47#endif
49 48
50static void imx_drm_driver_lastclose(struct drm_device *drm)
51{
52 struct imx_drm_device *imxdrm = drm->dev_private;
53
54 drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
55}
56
57DEFINE_DRM_GEM_CMA_FOPS(imx_drm_driver_fops); 49DEFINE_DRM_GEM_CMA_FOPS(imx_drm_driver_fops);
58 50
59void imx_drm_connector_destroy(struct drm_connector *connector) 51void imx_drm_connector_destroy(struct drm_connector *connector)
@@ -69,13 +61,6 @@ void imx_drm_encoder_destroy(struct drm_encoder *encoder)
69} 61}
70EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy); 62EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
71 63
72static void imx_drm_output_poll_changed(struct drm_device *drm)
73{
74 struct imx_drm_device *imxdrm = drm->dev_private;
75
76 drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
77}
78
79static int imx_drm_atomic_check(struct drm_device *dev, 64static int imx_drm_atomic_check(struct drm_device *dev,
80 struct drm_atomic_state *state) 65 struct drm_atomic_state *state)
81{ 66{
@@ -107,7 +92,7 @@ static int imx_drm_atomic_check(struct drm_device *dev,
107 92
108static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { 93static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
109 .fb_create = drm_gem_fb_create, 94 .fb_create = drm_gem_fb_create,
110 .output_poll_changed = imx_drm_output_poll_changed, 95 .output_poll_changed = drm_fb_helper_output_poll_changed,
111 .atomic_check = imx_drm_atomic_check, 96 .atomic_check = imx_drm_atomic_check,
112 .atomic_commit = drm_atomic_helper_commit, 97 .atomic_commit = drm_atomic_helper_commit,
113}; 98};
@@ -186,7 +171,7 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = {
186static struct drm_driver imx_drm_driver = { 171static struct drm_driver imx_drm_driver = {
187 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | 172 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
188 DRIVER_ATOMIC, 173 DRIVER_ATOMIC,
189 .lastclose = imx_drm_driver_lastclose, 174 .lastclose = drm_fb_helper_lastclose,
190 .gem_free_object_unlocked = drm_gem_cma_free_object, 175 .gem_free_object_unlocked = drm_gem_cma_free_object,
191 .gem_vm_ops = &drm_gem_cma_vm_ops, 176 .gem_vm_ops = &drm_gem_cma_vm_ops,
192 .dumb_create = drm_gem_cma_dumb_create, 177 .dumb_create = drm_gem_cma_dumb_create,
@@ -298,12 +283,9 @@ static int imx_drm_bind(struct device *dev)
298 dev_warn(dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); 283 dev_warn(dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
299 legacyfb_depth = 16; 284 legacyfb_depth = 16;
300 } 285 }
301 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, MAX_CRTC); 286 ret = drm_fb_cma_fbdev_init(drm, legacyfb_depth, MAX_CRTC);
302 if (IS_ERR(imxdrm->fbhelper)) { 287 if (ret)
303 ret = PTR_ERR(imxdrm->fbhelper);
304 imxdrm->fbhelper = NULL;
305 goto err_unbind; 288 goto err_unbind;
306 }
307#endif 289#endif
308 290
309 drm_kms_helper_poll_init(drm); 291 drm_kms_helper_poll_init(drm);
@@ -317,8 +299,7 @@ static int imx_drm_bind(struct device *dev)
317err_fbhelper: 299err_fbhelper:
318 drm_kms_helper_poll_fini(drm); 300 drm_kms_helper_poll_fini(drm);
319#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) 301#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
320 if (imxdrm->fbhelper) 302 drm_fb_cma_fbdev_fini(drm);
321 drm_fbdev_cma_fini(imxdrm->fbhelper);
322err_unbind: 303err_unbind:
323#endif 304#endif
324 component_unbind_all(drm->dev, drm); 305 component_unbind_all(drm->dev, drm);
@@ -333,14 +314,12 @@ err_unref:
333static void imx_drm_unbind(struct device *dev) 314static void imx_drm_unbind(struct device *dev)
334{ 315{
335 struct drm_device *drm = dev_get_drvdata(dev); 316 struct drm_device *drm = dev_get_drvdata(dev);
336 struct imx_drm_device *imxdrm = drm->dev_private;
337 317
338 drm_dev_unregister(drm); 318 drm_dev_unregister(drm);
339 319
340 drm_kms_helper_poll_fini(drm); 320 drm_kms_helper_poll_fini(drm);
341 321
342 if (imxdrm->fbhelper) 322 drm_fb_cma_fbdev_fini(drm);
343 drm_fbdev_cma_fini(imxdrm->fbhelper);
344 323
345 drm_mode_config_cleanup(drm); 324 drm_mode_config_cleanup(drm);
346 325
diff --git a/drivers/gpu/drm/imx/imx-drm.h b/drivers/gpu/drm/imx/imx-drm.h
index f0b7556c0857..15c2bec47a04 100644
--- a/drivers/gpu/drm/imx/imx-drm.h
+++ b/drivers/gpu/drm/imx/imx-drm.h
@@ -8,7 +8,6 @@ struct drm_connector;
8struct drm_device; 8struct drm_device;
9struct drm_display_mode; 9struct drm_display_mode;
10struct drm_encoder; 10struct drm_encoder;
11struct drm_fbdev_cma;
12struct drm_framebuffer; 11struct drm_framebuffer;
13struct drm_plane; 12struct drm_plane;
14struct imx_drm_crtc; 13struct imx_drm_crtc;
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 3b804fdaf7a0..f9ad0e960263 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -151,6 +151,14 @@ static struct regmap_config meson_regmap_config = {
151 .max_register = 0x1000, 151 .max_register = 0x1000,
152}; 152};
153 153
154static void meson_vpu_init(struct meson_drm *priv)
155{
156 writel_relaxed(0x210000, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
157 writel_relaxed(0x10000, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
158 writel_relaxed(0x900000, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
159 writel_relaxed(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
160}
161
154static int meson_drv_bind_master(struct device *dev, bool has_components) 162static int meson_drv_bind_master(struct device *dev, bool has_components)
155{ 163{
156 struct platform_device *pdev = to_platform_device(dev); 164 struct platform_device *pdev = to_platform_device(dev);
@@ -222,6 +230,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
222 230
223 /* Hardware Initialization */ 231 /* Hardware Initialization */
224 232
233 meson_vpu_init(priv);
225 meson_venc_init(priv); 234 meson_venc_init(priv);
226 meson_vpp_init(priv); 235 meson_vpp_init(priv);
227 meson_viu_init(priv); 236 meson_viu_init(priv);
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index cef414466f9f..17de3afd98f6 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -23,6 +23,7 @@
23#include <linux/of_graph.h> 23#include <linux/of_graph.h>
24#include <linux/reset.h> 24#include <linux/reset.h>
25#include <linux/clk.h> 25#include <linux/clk.h>
26#include <linux/regulator/consumer.h>
26 27
27#include <drm/drmP.h> 28#include <drm/drmP.h>
28#include <drm/drm_edid.h> 29#include <drm/drm_edid.h>
@@ -137,6 +138,7 @@ struct meson_dw_hdmi {
137 struct reset_control *hdmitx_phy; 138 struct reset_control *hdmitx_phy;
138 struct clk *hdmi_pclk; 139 struct clk *hdmi_pclk;
139 struct clk *venci_clk; 140 struct clk *venci_clk;
141 struct regulator *hdmi_supply;
140 u32 irq_stat; 142 u32 irq_stat;
141}; 143};
142#define encoder_to_meson_dw_hdmi(x) \ 144#define encoder_to_meson_dw_hdmi(x) \
@@ -751,6 +753,17 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
751 dw_plat_data = &meson_dw_hdmi->dw_plat_data; 753 dw_plat_data = &meson_dw_hdmi->dw_plat_data;
752 encoder = &meson_dw_hdmi->encoder; 754 encoder = &meson_dw_hdmi->encoder;
753 755
756 meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
757 if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
758 if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
759 return -EPROBE_DEFER;
760 meson_dw_hdmi->hdmi_supply = NULL;
761 } else {
762 ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
763 if (ret)
764 return ret;
765 }
766
754 meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev, 767 meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
755 "hdmitx_apb"); 768 "hdmitx_apb");
756 if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) { 769 if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
index 284738196af9..bca87143e548 100644
--- a/drivers/gpu/drm/meson/meson_registers.h
+++ b/drivers/gpu/drm/meson/meson_registers.h
@@ -1363,6 +1363,10 @@
1363#define VPU_PROT3_STAT_1 0x277a 1363#define VPU_PROT3_STAT_1 0x277a
1364#define VPU_PROT3_STAT_2 0x277b 1364#define VPU_PROT3_STAT_2 0x277b
1365#define VPU_PROT3_REQ_ONOFF 0x277c 1365#define VPU_PROT3_REQ_ONOFF 0x277c
1366#define VPU_RDARB_MODE_L1C1 0x2790
1367#define VPU_RDARB_MODE_L1C2 0x2799
1368#define VPU_RDARB_MODE_L2C1 0x279d
1369#define VPU_WRARB_MODE_L2C1 0x27a2
1366 1370
1367/* osd super scale */ 1371/* osd super scale */
1368#define OSDSR_HV_SIZEIN 0x3130 1372#define OSDSR_HV_SIZEIN 0x3130
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 0a3ea3034e39..d90ef1d78a1b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -37,16 +37,9 @@
37#define MSM_VERSION_MINOR 3 37#define MSM_VERSION_MINOR 3
38#define MSM_VERSION_PATCHLEVEL 0 38#define MSM_VERSION_PATCHLEVEL 0
39 39
40static void msm_fb_output_poll_changed(struct drm_device *dev)
41{
42 struct msm_drm_private *priv = dev->dev_private;
43 if (priv->fbdev)
44 drm_fb_helper_hotplug_event(priv->fbdev);
45}
46
47static const struct drm_mode_config_funcs mode_config_funcs = { 40static const struct drm_mode_config_funcs mode_config_funcs = {
48 .fb_create = msm_framebuffer_create, 41 .fb_create = msm_framebuffer_create,
49 .output_poll_changed = msm_fb_output_poll_changed, 42 .output_poll_changed = drm_fb_helper_output_poll_changed,
50 .atomic_check = drm_atomic_helper_check, 43 .atomic_check = drm_atomic_helper_check,
51 .atomic_commit = msm_atomic_commit, 44 .atomic_commit = msm_atomic_commit,
52 .atomic_state_alloc = msm_atomic_state_alloc, 45 .atomic_state_alloc = msm_atomic_state_alloc,
@@ -551,13 +544,6 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
551 context_close(ctx); 544 context_close(ctx);
552} 545}
553 546
554static void msm_lastclose(struct drm_device *dev)
555{
556 struct msm_drm_private *priv = dev->dev_private;
557 if (priv->fbdev)
558 drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
559}
560
561static irqreturn_t msm_irq(int irq, void *arg) 547static irqreturn_t msm_irq(int irq, void *arg)
562{ 548{
563 struct drm_device *dev = arg; 549 struct drm_device *dev = arg;
@@ -866,7 +852,7 @@ static struct drm_driver msm_driver = {
866 DRIVER_MODESET, 852 DRIVER_MODESET,
867 .open = msm_open, 853 .open = msm_open,
868 .postclose = msm_postclose, 854 .postclose = msm_postclose,
869 .lastclose = msm_lastclose, 855 .lastclose = drm_fb_helper_lastclose,
870 .irq_handler = msm_irq, 856 .irq_handler = msm_irq,
871 .irq_preinstall = msm_irq_preinstall, 857 .irq_preinstall = msm_irq_preinstall,
872 .irq_postinstall = msm_irq_postinstall, 858 .irq_postinstall = msm_irq_postinstall,
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 2e7785f49e6d..009713404cc4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -29,6 +29,7 @@
29#include <drm/drm_atomic.h> 29#include <drm/drm_atomic.h>
30#include <drm/drm_atomic_helper.h> 30#include <drm/drm_atomic_helper.h>
31#include <drm/drm_crtc_helper.h> 31#include <drm/drm_crtc_helper.h>
32#include <drm/drm_fb_helper.h>
32 33
33#include <nvif/class.h> 34#include <nvif/class.h>
34 35
@@ -292,7 +293,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
292 293
293static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { 294static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
294 .fb_create = nouveau_user_framebuffer_create, 295 .fb_create = nouveau_user_framebuffer_create,
295 .output_poll_changed = nouveau_fbcon_output_poll_changed, 296 .output_poll_changed = drm_fb_helper_output_poll_changed,
296}; 297};
297 298
298 299
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index c533d8e04afc..45a4572cd2fb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -413,14 +413,6 @@ out:
413 return ret; 413 return ret;
414} 414}
415 415
416void
417nouveau_fbcon_output_poll_changed(struct drm_device *dev)
418{
419 struct nouveau_drm *drm = nouveau_drm(dev);
420 if (drm->fbcon)
421 drm_fb_helper_hotplug_event(&drm->fbcon->helper);
422}
423
424static int 416static int
425nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) 417nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
426{ 418{
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index e2bca729721e..a6f192ea3fa6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -68,8 +68,6 @@ void nouveau_fbcon_set_suspend(struct drm_device *dev, int state);
68void nouveau_fbcon_accel_save_disable(struct drm_device *dev); 68void nouveau_fbcon_accel_save_disable(struct drm_device *dev);
69void nouveau_fbcon_accel_restore(struct drm_device *dev); 69void nouveau_fbcon_accel_restore(struct drm_device *dev);
70 70
71void nouveau_fbcon_output_poll_changed(struct drm_device *dev);
72
73extern int nouveau_nofbaccel; 71extern int nouveau_nofbaccel;
74 72
75#endif /* __NV50_FBCON_H__ */ 73#endif /* __NV50_FBCON_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 52e52a360fb1..3da5a4305aa4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -4,6 +4,7 @@
4 4
5#include <drm/drmP.h> 5#include <drm/drmP.h>
6#include <drm/drm_crtc_helper.h> 6#include <drm/drm_crtc_helper.h>
7#include <drm/drm_fb_helper.h>
7 8
8#include "nouveau_drv.h" 9#include "nouveau_drv.h"
9#include "nouveau_acpi.h" 10#include "nouveau_acpi.h"
@@ -61,7 +62,7 @@ static void
61nouveau_switcheroo_reprobe(struct pci_dev *pdev) 62nouveau_switcheroo_reprobe(struct pci_dev *pdev)
62{ 63{
63 struct drm_device *dev = pci_get_drvdata(pdev); 64 struct drm_device *dev = pci_get_drvdata(pdev);
64 nouveau_fbcon_output_poll_changed(dev); 65 drm_fb_helper_output_poll_changed(dev);
65} 66}
66 67
67static bool 68static bool
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 65336948e807..b22c37bde13f 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -4311,7 +4311,7 @@ nv50_disp_atomic_state_alloc(struct drm_device *dev)
4311static const struct drm_mode_config_funcs 4311static const struct drm_mode_config_funcs
4312nv50_disp_func = { 4312nv50_disp_func = {
4313 .fb_create = nouveau_user_framebuffer_create, 4313 .fb_create = nouveau_user_framebuffer_create,
4314 .output_poll_changed = nouveau_fbcon_output_poll_changed, 4314 .output_poll_changed = drm_fb_helper_output_poll_changed,
4315 .atomic_check = nv50_disp_atomic_check, 4315 .atomic_check = nv50_disp_atomic_check,
4316 .atomic_commit = nv50_disp_atomic_commit, 4316 .atomic_commit = nv50_disp_atomic_commit,
4317 .atomic_state_alloc = nv50_disp_atomic_state_alloc, 4317 .atomic_state_alloc = nv50_disp_atomic_state_alloc,
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index cdf5b0601eba..96857c508ee0 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -46,14 +46,6 @@
46 * devices 46 * devices
47 */ 47 */
48 48
49static void omap_fb_output_poll_changed(struct drm_device *dev)
50{
51 struct omap_drm_private *priv = dev->dev_private;
52 DBG("dev=%p", dev);
53 if (priv->fbdev)
54 drm_fb_helper_hotplug_event(priv->fbdev);
55}
56
57static void omap_atomic_wait_for_completion(struct drm_device *dev, 49static void omap_atomic_wait_for_completion(struct drm_device *dev,
58 struct drm_atomic_state *old_state) 50 struct drm_atomic_state *old_state)
59{ 51{
@@ -132,7 +124,7 @@ static const struct drm_mode_config_helper_funcs omap_mode_config_helper_funcs =
132 124
133static const struct drm_mode_config_funcs omap_mode_config_funcs = { 125static const struct drm_mode_config_funcs omap_mode_config_funcs = {
134 .fb_create = omap_framebuffer_create, 126 .fb_create = omap_framebuffer_create,
135 .output_poll_changed = omap_fb_output_poll_changed, 127 .output_poll_changed = drm_fb_helper_output_poll_changed,
136 .atomic_check = drm_atomic_helper_check, 128 .atomic_check = drm_atomic_helper_check,
137 .atomic_commit = drm_atomic_helper_commit, 129 .atomic_commit = drm_atomic_helper_commit,
138}; 130};
@@ -467,28 +459,6 @@ static int dev_open(struct drm_device *dev, struct drm_file *file)
467 return 0; 459 return 0;
468} 460}
469 461
470/**
471 * lastclose - clean up after all DRM clients have exited
472 * @dev: DRM device
473 *
474 * Take care of cleaning up after all DRM clients have exited. In the
475 * mode setting case, we want to restore the kernel's initial mode (just
476 * in case the last client left us in a bad state).
477 */
478static void dev_lastclose(struct drm_device *dev)
479{
480 struct omap_drm_private *priv = dev->dev_private;
481 int ret;
482
483 DBG("lastclose: dev=%p", dev);
484
485 if (priv->fbdev) {
486 ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
487 if (ret)
488 DBG("failed to restore crtc mode");
489 }
490}
491
492static const struct vm_operations_struct omap_gem_vm_ops = { 462static const struct vm_operations_struct omap_gem_vm_ops = {
493 .fault = omap_gem_fault, 463 .fault = omap_gem_fault,
494 .open = drm_gem_vm_open, 464 .open = drm_gem_vm_open,
@@ -511,7 +481,7 @@ static struct drm_driver omap_drm_driver = {
511 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | 481 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
512 DRIVER_ATOMIC | DRIVER_RENDER, 482 DRIVER_ATOMIC | DRIVER_RENDER,
513 .open = dev_open, 483 .open = dev_open,
514 .lastclose = dev_lastclose, 484 .lastclose = drm_fb_helper_lastclose,
515#ifdef CONFIG_DEBUG_FS 485#ifdef CONFIG_DEBUG_FS
516 .debugfs_init = omap_debugfs_init, 486 .debugfs_init = omap_debugfs_init,
517#endif 487#endif
diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h
index 440f53ebee8c..07fa2cdb364a 100644
--- a/drivers/gpu/drm/pl111/pl111_drm.h
+++ b/drivers/gpu/drm/pl111/pl111_drm.h
@@ -53,7 +53,6 @@ struct pl111_drm_dev_private {
53 struct drm_panel *panel; 53 struct drm_panel *panel;
54 struct drm_bridge *bridge; 54 struct drm_bridge *bridge;
55 struct drm_simple_display_pipe pipe; 55 struct drm_simple_display_pipe pipe;
56 struct drm_fbdev_cma *fbdev;
57 56
58 void *regs; 57 void *regs;
59 u32 ienb; 58 u32 ienb;
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index 201d57d5cb54..acb738c69873 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -64,6 +64,7 @@
64#include <drm/drm_crtc_helper.h> 64#include <drm/drm_crtc_helper.h>
65#include <drm/drm_gem_cma_helper.h> 65#include <drm/drm_gem_cma_helper.h>
66#include <drm/drm_gem_framebuffer_helper.h> 66#include <drm/drm_gem_framebuffer_helper.h>
67#include <drm/drm_fb_helper.h>
67#include <drm/drm_fb_cma_helper.h> 68#include <drm/drm_fb_cma_helper.h>
68#include <drm/drm_of.h> 69#include <drm/drm_of.h>
69#include <drm/drm_bridge.h> 70#include <drm/drm_bridge.h>
@@ -137,8 +138,7 @@ static int pl111_modeset_init(struct drm_device *dev)
137 138
138 drm_mode_config_reset(dev); 139 drm_mode_config_reset(dev);
139 140
140 priv->fbdev = drm_fbdev_cma_init(dev, 32, 141 drm_fb_cma_fbdev_init(dev, 32, 0);
141 dev->mode_config.num_connector);
142 142
143 drm_kms_helper_poll_init(dev); 143 drm_kms_helper_poll_init(dev);
144 144
@@ -155,17 +155,10 @@ finish:
155 155
156DEFINE_DRM_GEM_CMA_FOPS(drm_fops); 156DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
157 157
158static void pl111_lastclose(struct drm_device *dev)
159{
160 struct pl111_drm_dev_private *priv = dev->dev_private;
161
162 drm_fbdev_cma_restore_mode(priv->fbdev);
163}
164
165static struct drm_driver pl111_drm_driver = { 158static struct drm_driver pl111_drm_driver = {
166 .driver_features = 159 .driver_features =
167 DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, 160 DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
168 .lastclose = pl111_lastclose, 161 .lastclose = drm_fb_helper_lastclose,
169 .ioctls = NULL, 162 .ioctls = NULL,
170 .fops = &drm_fops, 163 .fops = &drm_fops,
171 .name = "pl111", 164 .name = "pl111",
@@ -281,8 +274,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev)
281 struct pl111_drm_dev_private *priv = drm->dev_private; 274 struct pl111_drm_dev_private *priv = drm->dev_private;
282 275
283 drm_dev_unregister(drm); 276 drm_dev_unregister(drm);
284 if (priv->fbdev) 277 drm_fb_cma_fbdev_fini(drm);
285 drm_fbdev_cma_fini(priv->fbdev);
286 if (priv->panel) 278 if (priv->panel)
287 drm_panel_bridge_remove(priv->bridge); 279 drm_panel_bridge_remove(priv->bridge);
288 drm_mode_config_cleanup(drm); 280 drm_mode_config_cleanup(drm);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 76d63de5921d..d85431400a0d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -207,13 +207,6 @@ static void rockchip_drm_unbind(struct device *dev)
207 drm_dev_unref(drm_dev); 207 drm_dev_unref(drm_dev);
208} 208}
209 209
210static void rockchip_drm_lastclose(struct drm_device *dev)
211{
212 struct rockchip_drm_private *priv = dev->dev_private;
213
214 drm_fb_helper_restore_fbdev_mode_unlocked(&priv->fbdev_helper);
215}
216
217static const struct file_operations rockchip_drm_driver_fops = { 210static const struct file_operations rockchip_drm_driver_fops = {
218 .owner = THIS_MODULE, 211 .owner = THIS_MODULE,
219 .open = drm_open, 212 .open = drm_open,
@@ -228,7 +221,7 @@ static const struct file_operations rockchip_drm_driver_fops = {
228static struct drm_driver rockchip_drm_driver = { 221static struct drm_driver rockchip_drm_driver = {
229 .driver_features = DRIVER_MODESET | DRIVER_GEM | 222 .driver_features = DRIVER_MODESET | DRIVER_GEM |
230 DRIVER_PRIME | DRIVER_ATOMIC, 223 DRIVER_PRIME | DRIVER_ATOMIC,
231 .lastclose = rockchip_drm_lastclose, 224 .lastclose = drm_fb_helper_lastclose,
232 .gem_vm_ops = &drm_gem_cma_vm_ops, 225 .gem_vm_ops = &drm_gem_cma_vm_ops,
233 .gem_free_object_unlocked = rockchip_gem_free_object, 226 .gem_free_object_unlocked = rockchip_gem_free_object,
234 .dumb_create = rockchip_gem_dumb_create, 227 .dumb_create = rockchip_gem_dumb_create,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index cd2ace0c3caa..e266539e04e5 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -167,20 +167,13 @@ err_gem_object_unreference:
167 return ERR_PTR(ret); 167 return ERR_PTR(ret);
168} 168}
169 169
170static void rockchip_drm_output_poll_changed(struct drm_device *dev)
171{
172 struct rockchip_drm_private *private = dev->dev_private;
173
174 drm_fb_helper_hotplug_event(&private->fbdev_helper);
175}
176
177static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { 170static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
178 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, 171 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
179}; 172};
180 173
181static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { 174static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
182 .fb_create = rockchip_user_fb_create, 175 .fb_create = rockchip_user_fb_create,
183 .output_poll_changed = rockchip_drm_output_poll_changed, 176 .output_poll_changed = drm_fb_helper_output_poll_changed,
184 .atomic_check = drm_atomic_helper_check, 177 .atomic_check = drm_atomic_helper_check,
185 .atomic_commit = drm_atomic_helper_commit, 178 .atomic_commit = drm_atomic_helper_commit,
186}; 179};
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 88d1dc6408af..55b6967d27e1 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -17,6 +17,7 @@
17#include <drm/drm_crtc_helper.h> 17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_gem_cma_helper.h> 18#include <drm/drm_gem_cma_helper.h>
19#include <drm/drm_gem_framebuffer_helper.h> 19#include <drm/drm_gem_framebuffer_helper.h>
20#include <drm/drm_fb_helper.h>
20#include <drm/drm_fb_cma_helper.h> 21#include <drm/drm_fb_cma_helper.h>
21#include <drm/drm_of.h> 22#include <drm/drm_of.h>
22 23
@@ -138,16 +139,9 @@ static int sti_atomic_check(struct drm_device *dev,
138 return ret; 139 return ret;
139} 140}
140 141
141static void sti_output_poll_changed(struct drm_device *ddev)
142{
143 struct sti_private *private = ddev->dev_private;
144
145 drm_fbdev_cma_hotplug_event(private->fbdev);
146}
147
148static const struct drm_mode_config_funcs sti_mode_config_funcs = { 142static const struct drm_mode_config_funcs sti_mode_config_funcs = {
149 .fb_create = drm_gem_fb_create, 143 .fb_create = drm_gem_fb_create,
150 .output_poll_changed = sti_output_poll_changed, 144 .output_poll_changed = drm_fb_helper_output_poll_changed,
151 .atomic_check = sti_atomic_check, 145 .atomic_check = sti_atomic_check,
152 .atomic_commit = drm_atomic_helper_commit, 146 .atomic_commit = drm_atomic_helper_commit,
153}; 147};
@@ -230,11 +224,7 @@ static void sti_cleanup(struct drm_device *ddev)
230{ 224{
231 struct sti_private *private = ddev->dev_private; 225 struct sti_private *private = ddev->dev_private;
232 226
233 if (private->fbdev) { 227 drm_fb_cma_fbdev_fini(ddev);
234 drm_fbdev_cma_fini(private->fbdev);
235 private->fbdev = NULL;
236 }
237
238 drm_kms_helper_poll_fini(ddev); 228 drm_kms_helper_poll_fini(ddev);
239 component_unbind_all(ddev->dev, ddev); 229 component_unbind_all(ddev->dev, ddev);
240 kfree(private); 230 kfree(private);
@@ -244,8 +234,6 @@ static void sti_cleanup(struct drm_device *ddev)
244static int sti_bind(struct device *dev) 234static int sti_bind(struct device *dev)
245{ 235{
246 struct drm_device *ddev; 236 struct drm_device *ddev;
247 struct sti_private *private;
248 struct drm_fbdev_cma *fbdev;
249 int ret; 237 int ret;
250 238
251 ddev = drm_dev_alloc(&sti_driver, dev); 239 ddev = drm_dev_alloc(&sti_driver, dev);
@@ -266,15 +254,10 @@ static int sti_bind(struct device *dev)
266 254
267 drm_mode_config_reset(ddev); 255 drm_mode_config_reset(ddev);
268 256
269 private = ddev->dev_private;
270 if (ddev->mode_config.num_connector) { 257 if (ddev->mode_config.num_connector) {
271 fbdev = drm_fbdev_cma_init(ddev, 32, 258 ret = drm_fb_cma_fbdev_init(ddev, 32, 0);
272 ddev->mode_config.num_connector); 259 if (ret)
273 if (IS_ERR(fbdev)) {
274 DRM_DEBUG_DRIVER("Warning: fails to create fbdev\n"); 260 DRM_DEBUG_DRIVER("Warning: fails to create fbdev\n");
275 fbdev = NULL;
276 }
277 private->fbdev = fbdev;
278 } 261 }
279 262
280 return 0; 263 return 0;
diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h
index abc49b43566e..4b41142a22e4 100644
--- a/drivers/gpu/drm/sti/sti_drv.h
+++ b/drivers/gpu/drm/sti/sti_drv.h
@@ -24,7 +24,6 @@ struct sti_private {
24 struct sti_compositor *compo; 24 struct sti_compositor *compo;
25 struct drm_property *plane_zorder_property; 25 struct drm_property *plane_zorder_property;
26 struct drm_device *drm_dev; 26 struct drm_device *drm_dev;
27 struct drm_fbdev_cma *fbdev;
28}; 27};
29 28
30extern struct platform_driver sti_tvout_driver; 29extern struct platform_driver sti_tvout_driver;
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 2d6e9ca0450b..8fe954c27fba 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -14,6 +14,7 @@
14#include <drm/drm_atomic.h> 14#include <drm/drm_atomic.h>
15#include <drm/drm_atomic_helper.h> 15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc_helper.h> 16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_fb_helper.h>
17#include <drm/drm_fb_cma_helper.h> 18#include <drm/drm_fb_cma_helper.h>
18#include <drm/drm_gem_cma_helper.h> 19#include <drm/drm_gem_cma_helper.h>
19#include <drm/drm_gem_framebuffer_helper.h> 20#include <drm/drm_gem_framebuffer_helper.h>
@@ -23,35 +24,19 @@
23#define STM_MAX_FB_WIDTH 2048 24#define STM_MAX_FB_WIDTH 2048
24#define STM_MAX_FB_HEIGHT 2048 /* same as width to handle orientation */ 25#define STM_MAX_FB_HEIGHT 2048 /* same as width to handle orientation */
25 26
26static void drv_output_poll_changed(struct drm_device *ddev)
27{
28 struct ltdc_device *ldev = ddev->dev_private;
29
30 drm_fbdev_cma_hotplug_event(ldev->fbdev);
31}
32
33static const struct drm_mode_config_funcs drv_mode_config_funcs = { 27static const struct drm_mode_config_funcs drv_mode_config_funcs = {
34 .fb_create = drm_gem_fb_create, 28 .fb_create = drm_gem_fb_create,
35 .output_poll_changed = drv_output_poll_changed, 29 .output_poll_changed = drm_fb_helper_output_poll_changed,
36 .atomic_check = drm_atomic_helper_check, 30 .atomic_check = drm_atomic_helper_check,
37 .atomic_commit = drm_atomic_helper_commit, 31 .atomic_commit = drm_atomic_helper_commit,
38}; 32};
39 33
40static void drv_lastclose(struct drm_device *ddev)
41{
42 struct ltdc_device *ldev = ddev->dev_private;
43
44 DRM_DEBUG("%s\n", __func__);
45
46 drm_fbdev_cma_restore_mode(ldev->fbdev);
47}
48
49DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops); 34DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops);
50 35
51static struct drm_driver drv_driver = { 36static struct drm_driver drv_driver = {
52 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | 37 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
53 DRIVER_ATOMIC, 38 DRIVER_ATOMIC,
54 .lastclose = drv_lastclose, 39 .lastclose = drm_fb_helper_lastclose,
55 .name = "stm", 40 .name = "stm",
56 .desc = "STMicroelectronics SoC DRM", 41 .desc = "STMicroelectronics SoC DRM",
57 .date = "20170330", 42 .date = "20170330",
@@ -78,7 +63,6 @@ static struct drm_driver drv_driver = {
78static int drv_load(struct drm_device *ddev) 63static int drv_load(struct drm_device *ddev)
79{ 64{
80 struct platform_device *pdev = to_platform_device(ddev->dev); 65 struct platform_device *pdev = to_platform_device(ddev->dev);
81 struct drm_fbdev_cma *fbdev;
82 struct ltdc_device *ldev; 66 struct ltdc_device *ldev;
83 int ret; 67 int ret;
84 68
@@ -111,14 +95,9 @@ static int drv_load(struct drm_device *ddev)
111 drm_kms_helper_poll_init(ddev); 95 drm_kms_helper_poll_init(ddev);
112 96
113 if (ddev->mode_config.num_connector) { 97 if (ddev->mode_config.num_connector) {
114 ldev = ddev->dev_private; 98 ret = drm_fb_cma_fbdev_init(ddev, 16, 0);
115 fbdev = drm_fbdev_cma_init(ddev, 16, 99 if (ret)
116 ddev->mode_config.num_connector);
117 if (IS_ERR(fbdev)) {
118 DRM_DEBUG("Warning: fails to create fbdev\n"); 100 DRM_DEBUG("Warning: fails to create fbdev\n");
119 fbdev = NULL;
120 }
121 ldev->fbdev = fbdev;
122 } 101 }
123 102
124 platform_set_drvdata(pdev, ddev); 103 platform_set_drvdata(pdev, ddev);
@@ -131,14 +110,9 @@ err:
131 110
132static void drv_unload(struct drm_device *ddev) 111static void drv_unload(struct drm_device *ddev)
133{ 112{
134 struct ltdc_device *ldev = ddev->dev_private;
135
136 DRM_DEBUG("%s\n", __func__); 113 DRM_DEBUG("%s\n", __func__);
137 114
138 if (ldev->fbdev) { 115 drm_fb_cma_fbdev_fini(ddev);
139 drm_fbdev_cma_fini(ldev->fbdev);
140 ldev->fbdev = NULL;
141 }
142 drm_kms_helper_poll_fini(ddev); 116 drm_kms_helper_poll_fini(ddev);
143 ltdc_unload(ddev); 117 ltdc_unload(ddev);
144 drm_mode_config_cleanup(ddev); 118 drm_mode_config_cleanup(ddev);
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
index d5da74d24995..edd1c0a446d1 100644
--- a/drivers/gpu/drm/stm/ltdc.h
+++ b/drivers/gpu/drm/stm/ltdc.h
@@ -20,7 +20,6 @@ struct ltdc_caps {
20}; 20};
21 21
22struct ltdc_device { 22struct ltdc_device {
23 struct drm_fbdev_cma *fbdev;
24 void __iomem *regs; 23 void __iomem *regs;
25 struct clk *pixel_clk; /* lcd pixel clock */ 24 struct clk *pixel_clk; /* lcd pixel clock */
26 struct mutex err_lock; /* protecting error_status */ 25 struct mutex err_lock; /* protecting error_status */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 49215d91c853..2b4717604eb3 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -26,20 +26,13 @@
26#include "sun4i_framebuffer.h" 26#include "sun4i_framebuffer.h"
27#include "sun4i_tcon.h" 27#include "sun4i_tcon.h"
28 28
29static void sun4i_drv_lastclose(struct drm_device *dev)
30{
31 struct sun4i_drv *drv = dev->dev_private;
32
33 drm_fbdev_cma_restore_mode(drv->fbdev);
34}
35
36DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); 29DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
37 30
38static struct drm_driver sun4i_drv_driver = { 31static struct drm_driver sun4i_drv_driver = {
39 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, 32 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
40 33
41 /* Generic Operations */ 34 /* Generic Operations */
42 .lastclose = sun4i_drv_lastclose, 35 .lastclose = drm_fb_helper_lastclose,
43 .fops = &sun4i_drv_fops, 36 .fops = &sun4i_drv_fops,
44 .name = "sun4i-drm", 37 .name = "sun4i-drm",
45 .desc = "Allwinner sun4i Display Engine", 38 .desc = "Allwinner sun4i Display Engine",
@@ -126,10 +119,9 @@ static int sun4i_drv_bind(struct device *dev)
126 sun4i_remove_framebuffers(); 119 sun4i_remove_framebuffers();
127 120
128 /* Create our framebuffer */ 121 /* Create our framebuffer */
129 drv->fbdev = sun4i_framebuffer_init(drm); 122 ret = sun4i_framebuffer_init(drm);
130 if (IS_ERR(drv->fbdev)) { 123 if (ret) {
131 dev_err(drm->dev, "Couldn't create our framebuffer\n"); 124 dev_err(drm->dev, "Couldn't create our framebuffer\n");
132 ret = PTR_ERR(drv->fbdev);
133 goto cleanup_mode_config; 125 goto cleanup_mode_config;
134 } 126 }
135 127
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index a960c89270cc..2825f140da54 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -20,8 +20,6 @@
20struct sun4i_drv { 20struct sun4i_drv {
21 struct list_head engine_list; 21 struct list_head engine_list;
22 struct list_head tcon_list; 22 struct list_head tcon_list;
23
24 struct drm_fbdev_cma *fbdev;
25}; 23};
26 24
27#endif /* _SUN4I_DRV_H_ */ 25#endif /* _SUN4I_DRV_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
index 2992f0a6b349..38a36c0dfa2f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <drm/drm_atomic_helper.h> 13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_fb_helper.h>
14#include <drm/drm_fb_cma_helper.h> 15#include <drm/drm_fb_cma_helper.h>
15#include <drm/drm_gem_framebuffer_helper.h> 16#include <drm/drm_gem_framebuffer_helper.h>
16#include <drm/drmP.h> 17#include <drm/drmP.h>
@@ -18,21 +19,14 @@
18#include "sun4i_drv.h" 19#include "sun4i_drv.h"
19#include "sun4i_framebuffer.h" 20#include "sun4i_framebuffer.h"
20 21
21static void sun4i_de_output_poll_changed(struct drm_device *drm)
22{
23 struct sun4i_drv *drv = drm->dev_private;
24
25 drm_fbdev_cma_hotplug_event(drv->fbdev);
26}
27
28static const struct drm_mode_config_funcs sun4i_de_mode_config_funcs = { 22static const struct drm_mode_config_funcs sun4i_de_mode_config_funcs = {
29 .output_poll_changed = sun4i_de_output_poll_changed, 23 .output_poll_changed = drm_fb_helper_output_poll_changed,
30 .atomic_check = drm_atomic_helper_check, 24 .atomic_check = drm_atomic_helper_check,
31 .atomic_commit = drm_atomic_helper_commit, 25 .atomic_commit = drm_atomic_helper_commit,
32 .fb_create = drm_gem_fb_create, 26 .fb_create = drm_gem_fb_create,
33}; 27};
34 28
35struct drm_fbdev_cma *sun4i_framebuffer_init(struct drm_device *drm) 29int sun4i_framebuffer_init(struct drm_device *drm)
36{ 30{
37 drm_mode_config_reset(drm); 31 drm_mode_config_reset(drm);
38 32
@@ -41,12 +35,10 @@ struct drm_fbdev_cma *sun4i_framebuffer_init(struct drm_device *drm)
41 35
42 drm->mode_config.funcs = &sun4i_de_mode_config_funcs; 36 drm->mode_config.funcs = &sun4i_de_mode_config_funcs;
43 37
44 return drm_fbdev_cma_init(drm, 32, drm->mode_config.num_connector); 38 return drm_fb_cma_fbdev_init(drm, 32, 0);
45} 39}
46 40
47void sun4i_framebuffer_free(struct drm_device *drm) 41void sun4i_framebuffer_free(struct drm_device *drm)
48{ 42{
49 struct sun4i_drv *drv = drm->dev_private; 43 drm_fb_cma_fbdev_fini(drm);
50
51 drm_fbdev_cma_fini(drv->fbdev);
52} 44}
diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.h b/drivers/gpu/drm/sun4i/sun4i_framebuffer.h
index 3afd65252ee0..7ef0aed8384c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.h
@@ -13,7 +13,7 @@
13#ifndef _SUN4I_FRAMEBUFFER_H_ 13#ifndef _SUN4I_FRAMEBUFFER_H_
14#define _SUN4I_FRAMEBUFFER_H_ 14#define _SUN4I_FRAMEBUFFER_H_
15 15
16struct drm_fbdev_cma *sun4i_framebuffer_init(struct drm_device *drm); 16int sun4i_framebuffer_init(struct drm_device *drm);
17void sun4i_framebuffer_free(struct drm_device *drm); 17void sun4i_framebuffer_free(struct drm_device *drm);
18 18
19#endif /* _SUN4I_FRAMEBUFFER_H_ */ 19#endif /* _SUN4I_FRAMEBUFFER_H_ */
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 52552b9b89ef..f157bc675269 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -120,7 +120,7 @@ static int tegra_atomic_commit(struct drm_device *drm,
120static const struct drm_mode_config_funcs tegra_drm_mode_funcs = { 120static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
121 .fb_create = tegra_fb_create, 121 .fb_create = tegra_fb_create,
122#ifdef CONFIG_DRM_FBDEV_EMULATION 122#ifdef CONFIG_DRM_FBDEV_EMULATION
123 .output_poll_changed = tegra_fb_output_poll_changed, 123 .output_poll_changed = drm_fb_helper_output_poll_changed,
124#endif 124#endif
125 .atomic_check = drm_atomic_helper_check, 125 .atomic_check = drm_atomic_helper_check,
126 .atomic_commit = tegra_atomic_commit, 126 .atomic_commit = tegra_atomic_commit,
@@ -286,15 +286,6 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
286 kfree(context); 286 kfree(context);
287} 287}
288 288
289static void tegra_drm_lastclose(struct drm_device *drm)
290{
291#ifdef CONFIG_DRM_FBDEV_EMULATION
292 struct tegra_drm *tegra = drm->dev_private;
293
294 tegra_fbdev_restore_mode(tegra->fbdev);
295#endif
296}
297
298static struct host1x_bo * 289static struct host1x_bo *
299host1x_bo_lookup(struct drm_file *file, u32 handle) 290host1x_bo_lookup(struct drm_file *file, u32 handle)
300{ 291{
@@ -1100,7 +1091,7 @@ static struct drm_driver tegra_drm_driver = {
1100 .unload = tegra_drm_unload, 1091 .unload = tegra_drm_unload,
1101 .open = tegra_drm_open, 1092 .open = tegra_drm_open,
1102 .postclose = tegra_drm_postclose, 1093 .postclose = tegra_drm_postclose,
1103 .lastclose = tegra_drm_lastclose, 1094 .lastclose = drm_fb_helper_lastclose,
1104 1095
1105#if defined(CONFIG_DEBUG_FS) 1096#if defined(CONFIG_DEBUG_FS)
1106 .debugfs_init = tegra_debugfs_init, 1097 .debugfs_init = tegra_debugfs_init,
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index ddae331ad8b6..0009f6ea21b6 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -188,10 +188,6 @@ int tegra_drm_fb_init(struct drm_device *drm);
188void tegra_drm_fb_exit(struct drm_device *drm); 188void tegra_drm_fb_exit(struct drm_device *drm);
189void tegra_drm_fb_suspend(struct drm_device *drm); 189void tegra_drm_fb_suspend(struct drm_device *drm);
190void tegra_drm_fb_resume(struct drm_device *drm); 190void tegra_drm_fb_resume(struct drm_device *drm);
191#ifdef CONFIG_DRM_FBDEV_EMULATION
192void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
193void tegra_fb_output_poll_changed(struct drm_device *drm);
194#endif
195 191
196extern struct platform_driver tegra_dc_driver; 192extern struct platform_driver tegra_dc_driver;
197extern struct platform_driver tegra_hdmi_driver; 193extern struct platform_driver tegra_hdmi_driver;
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 80540c1c66dc..8dfe3c6c217e 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -361,20 +361,6 @@ static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
361 drm_fb_helper_fini(&fbdev->base); 361 drm_fb_helper_fini(&fbdev->base);
362 tegra_fbdev_free(fbdev); 362 tegra_fbdev_free(fbdev);
363} 363}
364
365void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
366{
367 if (fbdev)
368 drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->base);
369}
370
371void tegra_fb_output_poll_changed(struct drm_device *drm)
372{
373 struct tegra_drm *tegra = drm->dev_private;
374
375 if (tegra->fbdev)
376 drm_fb_helper_hotplug_event(&tegra->fbdev->base);
377}
378#endif 364#endif
379 365
380int tegra_drm_fb_prepare(struct drm_device *drm) 366int tegra_drm_fb_prepare(struct drm_device *drm)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index bc4feb3a84b9..1afde61f1247 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -69,12 +69,6 @@ static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
69 return drm_gem_fb_create(dev, file_priv, mode_cmd); 69 return drm_gem_fb_create(dev, file_priv, mode_cmd);
70} 70}
71 71
72static void tilcdc_fb_output_poll_changed(struct drm_device *dev)
73{
74 struct tilcdc_drm_private *priv = dev->dev_private;
75 drm_fbdev_cma_hotplug_event(priv->fbdev);
76}
77
78static int tilcdc_atomic_check(struct drm_device *dev, 72static int tilcdc_atomic_check(struct drm_device *dev,
79 struct drm_atomic_state *state) 73 struct drm_atomic_state *state)
80{ 74{
@@ -146,7 +140,7 @@ static int tilcdc_commit(struct drm_device *dev,
146 140
147static const struct drm_mode_config_funcs mode_config_funcs = { 141static const struct drm_mode_config_funcs mode_config_funcs = {
148 .fb_create = tilcdc_fb_create, 142 .fb_create = tilcdc_fb_create,
149 .output_poll_changed = tilcdc_fb_output_poll_changed, 143 .output_poll_changed = drm_fb_helper_output_poll_changed,
150 .atomic_check = tilcdc_atomic_check, 144 .atomic_check = tilcdc_atomic_check,
151 .atomic_commit = tilcdc_commit, 145 .atomic_commit = tilcdc_commit,
152}; 146};
@@ -198,8 +192,7 @@ static void tilcdc_fini(struct drm_device *dev)
198 192
199 drm_kms_helper_poll_fini(dev); 193 drm_kms_helper_poll_fini(dev);
200 194
201 if (priv->fbdev) 195 drm_fb_cma_fbdev_fini(dev);
202 drm_fbdev_cma_fini(priv->fbdev);
203 196
204 drm_irq_uninstall(dev); 197 drm_irq_uninstall(dev);
205 drm_mode_config_cleanup(dev); 198 drm_mode_config_cleanup(dev);
@@ -405,12 +398,9 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
405 398
406 drm_mode_config_reset(ddev); 399 drm_mode_config_reset(ddev);
407 400
408 priv->fbdev = drm_fbdev_cma_init(ddev, bpp, 401 ret = drm_fb_cma_fbdev_init(ddev, bpp, 0);
409 ddev->mode_config.num_connector); 402 if (ret)
410 if (IS_ERR(priv->fbdev)) {
411 ret = PTR_ERR(priv->fbdev);
412 goto init_failed; 403 goto init_failed;
413 }
414 404
415 drm_kms_helper_poll_init(ddev); 405 drm_kms_helper_poll_init(ddev);
416 406
@@ -427,12 +417,6 @@ init_failed:
427 return ret; 417 return ret;
428} 418}
429 419
430static void tilcdc_lastclose(struct drm_device *dev)
431{
432 struct tilcdc_drm_private *priv = dev->dev_private;
433 drm_fbdev_cma_restore_mode(priv->fbdev);
434}
435
436static irqreturn_t tilcdc_irq(int irq, void *arg) 420static irqreturn_t tilcdc_irq(int irq, void *arg)
437{ 421{
438 struct drm_device *dev = arg; 422 struct drm_device *dev = arg;
@@ -537,7 +521,7 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
537static struct drm_driver tilcdc_driver = { 521static struct drm_driver tilcdc_driver = {
538 .driver_features = (DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET | 522 .driver_features = (DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET |
539 DRIVER_PRIME | DRIVER_ATOMIC), 523 DRIVER_PRIME | DRIVER_ATOMIC),
540 .lastclose = tilcdc_lastclose, 524 .lastclose = drm_fb_helper_lastclose,
541 .irq_handler = tilcdc_irq, 525 .irq_handler = tilcdc_irq,
542 .gem_free_object_unlocked = drm_gem_cma_free_object, 526 .gem_free_object_unlocked = drm_gem_cma_free_object,
543 .gem_print_info = drm_gem_cma_print_info, 527 .gem_print_info = drm_gem_cma_print_info,
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index 8caa11bc7aec..ead512216669 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -79,8 +79,6 @@ struct tilcdc_drm_private {
79 79
80 struct workqueue_struct *wq; 80 struct workqueue_struct *wq;
81 81
82 struct drm_fbdev_cma *fbdev;
83
84 struct drm_crtc *crtc; 82 struct drm_crtc *crtc;
85 83
86 unsigned int num_encoders; 84 unsigned int num_encoders;
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
index bd7b82824a34..4c6616278c48 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c
@@ -10,6 +10,7 @@
10#include <drm/drm_atomic.h> 10#include <drm/drm_atomic.h>
11#include <drm/drm_atomic_helper.h> 11#include <drm/drm_atomic_helper.h>
12#include <drm/drm_crtc_helper.h> 12#include <drm/drm_crtc_helper.h>
13#include <drm/drm_fb_helper.h>
13#include <drm/drm_gem_framebuffer_helper.h> 14#include <drm/drm_gem_framebuffer_helper.h>
14#include <drm/tinydrm/tinydrm.h> 15#include <drm/tinydrm/tinydrm.h>
15#include <linux/device.h> 16#include <linux/device.h>
@@ -36,23 +37,6 @@
36 */ 37 */
37 38
38/** 39/**
39 * tinydrm_lastclose - DRM lastclose helper
40 * @drm: DRM device
41 *
42 * This function ensures that fbdev is restored when drm_lastclose() is called
43 * on the last drm_release(). Drivers can use this as their
44 * &drm_driver->lastclose callback.
45 */
46void tinydrm_lastclose(struct drm_device *drm)
47{
48 struct tinydrm_device *tdev = drm->dev_private;
49
50 DRM_DEBUG_KMS("\n");
51 drm_fbdev_cma_restore_mode(tdev->fbdev_cma);
52}
53EXPORT_SYMBOL(tinydrm_lastclose);
54
55/**
56 * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from 40 * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from
57 * another driver's scatter/gather table of pinned pages 41 * another driver's scatter/gather table of pinned pages
58 * @drm: DRM device to import into 42 * @drm: DRM device to import into
@@ -214,35 +198,24 @@ EXPORT_SYMBOL(devm_tinydrm_init);
214static int tinydrm_register(struct tinydrm_device *tdev) 198static int tinydrm_register(struct tinydrm_device *tdev)
215{ 199{
216 struct drm_device *drm = tdev->drm; 200 struct drm_device *drm = tdev->drm;
217 int bpp = drm->mode_config.preferred_depth;
218 struct drm_fbdev_cma *fbdev;
219 int ret; 201 int ret;
220 202
221 ret = drm_dev_register(tdev->drm, 0); 203 ret = drm_dev_register(tdev->drm, 0);
222 if (ret) 204 if (ret)
223 return ret; 205 return ret;
224 206
225 fbdev = drm_fbdev_cma_init_with_funcs(drm, bpp ? bpp : 32, 207 ret = drm_fb_cma_fbdev_init_with_funcs(drm, 0, 0, tdev->fb_funcs);
226 drm->mode_config.num_connector, 208 if (ret)
227 tdev->fb_funcs); 209 DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
228 if (IS_ERR(fbdev))
229 DRM_ERROR("Failed to initialize fbdev: %ld\n", PTR_ERR(fbdev));
230 else
231 tdev->fbdev_cma = fbdev;
232 210
233 return 0; 211 return 0;
234} 212}
235 213
236static void tinydrm_unregister(struct tinydrm_device *tdev) 214static void tinydrm_unregister(struct tinydrm_device *tdev)
237{ 215{
238 struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma;
239
240 drm_atomic_helper_shutdown(tdev->drm); 216 drm_atomic_helper_shutdown(tdev->drm);
241 /* don't restore fbdev in lastclose, keep pipeline disabled */ 217 drm_fb_cma_fbdev_fini(tdev->drm);
242 tdev->fbdev_cma = NULL;
243 drm_dev_unregister(tdev->drm); 218 drm_dev_unregister(tdev->drm);
244 if (fbdev_cma)
245 drm_fbdev_cma_fini(fbdev_cma);
246} 219}
247 220
248static void devm_tinydrm_register_release(void *data) 221static void devm_tinydrm_register_release(void *data)
diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c
index 3b766a26aa61..e8f1b3af3852 100644
--- a/drivers/gpu/drm/tinydrm/ili9225.c
+++ b/drivers/gpu/drm/tinydrm/ili9225.c
@@ -20,6 +20,7 @@
20#include <linux/spi/spi.h> 20#include <linux/spi/spi.h>
21#include <video/mipi_display.h> 21#include <video/mipi_display.h>
22 22
23#include <drm/drm_fb_helper.h>
23#include <drm/drm_gem_framebuffer_helper.h> 24#include <drm/drm_gem_framebuffer_helper.h>
24#include <drm/tinydrm/mipi-dbi.h> 25#include <drm/tinydrm/mipi-dbi.h>
25#include <drm/tinydrm/tinydrm-helpers.h> 26#include <drm/tinydrm/tinydrm-helpers.h>
@@ -381,7 +382,7 @@ static struct drm_driver ili9225_driver = {
381 DRIVER_ATOMIC, 382 DRIVER_ATOMIC,
382 .fops = &ili9225_fops, 383 .fops = &ili9225_fops,
383 TINYDRM_GEM_DRIVER_OPS, 384 TINYDRM_GEM_DRIVER_OPS,
384 .lastclose = tinydrm_lastclose, 385 .lastclose = drm_fb_helper_lastclose,
385 .name = "ili9225", 386 .name = "ili9225",
386 .desc = "Ilitek ILI9225", 387 .desc = "Ilitek ILI9225",
387 .date = "20171106", 388 .date = "20171106",
diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c
index 70ae4f76f455..674d407640be 100644
--- a/drivers/gpu/drm/tinydrm/mi0283qt.c
+++ b/drivers/gpu/drm/tinydrm/mi0283qt.c
@@ -9,6 +9,7 @@
9 * (at your option) any later version. 9 * (at your option) any later version.
10 */ 10 */
11 11
12#include <drm/drm_fb_helper.h>
12#include <drm/drm_modeset_helper.h> 13#include <drm/drm_modeset_helper.h>
13#include <drm/tinydrm/ili9341.h> 14#include <drm/tinydrm/ili9341.h>
14#include <drm/tinydrm/mipi-dbi.h> 15#include <drm/tinydrm/mipi-dbi.h>
@@ -140,7 +141,7 @@ static struct drm_driver mi0283qt_driver = {
140 DRIVER_ATOMIC, 141 DRIVER_ATOMIC,
141 .fops = &mi0283qt_fops, 142 .fops = &mi0283qt_fops,
142 TINYDRM_GEM_DRIVER_OPS, 143 TINYDRM_GEM_DRIVER_OPS,
143 .lastclose = tinydrm_lastclose, 144 .lastclose = drm_fb_helper_lastclose,
144 .debugfs_init = mipi_dbi_debugfs_init, 145 .debugfs_init = mipi_dbi_debugfs_init,
145 .name = "mi0283qt", 146 .name = "mi0283qt",
146 .desc = "Multi-Inno MI0283QT", 147 .desc = "Multi-Inno MI0283QT",
diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c
index 0a2c60da5c0e..5aebfceb740e 100644
--- a/drivers/gpu/drm/tinydrm/st7586.c
+++ b/drivers/gpu/drm/tinydrm/st7586.c
@@ -17,6 +17,7 @@
17#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
18#include <video/mipi_display.h> 18#include <video/mipi_display.h>
19 19
20#include <drm/drm_fb_helper.h>
20#include <drm/drm_gem_framebuffer_helper.h> 21#include <drm/drm_gem_framebuffer_helper.h>
21#include <drm/tinydrm/mipi-dbi.h> 22#include <drm/tinydrm/mipi-dbi.h>
22#include <drm/tinydrm/tinydrm-helpers.h> 23#include <drm/tinydrm/tinydrm-helpers.h>
@@ -320,7 +321,7 @@ static struct drm_driver st7586_driver = {
320 DRIVER_ATOMIC, 321 DRIVER_ATOMIC,
321 .fops = &st7586_fops, 322 .fops = &st7586_fops,
322 TINYDRM_GEM_DRIVER_OPS, 323 TINYDRM_GEM_DRIVER_OPS,
323 .lastclose = tinydrm_lastclose, 324 .lastclose = drm_fb_helper_lastclose,
324 .debugfs_init = mipi_dbi_debugfs_init, 325 .debugfs_init = mipi_dbi_debugfs_init,
325 .name = "st7586", 326 .name = "st7586",
326 .desc = "Sitronix ST7586", 327 .desc = "Sitronix ST7586",
diff --git a/drivers/gpu/drm/tve200/tve200_drm.h b/drivers/gpu/drm/tve200/tve200_drm.h
index 628b79324c48..5c270055bd58 100644
--- a/drivers/gpu/drm/tve200/tve200_drm.h
+++ b/drivers/gpu/drm/tve200/tve200_drm.h
@@ -103,7 +103,6 @@ struct tve200_drm_dev_private {
103 struct drm_panel *panel; 103 struct drm_panel *panel;
104 struct drm_bridge *bridge; 104 struct drm_bridge *bridge;
105 struct drm_simple_display_pipe pipe; 105 struct drm_simple_display_pipe pipe;
106 struct drm_fbdev_cma *fbdev;
107 106
108 void *regs; 107 void *regs;
109 struct clk *pclk; 108 struct clk *pclk;
diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c
index bd6c9454d767..44911d921864 100644
--- a/drivers/gpu/drm/tve200/tve200_drv.c
+++ b/drivers/gpu/drm/tve200/tve200_drv.c
@@ -46,6 +46,7 @@
46#include <drm/drm_crtc_helper.h> 46#include <drm/drm_crtc_helper.h>
47#include <drm/drm_gem_cma_helper.h> 47#include <drm/drm_gem_cma_helper.h>
48#include <drm/drm_gem_framebuffer_helper.h> 48#include <drm/drm_gem_framebuffer_helper.h>
49#include <drm/drm_fb_helper.h>
49#include <drm/drm_fb_cma_helper.h> 50#include <drm/drm_fb_cma_helper.h>
50#include <drm/drm_panel.h> 51#include <drm/drm_panel.h>
51#include <drm/drm_of.h> 52#include <drm/drm_of.h>
@@ -130,8 +131,7 @@ static int tve200_modeset_init(struct drm_device *dev)
130 * Passing in 16 here will make the RGB656 mode the default 131 * Passing in 16 here will make the RGB656 mode the default
131 * Passing in 32 will use XRGB8888 mode 132 * Passing in 32 will use XRGB8888 mode
132 */ 133 */
133 priv->fbdev = drm_fbdev_cma_init(dev, 16, 134 drm_fb_cma_fbdev_init(dev, 16, 0);
134 dev->mode_config.num_connector);
135 drm_kms_helper_poll_init(dev); 135 drm_kms_helper_poll_init(dev);
136 136
137 goto finish; 137 goto finish;
@@ -146,17 +146,10 @@ finish:
146 146
147DEFINE_DRM_GEM_CMA_FOPS(drm_fops); 147DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
148 148
149static void tve200_lastclose(struct drm_device *dev)
150{
151 struct tve200_drm_dev_private *priv = dev->dev_private;
152
153 drm_fbdev_cma_restore_mode(priv->fbdev);
154}
155
156static struct drm_driver tve200_drm_driver = { 149static struct drm_driver tve200_drm_driver = {
157 .driver_features = 150 .driver_features =
158 DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, 151 DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
159 .lastclose = tve200_lastclose, 152 .lastclose = drm_fb_helper_lastclose,
160 .ioctls = NULL, 153 .ioctls = NULL,
161 .fops = &drm_fops, 154 .fops = &drm_fops,
162 .name = "tve200", 155 .name = "tve200",
@@ -270,8 +263,7 @@ static int tve200_remove(struct platform_device *pdev)
270 struct tve200_drm_dev_private *priv = drm->dev_private; 263 struct tve200_drm_dev_private *priv = drm->dev_private;
271 264
272 drm_dev_unregister(drm); 265 drm_dev_unregister(drm);
273 if (priv->fbdev) 266 drm_fb_cma_fbdev_fini(drm);
274 drm_fbdev_cma_fini(priv->fbdev);
275 if (priv->panel) 267 if (priv->panel)
276 drm_panel_bridge_remove(priv->bridge); 268 drm_panel_bridge_remove(priv->bridge);
277 drm_mode_config_cleanup(drm); 269 drm_mode_config_cleanup(drm);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index e3c29729da2e..ceb385fd69c5 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -111,13 +111,6 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data,
111 return 0; 111 return 0;
112} 112}
113 113
114static void vc4_lastclose(struct drm_device *dev)
115{
116 struct vc4_dev *vc4 = to_vc4_dev(dev);
117
118 drm_fbdev_cma_restore_mode(vc4->fbdev);
119}
120
121static const struct vm_operations_struct vc4_vm_ops = { 114static const struct vm_operations_struct vc4_vm_ops = {
122 .fault = vc4_fault, 115 .fault = vc4_fault,
123 .open = drm_gem_vm_open, 116 .open = drm_gem_vm_open,
@@ -159,7 +152,7 @@ static struct drm_driver vc4_drm_driver = {
159 DRIVER_HAVE_IRQ | 152 DRIVER_HAVE_IRQ |
160 DRIVER_RENDER | 153 DRIVER_RENDER |
161 DRIVER_PRIME), 154 DRIVER_PRIME),
162 .lastclose = vc4_lastclose, 155 .lastclose = drm_fb_helper_lastclose,
163 .irq_handler = vc4_irq, 156 .irq_handler = vc4_irq,
164 .irq_preinstall = vc4_irq_preinstall, 157 .irq_preinstall = vc4_irq_preinstall,
165 .irq_postinstall = vc4_irq_postinstall, 158 .irq_postinstall = vc4_irq_postinstall,
@@ -301,12 +294,10 @@ static void vc4_drm_unbind(struct device *dev)
301{ 294{
302 struct platform_device *pdev = to_platform_device(dev); 295 struct platform_device *pdev = to_platform_device(dev);
303 struct drm_device *drm = platform_get_drvdata(pdev); 296 struct drm_device *drm = platform_get_drvdata(pdev);
304 struct vc4_dev *vc4 = to_vc4_dev(drm);
305 297
306 drm_dev_unregister(drm); 298 drm_dev_unregister(drm);
307 299
308 if (vc4->fbdev) 300 drm_fb_cma_fbdev_fini(drm);
309 drm_fbdev_cma_fini(vc4->fbdev);
310 301
311 drm_mode_config_cleanup(drm); 302 drm_mode_config_cleanup(drm);
312 303
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 9c0d380c96f2..3af22936d9b3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -39,8 +39,6 @@ struct vc4_dev {
39 struct vc4_dsi *dsi1; 39 struct vc4_dsi *dsi1;
40 struct vc4_vec *vec; 40 struct vc4_vec *vec;
41 41
42 struct drm_fbdev_cma *fbdev;
43
44 struct vc4_hang_state *hang_state; 42 struct vc4_hang_state *hang_state;
45 43
46 /* The kernel-space BO cache. Tracks buffers that have been 44 /* The kernel-space BO cache. Tracks buffers that have been
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 50c4959b5bd3..4256f294c346 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -19,17 +19,11 @@
19#include <drm/drm_atomic_helper.h> 19#include <drm/drm_atomic_helper.h>
20#include <drm/drm_crtc_helper.h> 20#include <drm/drm_crtc_helper.h>
21#include <drm/drm_plane_helper.h> 21#include <drm/drm_plane_helper.h>
22#include <drm/drm_fb_helper.h>
22#include <drm/drm_fb_cma_helper.h> 23#include <drm/drm_fb_cma_helper.h>
23#include <drm/drm_gem_framebuffer_helper.h> 24#include <drm/drm_gem_framebuffer_helper.h>
24#include "vc4_drv.h" 25#include "vc4_drv.h"
25 26
26static void vc4_output_poll_changed(struct drm_device *dev)
27{
28 struct vc4_dev *vc4 = to_vc4_dev(dev);
29
30 drm_fbdev_cma_hotplug_event(vc4->fbdev);
31}
32
33static void 27static void
34vc4_atomic_complete_commit(struct drm_atomic_state *state) 28vc4_atomic_complete_commit(struct drm_atomic_state *state)
35{ 29{
@@ -194,7 +188,7 @@ static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
194} 188}
195 189
196static const struct drm_mode_config_funcs vc4_mode_funcs = { 190static const struct drm_mode_config_funcs vc4_mode_funcs = {
197 .output_poll_changed = vc4_output_poll_changed, 191 .output_poll_changed = drm_fb_helper_output_poll_changed,
198 .atomic_check = drm_atomic_helper_check, 192 .atomic_check = drm_atomic_helper_check,
199 .atomic_commit = vc4_atomic_commit, 193 .atomic_commit = vc4_atomic_commit,
200 .fb_create = vc4_fb_create, 194 .fb_create = vc4_fb_create,
@@ -224,12 +218,8 @@ int vc4_kms_load(struct drm_device *dev)
224 218
225 drm_mode_config_reset(dev); 219 drm_mode_config_reset(dev);
226 220
227 if (dev->mode_config.num_connector) { 221 if (dev->mode_config.num_connector)
228 vc4->fbdev = drm_fbdev_cma_init(dev, 32, 222 drm_fb_cma_fbdev_init(dev, 32, 0);
229 dev->mode_config.num_connector);
230 if (IS_ERR(vc4->fbdev))
231 vc4->fbdev = NULL;
232 }
233 223
234 drm_kms_helper_poll_init(dev); 224 drm_kms_helper_poll_init(dev);
235 225
diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c
index e8b8266c0cde..6f4205e80378 100644
--- a/drivers/gpu/drm/zte/zx_drm_drv.c
+++ b/drivers/gpu/drm/zte/zx_drm_drv.c
@@ -29,37 +29,19 @@
29#include "zx_drm_drv.h" 29#include "zx_drm_drv.h"
30#include "zx_vou.h" 30#include "zx_vou.h"
31 31
32struct zx_drm_private {
33 struct drm_fbdev_cma *fbdev;
34};
35
36static void zx_drm_fb_output_poll_changed(struct drm_device *drm)
37{
38 struct zx_drm_private *priv = drm->dev_private;
39
40 drm_fbdev_cma_hotplug_event(priv->fbdev);
41}
42
43static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = { 32static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = {
44 .fb_create = drm_gem_fb_create, 33 .fb_create = drm_gem_fb_create,
45 .output_poll_changed = zx_drm_fb_output_poll_changed, 34 .output_poll_changed = drm_fb_helper_output_poll_changed,
46 .atomic_check = drm_atomic_helper_check, 35 .atomic_check = drm_atomic_helper_check,
47 .atomic_commit = drm_atomic_helper_commit, 36 .atomic_commit = drm_atomic_helper_commit,
48}; 37};
49 38
50static void zx_drm_lastclose(struct drm_device *drm)
51{
52 struct zx_drm_private *priv = drm->dev_private;
53
54 drm_fbdev_cma_restore_mode(priv->fbdev);
55}
56
57DEFINE_DRM_GEM_CMA_FOPS(zx_drm_fops); 39DEFINE_DRM_GEM_CMA_FOPS(zx_drm_fops);
58 40
59static struct drm_driver zx_drm_driver = { 41static struct drm_driver zx_drm_driver = {
60 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | 42 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
61 DRIVER_ATOMIC, 43 DRIVER_ATOMIC,
62 .lastclose = zx_drm_lastclose, 44 .lastclose = drm_fb_helper_lastclose,
63 .gem_free_object_unlocked = drm_gem_cma_free_object, 45 .gem_free_object_unlocked = drm_gem_cma_free_object,
64 .gem_vm_ops = &drm_gem_cma_vm_ops, 46 .gem_vm_ops = &drm_gem_cma_vm_ops,
65 .dumb_create = drm_gem_cma_dumb_create, 47 .dumb_create = drm_gem_cma_dumb_create,
@@ -83,18 +65,12 @@ static struct drm_driver zx_drm_driver = {
83static int zx_drm_bind(struct device *dev) 65static int zx_drm_bind(struct device *dev)
84{ 66{
85 struct drm_device *drm; 67 struct drm_device *drm;
86 struct zx_drm_private *priv;
87 int ret; 68 int ret;
88 69
89 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
90 if (!priv)
91 return -ENOMEM;
92
93 drm = drm_dev_alloc(&zx_drm_driver, dev); 70 drm = drm_dev_alloc(&zx_drm_driver, dev);
94 if (IS_ERR(drm)) 71 if (IS_ERR(drm))
95 return PTR_ERR(drm); 72 return PTR_ERR(drm);
96 73
97 drm->dev_private = priv;
98 dev_set_drvdata(dev, drm); 74 dev_set_drvdata(dev, drm);
99 75
100 drm_mode_config_init(drm); 76 drm_mode_config_init(drm);
@@ -125,12 +101,9 @@ static int zx_drm_bind(struct device *dev)
125 drm_mode_config_reset(drm); 101 drm_mode_config_reset(drm);
126 drm_kms_helper_poll_init(drm); 102 drm_kms_helper_poll_init(drm);
127 103
128 priv->fbdev = drm_fbdev_cma_init(drm, 32, 104 ret = drm_fb_cma_fbdev_init(drm, 32, 0);
129 drm->mode_config.num_connector); 105 if (ret) {
130 if (IS_ERR(priv->fbdev)) {
131 ret = PTR_ERR(priv->fbdev);
132 DRM_DEV_ERROR(dev, "failed to init cma fbdev: %d\n", ret); 106 DRM_DEV_ERROR(dev, "failed to init cma fbdev: %d\n", ret);
133 priv->fbdev = NULL;
134 goto out_poll_fini; 107 goto out_poll_fini;
135 } 108 }
136 109
@@ -141,10 +114,7 @@ static int zx_drm_bind(struct device *dev)
141 return 0; 114 return 0;
142 115
143out_fbdev_fini: 116out_fbdev_fini:
144 if (priv->fbdev) { 117 drm_fb_cma_fbdev_fini(drm);
145 drm_fbdev_cma_fini(priv->fbdev);
146 priv->fbdev = NULL;
147 }
148out_poll_fini: 118out_poll_fini:
149 drm_kms_helper_poll_fini(drm); 119 drm_kms_helper_poll_fini(drm);
150 drm_mode_config_cleanup(drm); 120 drm_mode_config_cleanup(drm);
@@ -152,7 +122,6 @@ out_unbind:
152 component_unbind_all(dev, drm); 122 component_unbind_all(dev, drm);
153out_unregister: 123out_unregister:
154 dev_set_drvdata(dev, NULL); 124 dev_set_drvdata(dev, NULL);
155 drm->dev_private = NULL;
156 drm_dev_unref(drm); 125 drm_dev_unref(drm);
157 return ret; 126 return ret;
158} 127}
@@ -160,18 +129,13 @@ out_unregister:
160static void zx_drm_unbind(struct device *dev) 129static void zx_drm_unbind(struct device *dev)
161{ 130{
162 struct drm_device *drm = dev_get_drvdata(dev); 131 struct drm_device *drm = dev_get_drvdata(dev);
163 struct zx_drm_private *priv = drm->dev_private;
164 132
165 drm_dev_unregister(drm); 133 drm_dev_unregister(drm);
166 if (priv->fbdev) { 134 drm_fb_cma_fbdev_fini(drm);
167 drm_fbdev_cma_fini(priv->fbdev);
168 priv->fbdev = NULL;
169 }
170 drm_kms_helper_poll_fini(drm); 135 drm_kms_helper_poll_fini(drm);
171 drm_mode_config_cleanup(drm); 136 drm_mode_config_cleanup(drm);
172 component_unbind_all(dev, drm); 137 component_unbind_all(dev, drm);
173 dev_set_drvdata(dev, NULL); 138 dev_set_drvdata(dev, NULL);
174 drm->dev_private = NULL;
175 drm_dev_unref(drm); 139 drm_dev_unref(drm);
176} 140}
177 141