1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/async.h>
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/console.h>
31#include <linux/errno.h>
32#include <linux/string.h>
33#include <linux/mm.h>
34#include <linux/tty.h>
35#include <linux/sysrq.h>
36#include <linux/delay.h>
37#include <linux/init.h>
38#include <linux/vga_switcheroo.h>
39
40#include <drm/drmP.h>
41#include <drm/drm_crtc.h>
42#include <drm/drm_fb_helper.h>
43#include "intel_drv.h"
44#include "intel_frontbuffer.h"
45#include <drm/i915_drm.h>
46#include "i915_drv.h"
47
48static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
49{
50 struct drm_i915_gem_object *obj = ifbdev->fb->obj;
51 unsigned int origin =
52 ifbdev->vma_flags & PLANE_HAS_FENCE ? ORIGIN_GTT : ORIGIN_CPU;
53
54 intel_fb_obj_invalidate(obj, origin);
55}
56
57static int intel_fbdev_set_par(struct fb_info *info)
58{
59 struct drm_fb_helper *fb_helper = info->par;
60 struct intel_fbdev *ifbdev =
61 container_of(fb_helper, struct intel_fbdev, helper);
62 int ret;
63
64 ret = drm_fb_helper_set_par(info);
65 if (ret == 0)
66 intel_fbdev_invalidate(ifbdev);
67
68 return ret;
69}
70
71static int intel_fbdev_blank(int blank, struct fb_info *info)
72{
73 struct drm_fb_helper *fb_helper = info->par;
74 struct intel_fbdev *ifbdev =
75 container_of(fb_helper, struct intel_fbdev, helper);
76 int ret;
77
78 ret = drm_fb_helper_blank(blank, info);
79 if (ret == 0)
80 intel_fbdev_invalidate(ifbdev);
81
82 return ret;
83}
84
85static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
86 struct fb_info *info)
87{
88 struct drm_fb_helper *fb_helper = info->par;
89 struct intel_fbdev *ifbdev =
90 container_of(fb_helper, struct intel_fbdev, helper);
91 int ret;
92
93 ret = drm_fb_helper_pan_display(var, info);
94 if (ret == 0)
95 intel_fbdev_invalidate(ifbdev);
96
97 return ret;
98}
99
100static struct fb_ops intelfb_ops = {
101 .owner = THIS_MODULE,
102 DRM_FB_HELPER_DEFAULT_OPS,
103 .fb_set_par = intel_fbdev_set_par,
104 .fb_fillrect = drm_fb_helper_cfb_fillrect,
105 .fb_copyarea = drm_fb_helper_cfb_copyarea,
106 .fb_imageblit = drm_fb_helper_cfb_imageblit,
107 .fb_pan_display = intel_fbdev_pan_display,
108 .fb_blank = intel_fbdev_blank,
109};
110
111static int intelfb_alloc(struct drm_fb_helper *helper,
112 struct drm_fb_helper_surface_size *sizes)
113{
114 struct intel_fbdev *ifbdev =
115 container_of(helper, struct intel_fbdev, helper);
116 struct drm_framebuffer *fb;
117 struct drm_device *dev = helper->dev;
118 struct drm_i915_private *dev_priv = to_i915(dev);
119 struct drm_mode_fb_cmd2 mode_cmd = {};
120 struct drm_i915_gem_object *obj;
121 int size, ret;
122
123
124 if (sizes->surface_bpp == 24)
125 sizes->surface_bpp = 32;
126
127 mode_cmd.width = sizes->surface_width;
128 mode_cmd.height = sizes->surface_height;
129
130 mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
131 DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
132 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
133 sizes->surface_depth);
134
135 size = mode_cmd.pitches[0] * mode_cmd.height;
136 size = PAGE_ALIGN(size);
137
138
139
140
141 obj = NULL;
142 if (size * 2 < dev_priv->stolen_usable_size)
143 obj = i915_gem_object_create_stolen(dev_priv, size);
144 if (obj == NULL)
145 obj = i915_gem_object_create(dev_priv, size);
146 if (IS_ERR(obj)) {
147 DRM_ERROR("failed to allocate framebuffer\n");
148 ret = PTR_ERR(obj);
149 goto err;
150 }
151
152 fb = intel_framebuffer_create(obj, &mode_cmd);
153 if (IS_ERR(fb)) {
154 ret = PTR_ERR(fb);
155 goto err_obj;
156 }
157
158 ifbdev->fb = to_intel_framebuffer(fb);
159
160 return 0;
161
162err_obj:
163 i915_gem_object_put(obj);
164err:
165 return ret;
166}
167
168static int intelfb_create(struct drm_fb_helper *helper,
169 struct drm_fb_helper_surface_size *sizes)
170{
171 struct intel_fbdev *ifbdev =
172 container_of(helper, struct intel_fbdev, helper);
173 struct intel_framebuffer *intel_fb = ifbdev->fb;
174 struct drm_device *dev = helper->dev;
175 struct drm_i915_private *dev_priv = to_i915(dev);
176 struct pci_dev *pdev = dev_priv->drm.pdev;
177 struct i915_ggtt *ggtt = &dev_priv->ggtt;
178 struct fb_info *info;
179 struct drm_framebuffer *fb;
180 struct i915_vma *vma;
181 unsigned long flags = 0;
182 bool prealloc = false;
183 void __iomem *vaddr;
184 int ret;
185
186 if (intel_fb &&
187 (sizes->fb_width > intel_fb->base.width ||
188 sizes->fb_height > intel_fb->base.height)) {
189 DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d),"
190 " releasing it\n",
191 intel_fb->base.width, intel_fb->base.height,
192 sizes->fb_width, sizes->fb_height);
193 drm_framebuffer_put(&intel_fb->base);
194 intel_fb = ifbdev->fb = NULL;
195 }
196 if (!intel_fb || WARN_ON(!intel_fb->obj)) {
197 DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
198 ret = intelfb_alloc(helper, sizes);
199 if (ret)
200 return ret;
201 intel_fb = ifbdev->fb;
202 } else {
203 DRM_DEBUG_KMS("re-using BIOS fb\n");
204 prealloc = true;
205 sizes->fb_width = intel_fb->base.width;
206 sizes->fb_height = intel_fb->base.height;
207 }
208
209 mutex_lock(&dev->struct_mutex);
210 intel_runtime_pm_get(dev_priv);
211
212
213
214
215
216 vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base,
217 DRM_MODE_ROTATE_0,
218 false, &flags);
219 if (IS_ERR(vma)) {
220 ret = PTR_ERR(vma);
221 goto out_unlock;
222 }
223
224 fb = &ifbdev->fb->base;
225 intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_DIRTYFB);
226
227 info = drm_fb_helper_alloc_fbi(helper);
228 if (IS_ERR(info)) {
229 DRM_ERROR("Failed to allocate fb_info\n");
230 ret = PTR_ERR(info);
231 goto out_unpin;
232 }
233
234 info->par = helper;
235
236 ifbdev->helper.fb = fb;
237
238 strcpy(info->fix.id, "inteldrmfb");
239
240 info->fbops = &intelfb_ops;
241
242
243 info->apertures->ranges[0].base = dev->mode_config.fb_base;
244 info->apertures->ranges[0].size = ggtt->mappable_end;
245
246 info->fix.smem_start = dev->mode_config.fb_base + i915_ggtt_offset(vma);
247 info->fix.smem_len = vma->node.size;
248
249 vaddr = i915_vma_pin_iomap(vma);
250 if (IS_ERR(vaddr)) {
251 DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
252 ret = PTR_ERR(vaddr);
253 goto out_unpin;
254 }
255 info->screen_base = vaddr;
256 info->screen_size = vma->node.size;
257
258
259 info->skip_vt_switch = true;
260
261 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
262 drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
263
264
265
266
267
268 if (intel_fb->obj->stolen && !prealloc)
269 memset_io(info->screen_base, 0, info->screen_size);
270
271
272
273 DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n",
274 fb->width, fb->height, i915_ggtt_offset(vma));
275 ifbdev->vma = vma;
276 ifbdev->vma_flags = flags;
277
278 intel_runtime_pm_put(dev_priv);
279 mutex_unlock(&dev->struct_mutex);
280 vga_switcheroo_client_fb_set(pdev, info);
281 return 0;
282
283out_unpin:
284 intel_unpin_fb_vma(vma, flags);
285out_unlock:
286 intel_runtime_pm_put(dev_priv);
287 mutex_unlock(&dev->struct_mutex);
288 return ret;
289}
290
291static struct drm_fb_helper_crtc *
292intel_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
293{
294 int i;
295
296 for (i = 0; i < fb_helper->crtc_count; i++)
297 if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
298 return &fb_helper->crtc_info[i];
299
300 return NULL;
301}
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
331 struct drm_fb_helper_crtc **crtcs,
332 struct drm_display_mode **modes,
333 struct drm_fb_offset *offsets,
334 bool *enabled, int width, int height)
335{
336 struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
337 unsigned long conn_configured, conn_seq, mask;
338 unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
339 int i, j;
340 bool *save_enabled;
341 bool fallback = true, ret = true;
342 int num_connectors_enabled = 0;
343 int num_connectors_detected = 0;
344 struct drm_modeset_acquire_ctx ctx;
345
346 save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
347 if (!save_enabled)
348 return false;
349
350 drm_modeset_acquire_init(&ctx, 0);
351
352 while (drm_modeset_lock_all_ctx(fb_helper->dev, &ctx) != 0)
353 drm_modeset_backoff(&ctx);
354
355 memcpy(save_enabled, enabled, count);
356 mask = GENMASK(count - 1, 0);
357 conn_configured = 0;
358retry:
359 conn_seq = conn_configured;
360 for (i = 0; i < count; i++) {
361 struct drm_fb_helper_connector *fb_conn;
362 struct drm_connector *connector;
363 struct drm_encoder *encoder;
364 struct drm_fb_helper_crtc *new_crtc;
365
366 fb_conn = fb_helper->connector_info[i];
367 connector = fb_conn->connector;
368
369 if (conn_configured & BIT(i))
370 continue;
371
372 if (conn_seq == 0 && !connector->has_tile)
373 continue;
374
375 if (connector->status == connector_status_connected)
376 num_connectors_detected++;
377
378 if (!enabled[i]) {
379 DRM_DEBUG_KMS("connector %s not enabled, skipping\n",
380 connector->name);
381 conn_configured |= BIT(i);
382 continue;
383 }
384
385 if (connector->force == DRM_FORCE_OFF) {
386 DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n",
387 connector->name);
388 enabled[i] = false;
389 continue;
390 }
391
392 encoder = connector->state->best_encoder;
393 if (!encoder || WARN_ON(!connector->state->crtc)) {
394 if (connector->force > DRM_FORCE_OFF)
395 goto bail;
396
397 DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n",
398 connector->name);
399 enabled[i] = false;
400 conn_configured |= BIT(i);
401 continue;
402 }
403
404 num_connectors_enabled++;
405
406 new_crtc = intel_fb_helper_crtc(fb_helper,
407 connector->state->crtc);
408
409
410
411
412
413
414 for (j = 0; j < count; j++) {
415 if (crtcs[j] == new_crtc) {
416 DRM_DEBUG_KMS("fallback: cloned configuration\n");
417 goto bail;
418 }
419 }
420
421 DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n",
422 connector->name);
423
424
425 modes[i] = drm_pick_cmdline_mode(fb_conn);
426
427
428 if (!modes[i]) {
429 DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
430 connector->name, connector->has_tile);
431 modes[i] = drm_has_preferred_mode(fb_conn, width,
432 height);
433 }
434
435
436 if (!modes[i] && !list_empty(&connector->modes)) {
437 DRM_DEBUG_KMS("using first mode listed on connector %s\n",
438 connector->name);
439 modes[i] = list_first_entry(&connector->modes,
440 struct drm_display_mode,
441 head);
442 }
443
444
445 if (!modes[i]) {
446
447
448
449
450
451
452
453
454
455
456
457
458
459 DRM_DEBUG_KMS("looking for current mode on connector %s\n",
460 connector->name);
461 modes[i] = &connector->state->crtc->mode;
462 }
463 crtcs[i] = new_crtc;
464
465 DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n",
466 connector->name,
467 connector->state->crtc->base.id,
468 connector->state->crtc->name,
469 modes[i]->hdisplay, modes[i]->vdisplay,
470 modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
471
472 fallback = false;
473 conn_configured |= BIT(i);
474 }
475
476 if ((conn_configured & mask) != mask && conn_configured != conn_seq)
477 goto retry;
478
479
480
481
482
483
484 if (num_connectors_enabled != num_connectors_detected &&
485 num_connectors_enabled < INTEL_INFO(dev_priv)->num_pipes) {
486 DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
487 DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
488 num_connectors_detected);
489 fallback = true;
490 }
491
492 if (fallback) {
493bail:
494 DRM_DEBUG_KMS("Not using firmware configuration\n");
495 memcpy(enabled, save_enabled, count);
496 ret = false;
497 }
498
499 drm_modeset_drop_locks(&ctx);
500 drm_modeset_acquire_fini(&ctx);
501
502 kfree(save_enabled);
503 return ret;
504}
505
506static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
507 .initial_config = intel_fb_initial_config,
508 .fb_probe = intelfb_create,
509};
510
511static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
512{
513
514
515
516
517
518 drm_fb_helper_fini(&ifbdev->helper);
519
520 if (ifbdev->vma) {
521 mutex_lock(&ifbdev->helper.dev->struct_mutex);
522 intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags);
523 mutex_unlock(&ifbdev->helper.dev->struct_mutex);
524 }
525
526 if (ifbdev->fb)
527 drm_framebuffer_remove(&ifbdev->fb->base);
528
529 kfree(ifbdev);
530}
531
532
533
534
535
536
537
538
539
540
541static bool intel_fbdev_init_bios(struct drm_device *dev,
542 struct intel_fbdev *ifbdev)
543{
544 struct intel_framebuffer *fb = NULL;
545 struct drm_crtc *crtc;
546 struct intel_crtc *intel_crtc;
547 unsigned int max_size = 0;
548
549
550 for_each_crtc(dev, crtc) {
551 struct drm_i915_gem_object *obj =
552 intel_fb_obj(crtc->primary->state->fb);
553 intel_crtc = to_intel_crtc(crtc);
554
555 if (!crtc->state->active || !obj) {
556 DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
557 pipe_name(intel_crtc->pipe));
558 continue;
559 }
560
561 if (obj->base.size > max_size) {
562 DRM_DEBUG_KMS("found possible fb from plane %c\n",
563 pipe_name(intel_crtc->pipe));
564 fb = to_intel_framebuffer(crtc->primary->state->fb);
565 max_size = obj->base.size;
566 }
567 }
568
569 if (!fb) {
570 DRM_DEBUG_KMS("no active fbs found, not using BIOS config\n");
571 goto out;
572 }
573
574
575 for_each_crtc(dev, crtc) {
576 unsigned int cur_size;
577
578 intel_crtc = to_intel_crtc(crtc);
579
580 if (!crtc->state->active) {
581 DRM_DEBUG_KMS("pipe %c not active, skipping\n",
582 pipe_name(intel_crtc->pipe));
583 continue;
584 }
585
586 DRM_DEBUG_KMS("checking plane %c for BIOS fb\n",
587 pipe_name(intel_crtc->pipe));
588
589
590
591
592
593
594 cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay;
595 cur_size = cur_size * fb->base.format->cpp[0];
596 if (fb->base.pitches[0] < cur_size) {
597 DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n",
598 pipe_name(intel_crtc->pipe),
599 cur_size, fb->base.pitches[0]);
600 fb = NULL;
601 break;
602 }
603
604 cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
605 cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
606 cur_size *= fb->base.pitches[0];
607 DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
608 pipe_name(intel_crtc->pipe),
609 intel_crtc->config->base.adjusted_mode.crtc_hdisplay,
610 intel_crtc->config->base.adjusted_mode.crtc_vdisplay,
611 fb->base.format->cpp[0] * 8,
612 cur_size);
613
614 if (cur_size > max_size) {
615 DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n",
616 pipe_name(intel_crtc->pipe),
617 cur_size, max_size);
618 fb = NULL;
619 break;
620 }
621
622 DRM_DEBUG_KMS("fb big enough for plane %c (%d >= %d)\n",
623 pipe_name(intel_crtc->pipe),
624 max_size, cur_size);
625 }
626
627 if (!fb) {
628 DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n");
629 goto out;
630 }
631
632 ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8;
633 ifbdev->fb = fb;
634
635 drm_framebuffer_get(&ifbdev->fb->base);
636
637
638 for_each_crtc(dev, crtc) {
639 intel_crtc = to_intel_crtc(crtc);
640
641 if (!crtc->state->active)
642 continue;
643
644 WARN(!crtc->primary->state->fb,
645 "re-used BIOS config but lost an fb on crtc %d\n",
646 crtc->base.id);
647 }
648
649
650 DRM_DEBUG_KMS("using BIOS fb for initial console\n");
651 return true;
652
653out:
654
655 return false;
656}
657
658static void intel_fbdev_suspend_worker(struct work_struct *work)
659{
660 intel_fbdev_set_suspend(&container_of(work,
661 struct drm_i915_private,
662 fbdev_suspend_work)->drm,
663 FBINFO_STATE_RUNNING,
664 true);
665}
666
667int intel_fbdev_init(struct drm_device *dev)
668{
669 struct drm_i915_private *dev_priv = to_i915(dev);
670 struct intel_fbdev *ifbdev;
671 int ret;
672
673 if (WARN_ON(INTEL_INFO(dev_priv)->num_pipes == 0))
674 return -ENODEV;
675
676 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
677 if (ifbdev == NULL)
678 return -ENOMEM;
679
680 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
681
682 if (!intel_fbdev_init_bios(dev, ifbdev))
683 ifbdev->preferred_bpp = 32;
684
685 ret = drm_fb_helper_init(dev, &ifbdev->helper, 4);
686 if (ret) {
687 kfree(ifbdev);
688 return ret;
689 }
690
691 dev_priv->fbdev = ifbdev;
692 INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
693
694 drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
695
696 return 0;
697}
698
699static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
700{
701 struct intel_fbdev *ifbdev = data;
702
703
704 if (drm_fb_helper_initial_config(&ifbdev->helper,
705 ifbdev->preferred_bpp))
706 intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
707}
708
709void intel_fbdev_initial_config_async(struct drm_device *dev)
710{
711 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
712
713 if (!ifbdev)
714 return;
715
716 ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
717}
718
719static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
720{
721 if (!ifbdev->cookie)
722 return;
723
724
725 async_synchronize_cookie(ifbdev->cookie + 1);
726 ifbdev->cookie = 0;
727}
728
729void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
730{
731 struct intel_fbdev *ifbdev = dev_priv->fbdev;
732
733 if (!ifbdev)
734 return;
735
736 cancel_work_sync(&dev_priv->fbdev_suspend_work);
737 if (!current_is_async())
738 intel_fbdev_sync(ifbdev);
739
740 drm_fb_helper_unregister_fbi(&ifbdev->helper);
741}
742
743void intel_fbdev_fini(struct drm_i915_private *dev_priv)
744{
745 struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->fbdev);
746
747 if (!ifbdev)
748 return;
749
750 intel_fbdev_destroy(ifbdev);
751}
752
753void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
754{
755 struct drm_i915_private *dev_priv = to_i915(dev);
756 struct intel_fbdev *ifbdev = dev_priv->fbdev;
757 struct fb_info *info;
758
759 if (!ifbdev || !ifbdev->vma)
760 return;
761
762 info = ifbdev->helper.fbdev;
763
764 if (synchronous) {
765
766
767
768
769
770
771
772 if (state != FBINFO_STATE_RUNNING)
773 flush_work(&dev_priv->fbdev_suspend_work);
774 console_lock();
775 } else {
776
777
778
779
780
781 WARN_ON(state != FBINFO_STATE_RUNNING);
782 if (!console_trylock()) {
783
784
785
786 schedule_work(&dev_priv->fbdev_suspend_work);
787 return;
788 }
789 }
790
791
792
793
794
795 if (state == FBINFO_STATE_RUNNING && ifbdev->fb->obj->stolen)
796 memset_io(info->screen_base, 0, info->screen_size);
797
798 drm_fb_helper_set_suspend(&ifbdev->helper, state);
799 console_unlock();
800}
801
802void intel_fbdev_output_poll_changed(struct drm_device *dev)
803{
804 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
805
806 if (!ifbdev)
807 return;
808
809 intel_fbdev_sync(ifbdev);
810 if (ifbdev->vma || ifbdev->helper.deferred_setup)
811 drm_fb_helper_hotplug_event(&ifbdev->helper);
812}
813
814void intel_fbdev_restore_mode(struct drm_device *dev)
815{
816 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
817
818 if (!ifbdev)
819 return;
820
821 intel_fbdev_sync(ifbdev);
822 if (!ifbdev->vma)
823 return;
824
825 if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper) == 0)
826 intel_fbdev_invalidate(ifbdev);
827}
828