/* * We rely on the object-free to release the VMA pinning for * the info->screen_base mmaping. Leaking the VMA is simpler than * trying to rectify all the possible error paths leading here.
*/
intel_fb_unpin_vma(ifbdev->vma, ifbdev->vma_flags);
drm_framebuffer_remove(fb_helper->fb);
/* * When resuming from hibernation, Linux restores the object's * content from swap if the buffer is backed by shmemfs. If the * object is stolen however, it will be full of whatever garbage * was left in there. Clear it to zero in this case.
*/ if (!suspend && !intel_bo_is_shmem(intel_fb_bo(fb_helper->fb)))
memset_io(info->screen_base, 0, info->screen_size);
if (fb &&
(sizes->fb_width > fb->base.width ||
sizes->fb_height > fb->base.height)) {
drm_dbg_kms(display->drm, "BIOS fb too small (%dx%d), we require (%dx%d)," " releasing it\n",
fb->base.width, fb->base.height,
sizes->fb_width, sizes->fb_height);
drm_framebuffer_put(&fb->base);
fb = NULL;
} if (!fb || drm_WARN_ON(display->drm, !intel_fb_bo(&fb->base))) {
drm_dbg_kms(display->drm, "no BIOS fb, allocating a new one\n");
fb = intel_fbdev_fb_alloc(helper, sizes); if (IS_ERR(fb)) return PTR_ERR(fb);
} else {
drm_dbg_kms(display->drm, "re-using BIOS fb\n");
prealloc = true;
sizes->fb_width = fb->base.width;
sizes->fb_height = fb->base.height;
}
wakeref = intel_display_rpm_get(display);
/* Pin the GGTT vma for our access via info->screen_base. * This also validates that any existing fb inherited from the * BIOS is suitable for own access.
*/
vma = intel_fb_pin_to_ggtt(&fb->base, &fb->normal_view.gtt,
fb->min_alignment, 0,
intel_fb_view_vtd_guard(&fb->base, &fb->normal_view,
DRM_MODE_ROTATE_0), false, &flags); if (IS_ERR(vma)) {
ret = PTR_ERR(vma); goto out_unlock;
}
info = drm_fb_helper_alloc_info(helper); if (IS_ERR(info)) {
drm_err(display->drm, "Failed to allocate fb_info (%pe)\n", info);
ret = PTR_ERR(info); goto out_unpin;
}
/* If the object is shmemfs backed, it will have given us zeroed pages. * If the object is stolen however, it will be full of whatever * garbage was left in there.
*/ if (!intel_bo_is_shmem(obj) && !prealloc)
memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
/* * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible. * The core display code will have read out the current plane configuration, * so we use that to figure out if there's an object for us to use as the * fb, and if so, we re-use it for the fbdev configuration. * * Note we only support a single fb shared across pipes for boot (mostly for * fbcon), so we just find the biggest and use that.
*/ staticbool intel_fbdev_init_bios(struct intel_display *display, struct intel_fbdev *ifbdev)
{ struct intel_framebuffer *fb = NULL; struct intel_crtc *crtc; unsignedint max_size = 0;
if (!crtc_state->uapi.active) {
drm_dbg_kms(display->drm, "[CRTC:%d:%s] not active, skipping\n",
crtc->base.base.id, crtc->base.name); continue;
}
if (!obj) {
drm_dbg_kms(display->drm, "[PLANE:%d:%s] no fb, skipping\n",
plane->base.base.id, plane->base.name); continue;
}
if (obj->size > max_size) {
drm_dbg_kms(display->drm, "found possible fb from [PLANE:%d:%s]\n",
plane->base.base.id, plane->base.name);
fb = to_intel_framebuffer(plane_state->uapi.fb);
max_size = obj->size;
}
}
if (!fb) {
drm_dbg_kms(display->drm, "no active fbs found, not using BIOS config\n"); goto out;
}
/* Now make sure all the pipes will fit into it */
for_each_intel_crtc(display->drm, crtc) { struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state); struct intel_plane *plane =
to_intel_plane(crtc->base.primary); unsignedint cur_size;
if (!crtc_state->uapi.active) {
drm_dbg_kms(display->drm, "[CRTC:%d:%s] not active, skipping\n",
crtc->base.base.id, crtc->base.name); continue;
}
drm_dbg_kms(display->drm, "checking [PLANE:%d:%s] for BIOS fb\n",
plane->base.base.id, plane->base.name);
/* * See if the plane fb we found above will fit on this * pipe. Note we need to use the selected fb's pitch and bpp * rather than the current pipe's, since they differ.
*/
cur_size = crtc_state->uapi.adjusted_mode.crtc_hdisplay;
cur_size = cur_size * fb->base.format->cpp[0]; if (fb->base.pitches[0] < cur_size) {
drm_dbg_kms(display->drm, "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n",
plane->base.base.id, plane->base.name,
cur_size, fb->base.pitches[0]);
fb = NULL; break;
}
if (cur_size > max_size) {
drm_dbg_kms(display->drm, "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n",
plane->base.base.id, plane->base.name,
cur_size, max_size);
fb = NULL; break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.