0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <linux/async.h>
0028 #include <linux/console.h>
0029 #include <linux/delay.h>
0030 #include <linux/errno.h>
0031 #include <linux/init.h>
0032 #include <linux/kernel.h>
0033 #include <linux/mm.h>
0034 #include <linux/module.h>
0035 #include <linux/string.h>
0036 #include <linux/sysrq.h>
0037 #include <linux/tty.h>
0038 #include <linux/vga_switcheroo.h>
0039
0040 #include <drm/drm_crtc.h>
0041 #include <drm/drm_fb_helper.h>
0042 #include <drm/drm_fourcc.h>
0043
0044 #include "gem/i915_gem_lmem.h"
0045
0046 #include "i915_drv.h"
0047 #include "intel_display_types.h"
0048 #include "intel_fb.h"
0049 #include "intel_fb_pin.h"
0050 #include "intel_fbdev.h"
0051 #include "intel_frontbuffer.h"
0052
0053 struct intel_fbdev {
0054 struct drm_fb_helper helper;
0055 struct intel_framebuffer *fb;
0056 struct i915_vma *vma;
0057 unsigned long vma_flags;
0058 async_cookie_t cookie;
0059 int preferred_bpp;
0060
0061
0062 bool hpd_suspended: 1;
0063
0064 bool hpd_waiting: 1;
0065
0066
0067 struct mutex hpd_lock;
0068 };
0069
0070 static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
0071 {
0072 return ifbdev->fb->frontbuffer;
0073 }
0074
0075 static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
0076 {
0077 intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
0078 }
0079
0080 static int intel_fbdev_set_par(struct fb_info *info)
0081 {
0082 struct drm_fb_helper *fb_helper = info->par;
0083 struct intel_fbdev *ifbdev =
0084 container_of(fb_helper, struct intel_fbdev, helper);
0085 int ret;
0086
0087 ret = drm_fb_helper_set_par(info);
0088 if (ret == 0)
0089 intel_fbdev_invalidate(ifbdev);
0090
0091 return ret;
0092 }
0093
0094 static int intel_fbdev_blank(int blank, struct fb_info *info)
0095 {
0096 struct drm_fb_helper *fb_helper = info->par;
0097 struct intel_fbdev *ifbdev =
0098 container_of(fb_helper, struct intel_fbdev, helper);
0099 int ret;
0100
0101 ret = drm_fb_helper_blank(blank, info);
0102 if (ret == 0)
0103 intel_fbdev_invalidate(ifbdev);
0104
0105 return ret;
0106 }
0107
0108 static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
0109 struct fb_info *info)
0110 {
0111 struct drm_fb_helper *fb_helper = info->par;
0112 struct intel_fbdev *ifbdev =
0113 container_of(fb_helper, struct intel_fbdev, helper);
0114 int ret;
0115
0116 ret = drm_fb_helper_pan_display(var, info);
0117 if (ret == 0)
0118 intel_fbdev_invalidate(ifbdev);
0119
0120 return ret;
0121 }
0122
0123 static const struct fb_ops intelfb_ops = {
0124 .owner = THIS_MODULE,
0125 DRM_FB_HELPER_DEFAULT_OPS,
0126 .fb_set_par = intel_fbdev_set_par,
0127 .fb_fillrect = drm_fb_helper_cfb_fillrect,
0128 .fb_copyarea = drm_fb_helper_cfb_copyarea,
0129 .fb_imageblit = drm_fb_helper_cfb_imageblit,
0130 .fb_pan_display = intel_fbdev_pan_display,
0131 .fb_blank = intel_fbdev_blank,
0132 };
0133
0134 static int intelfb_alloc(struct drm_fb_helper *helper,
0135 struct drm_fb_helper_surface_size *sizes)
0136 {
0137 struct intel_fbdev *ifbdev =
0138 container_of(helper, struct intel_fbdev, helper);
0139 struct drm_framebuffer *fb;
0140 struct drm_device *dev = helper->dev;
0141 struct drm_i915_private *dev_priv = to_i915(dev);
0142 struct drm_mode_fb_cmd2 mode_cmd = {};
0143 struct drm_i915_gem_object *obj;
0144 int size;
0145
0146
0147 if (sizes->surface_bpp == 24)
0148 sizes->surface_bpp = 32;
0149
0150 mode_cmd.width = sizes->surface_width;
0151 mode_cmd.height = sizes->surface_height;
0152
0153 mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
0154 DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
0155 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
0156 sizes->surface_depth);
0157
0158 size = mode_cmd.pitches[0] * mode_cmd.height;
0159 size = PAGE_ALIGN(size);
0160
0161 obj = ERR_PTR(-ENODEV);
0162 if (HAS_LMEM(dev_priv)) {
0163 obj = i915_gem_object_create_lmem(dev_priv, size,
0164 I915_BO_ALLOC_CONTIGUOUS);
0165 } else {
0166
0167
0168
0169
0170
0171 if (size * 2 < dev_priv->stolen_usable_size)
0172 obj = i915_gem_object_create_stolen(dev_priv, size);
0173 if (IS_ERR(obj))
0174 obj = i915_gem_object_create_shmem(dev_priv, size);
0175 }
0176
0177 if (IS_ERR(obj)) {
0178 drm_err(&dev_priv->drm, "failed to allocate framebuffer\n");
0179 return PTR_ERR(obj);
0180 }
0181
0182 fb = intel_framebuffer_create(obj, &mode_cmd);
0183 i915_gem_object_put(obj);
0184 if (IS_ERR(fb))
0185 return PTR_ERR(fb);
0186
0187 ifbdev->fb = to_intel_framebuffer(fb);
0188 return 0;
0189 }
0190
0191 static int intelfb_create(struct drm_fb_helper *helper,
0192 struct drm_fb_helper_surface_size *sizes)
0193 {
0194 struct intel_fbdev *ifbdev =
0195 container_of(helper, struct intel_fbdev, helper);
0196 struct intel_framebuffer *intel_fb = ifbdev->fb;
0197 struct drm_device *dev = helper->dev;
0198 struct drm_i915_private *dev_priv = to_i915(dev);
0199 struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
0200 struct i915_ggtt *ggtt = to_gt(dev_priv)->ggtt;
0201 const struct i915_ggtt_view view = {
0202 .type = I915_GGTT_VIEW_NORMAL,
0203 };
0204 intel_wakeref_t wakeref;
0205 struct fb_info *info;
0206 struct i915_vma *vma;
0207 unsigned long flags = 0;
0208 bool prealloc = false;
0209 void __iomem *vaddr;
0210 struct drm_i915_gem_object *obj;
0211 int ret;
0212
0213 if (intel_fb &&
0214 (sizes->fb_width > intel_fb->base.width ||
0215 sizes->fb_height > intel_fb->base.height)) {
0216 drm_dbg_kms(&dev_priv->drm,
0217 "BIOS fb too small (%dx%d), we require (%dx%d),"
0218 " releasing it\n",
0219 intel_fb->base.width, intel_fb->base.height,
0220 sizes->fb_width, sizes->fb_height);
0221 drm_framebuffer_put(&intel_fb->base);
0222 intel_fb = ifbdev->fb = NULL;
0223 }
0224 if (!intel_fb || drm_WARN_ON(dev, !intel_fb_obj(&intel_fb->base))) {
0225 drm_dbg_kms(&dev_priv->drm,
0226 "no BIOS fb, allocating a new one\n");
0227 ret = intelfb_alloc(helper, sizes);
0228 if (ret)
0229 return ret;
0230 intel_fb = ifbdev->fb;
0231 } else {
0232 drm_dbg_kms(&dev_priv->drm, "re-using BIOS fb\n");
0233 prealloc = true;
0234 sizes->fb_width = intel_fb->base.width;
0235 sizes->fb_height = intel_fb->base.height;
0236 }
0237
0238 wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
0239
0240
0241
0242
0243
0244 vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, false,
0245 &view, false, &flags);
0246 if (IS_ERR(vma)) {
0247 ret = PTR_ERR(vma);
0248 goto out_unlock;
0249 }
0250
0251 info = drm_fb_helper_alloc_fbi(helper);
0252 if (IS_ERR(info)) {
0253 drm_err(&dev_priv->drm, "Failed to allocate fb_info\n");
0254 ret = PTR_ERR(info);
0255 goto out_unpin;
0256 }
0257
0258 ifbdev->helper.fb = &ifbdev->fb->base;
0259
0260 info->fbops = &intelfb_ops;
0261
0262
0263 obj = intel_fb_obj(&intel_fb->base);
0264 if (i915_gem_object_is_lmem(obj)) {
0265 struct intel_memory_region *mem = obj->mm.region;
0266
0267 info->apertures->ranges[0].base = mem->io_start;
0268 info->apertures->ranges[0].size = mem->io_size;
0269
0270
0271 info->fix.smem_start =
0272 (unsigned long)(mem->io_start +
0273 i915_gem_object_get_dma_address(obj, 0));
0274 info->fix.smem_len = obj->base.size;
0275 } else {
0276 info->apertures->ranges[0].base = ggtt->gmadr.start;
0277 info->apertures->ranges[0].size = ggtt->mappable_end;
0278
0279
0280 info->fix.smem_start =
0281 (unsigned long)(ggtt->gmadr.start + vma->node.start);
0282 info->fix.smem_len = vma->size;
0283 }
0284
0285 vaddr = i915_vma_pin_iomap(vma);
0286 if (IS_ERR(vaddr)) {
0287 drm_err(&dev_priv->drm,
0288 "Failed to remap framebuffer into virtual memory\n");
0289 ret = PTR_ERR(vaddr);
0290 goto out_unpin;
0291 }
0292 info->screen_base = vaddr;
0293 info->screen_size = vma->size;
0294
0295 drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
0296
0297
0298
0299
0300
0301 if (!i915_gem_object_is_shmem(vma->obj) && !prealloc)
0302 memset_io(info->screen_base, 0, info->screen_size);
0303
0304
0305
0306 drm_dbg_kms(&dev_priv->drm, "allocated %dx%d fb: 0x%08x\n",
0307 ifbdev->fb->base.width, ifbdev->fb->base.height,
0308 i915_ggtt_offset(vma));
0309 ifbdev->vma = vma;
0310 ifbdev->vma_flags = flags;
0311
0312 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
0313 vga_switcheroo_client_fb_set(pdev, info);
0314 return 0;
0315
0316 out_unpin:
0317 intel_unpin_fb_vma(vma, flags);
0318 out_unlock:
0319 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
0320 return ret;
0321 }
0322
0323 static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
0324 .fb_probe = intelfb_create,
0325 };
0326
0327 static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
0328 {
0329
0330
0331
0332
0333
0334 drm_fb_helper_fini(&ifbdev->helper);
0335
0336 if (ifbdev->vma)
0337 intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags);
0338
0339 if (ifbdev->fb)
0340 drm_framebuffer_remove(&ifbdev->fb->base);
0341
0342 kfree(ifbdev);
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 static bool intel_fbdev_init_bios(struct drm_device *dev,
0355 struct intel_fbdev *ifbdev)
0356 {
0357 struct drm_i915_private *i915 = to_i915(dev);
0358 struct intel_framebuffer *fb = NULL;
0359 struct intel_crtc *crtc;
0360 unsigned int max_size = 0;
0361
0362
0363 for_each_intel_crtc(dev, crtc) {
0364 struct intel_crtc_state *crtc_state =
0365 to_intel_crtc_state(crtc->base.state);
0366 struct intel_plane *plane =
0367 to_intel_plane(crtc->base.primary);
0368 struct intel_plane_state *plane_state =
0369 to_intel_plane_state(plane->base.state);
0370 struct drm_i915_gem_object *obj =
0371 intel_fb_obj(plane_state->uapi.fb);
0372
0373 if (!crtc_state->uapi.active) {
0374 drm_dbg_kms(&i915->drm,
0375 "[CRTC:%d:%s] not active, skipping\n",
0376 crtc->base.base.id, crtc->base.name);
0377 continue;
0378 }
0379
0380 if (!obj) {
0381 drm_dbg_kms(&i915->drm,
0382 "[PLANE:%d:%s] no fb, skipping\n",
0383 plane->base.base.id, plane->base.name);
0384 continue;
0385 }
0386
0387 if (obj->base.size > max_size) {
0388 drm_dbg_kms(&i915->drm,
0389 "found possible fb from [PLANE:%d:%s]\n",
0390 plane->base.base.id, plane->base.name);
0391 fb = to_intel_framebuffer(plane_state->uapi.fb);
0392 max_size = obj->base.size;
0393 }
0394 }
0395
0396 if (!fb) {
0397 drm_dbg_kms(&i915->drm,
0398 "no active fbs found, not using BIOS config\n");
0399 goto out;
0400 }
0401
0402
0403 for_each_intel_crtc(dev, crtc) {
0404 struct intel_crtc_state *crtc_state =
0405 to_intel_crtc_state(crtc->base.state);
0406 struct intel_plane *plane =
0407 to_intel_plane(crtc->base.primary);
0408 unsigned int cur_size;
0409
0410 if (!crtc_state->uapi.active) {
0411 drm_dbg_kms(&i915->drm,
0412 "[CRTC:%d:%s] not active, skipping\n",
0413 crtc->base.base.id, crtc->base.name);
0414 continue;
0415 }
0416
0417 drm_dbg_kms(&i915->drm, "checking [PLANE:%d:%s] for BIOS fb\n",
0418 plane->base.base.id, plane->base.name);
0419
0420
0421
0422
0423
0424
0425 cur_size = crtc_state->uapi.adjusted_mode.crtc_hdisplay;
0426 cur_size = cur_size * fb->base.format->cpp[0];
0427 if (fb->base.pitches[0] < cur_size) {
0428 drm_dbg_kms(&i915->drm,
0429 "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n",
0430 plane->base.base.id, plane->base.name,
0431 cur_size, fb->base.pitches[0]);
0432 fb = NULL;
0433 break;
0434 }
0435
0436 cur_size = crtc_state->uapi.adjusted_mode.crtc_vdisplay;
0437 cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
0438 cur_size *= fb->base.pitches[0];
0439 drm_dbg_kms(&i915->drm,
0440 "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n",
0441 crtc->base.base.id, crtc->base.name,
0442 crtc_state->uapi.adjusted_mode.crtc_hdisplay,
0443 crtc_state->uapi.adjusted_mode.crtc_vdisplay,
0444 fb->base.format->cpp[0] * 8,
0445 cur_size);
0446
0447 if (cur_size > max_size) {
0448 drm_dbg_kms(&i915->drm,
0449 "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n",
0450 plane->base.base.id, plane->base.name,
0451 cur_size, max_size);
0452 fb = NULL;
0453 break;
0454 }
0455
0456 drm_dbg_kms(&i915->drm,
0457 "fb big enough [PLANE:%d:%s] (%d >= %d)\n",
0458 plane->base.base.id, plane->base.name,
0459 max_size, cur_size);
0460 }
0461
0462 if (!fb) {
0463 drm_dbg_kms(&i915->drm,
0464 "BIOS fb not suitable for all pipes, not using\n");
0465 goto out;
0466 }
0467
0468 ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8;
0469 ifbdev->fb = fb;
0470
0471 drm_framebuffer_get(&ifbdev->fb->base);
0472
0473
0474 for_each_intel_crtc(dev, crtc) {
0475 struct intel_crtc_state *crtc_state =
0476 to_intel_crtc_state(crtc->base.state);
0477 struct intel_plane *plane =
0478 to_intel_plane(crtc->base.primary);
0479 struct intel_plane_state *plane_state =
0480 to_intel_plane_state(plane->base.state);
0481
0482 if (!crtc_state->uapi.active)
0483 continue;
0484
0485 drm_WARN(dev, !plane_state->uapi.fb,
0486 "re-used BIOS config but lost an fb on [PLANE:%d:%s]\n",
0487 plane->base.base.id, plane->base.name);
0488 }
0489
0490
0491 drm_dbg_kms(&i915->drm, "using BIOS fb for initial console\n");
0492 return true;
0493
0494 out:
0495
0496 return false;
0497 }
0498
0499 static void intel_fbdev_suspend_worker(struct work_struct *work)
0500 {
0501 intel_fbdev_set_suspend(&container_of(work,
0502 struct drm_i915_private,
0503 fbdev_suspend_work)->drm,
0504 FBINFO_STATE_RUNNING,
0505 true);
0506 }
0507
0508 int intel_fbdev_init(struct drm_device *dev)
0509 {
0510 struct drm_i915_private *dev_priv = to_i915(dev);
0511 struct intel_fbdev *ifbdev;
0512 int ret;
0513
0514 if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv)))
0515 return -ENODEV;
0516
0517 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
0518 if (ifbdev == NULL)
0519 return -ENOMEM;
0520
0521 mutex_init(&ifbdev->hpd_lock);
0522 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
0523
0524 if (!intel_fbdev_init_bios(dev, ifbdev))
0525 ifbdev->preferred_bpp = 32;
0526
0527 ret = drm_fb_helper_init(dev, &ifbdev->helper);
0528 if (ret) {
0529 kfree(ifbdev);
0530 return ret;
0531 }
0532
0533 dev_priv->fbdev = ifbdev;
0534 INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
0535
0536 return 0;
0537 }
0538
0539 static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
0540 {
0541 struct intel_fbdev *ifbdev = data;
0542
0543
0544 if (drm_fb_helper_initial_config(&ifbdev->helper,
0545 ifbdev->preferred_bpp))
0546 intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
0547 }
0548
0549 void intel_fbdev_initial_config_async(struct drm_device *dev)
0550 {
0551 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
0552
0553 if (!ifbdev)
0554 return;
0555
0556 ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
0557 }
0558
0559 static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
0560 {
0561 if (!ifbdev->cookie)
0562 return;
0563
0564
0565 async_synchronize_cookie(ifbdev->cookie + 1);
0566 ifbdev->cookie = 0;
0567 }
0568
0569 void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
0570 {
0571 struct intel_fbdev *ifbdev = dev_priv->fbdev;
0572
0573 if (!ifbdev)
0574 return;
0575
0576 cancel_work_sync(&dev_priv->fbdev_suspend_work);
0577 if (!current_is_async())
0578 intel_fbdev_sync(ifbdev);
0579
0580 drm_fb_helper_unregister_fbi(&ifbdev->helper);
0581 }
0582
0583 void intel_fbdev_fini(struct drm_i915_private *dev_priv)
0584 {
0585 struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->fbdev);
0586
0587 if (!ifbdev)
0588 return;
0589
0590 intel_fbdev_destroy(ifbdev);
0591 }
0592
0593
0594
0595
0596
0597 static void intel_fbdev_hpd_set_suspend(struct drm_i915_private *i915, int state)
0598 {
0599 struct intel_fbdev *ifbdev = i915->fbdev;
0600 bool send_hpd = false;
0601
0602 mutex_lock(&ifbdev->hpd_lock);
0603 ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
0604 send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
0605 ifbdev->hpd_waiting = false;
0606 mutex_unlock(&ifbdev->hpd_lock);
0607
0608 if (send_hpd) {
0609 drm_dbg_kms(&i915->drm, "Handling delayed fbcon HPD event\n");
0610 drm_fb_helper_hotplug_event(&ifbdev->helper);
0611 }
0612 }
0613
0614 void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
0615 {
0616 struct drm_i915_private *dev_priv = to_i915(dev);
0617 struct intel_fbdev *ifbdev = dev_priv->fbdev;
0618 struct fb_info *info;
0619
0620 if (!ifbdev || !ifbdev->vma)
0621 return;
0622
0623 info = ifbdev->helper.fbdev;
0624
0625 if (synchronous) {
0626
0627
0628
0629
0630
0631
0632
0633 if (state != FBINFO_STATE_RUNNING)
0634 flush_work(&dev_priv->fbdev_suspend_work);
0635
0636 console_lock();
0637 } else {
0638
0639
0640
0641
0642
0643 drm_WARN_ON(dev, state != FBINFO_STATE_RUNNING);
0644 if (!console_trylock()) {
0645
0646
0647
0648 schedule_work(&dev_priv->fbdev_suspend_work);
0649 return;
0650 }
0651 }
0652
0653
0654
0655
0656
0657 if (state == FBINFO_STATE_RUNNING &&
0658 !i915_gem_object_is_shmem(intel_fb_obj(&ifbdev->fb->base)))
0659 memset_io(info->screen_base, 0, info->screen_size);
0660
0661 drm_fb_helper_set_suspend(&ifbdev->helper, state);
0662 console_unlock();
0663
0664 intel_fbdev_hpd_set_suspend(dev_priv, state);
0665 }
0666
0667 void intel_fbdev_output_poll_changed(struct drm_device *dev)
0668 {
0669 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
0670 bool send_hpd;
0671
0672 if (!ifbdev)
0673 return;
0674
0675 intel_fbdev_sync(ifbdev);
0676
0677 mutex_lock(&ifbdev->hpd_lock);
0678 send_hpd = !ifbdev->hpd_suspended;
0679 ifbdev->hpd_waiting = true;
0680 mutex_unlock(&ifbdev->hpd_lock);
0681
0682 if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
0683 drm_fb_helper_hotplug_event(&ifbdev->helper);
0684 }
0685
0686 void intel_fbdev_restore_mode(struct drm_device *dev)
0687 {
0688 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
0689
0690 if (!ifbdev)
0691 return;
0692
0693 intel_fbdev_sync(ifbdev);
0694 if (!ifbdev->vma)
0695 return;
0696
0697 if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper) == 0)
0698 intel_fbdev_invalidate(ifbdev);
0699 }
0700
0701 struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev)
0702 {
0703 if (!fbdev || !fbdev->helper.fb)
0704 return NULL;
0705
0706 return to_intel_framebuffer(fbdev->helper.fb);
0707 }