static int qxlfb_create(struct qxl_fbdev *qfbdev, struct drm_fb_helper_surface_size *sizes) { struct qxl_device *qdev = qfbdev->qdev; struct fb_info *info; struct drm_framebuffer *fb = NULL; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; struct qxl_bo *qbo = NULL; int ret; int size; int bpp = sizes->surface_bpp; int depth = sizes->surface_depth; void *shadow; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 1) / 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); ret = qxlfb_create_pinned_object(qfbdev, &mode_cmd, &gobj); if (ret < 0) return ret; qbo = gem_to_qxl_bo(gobj); QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width, mode_cmd.height, mode_cmd.pitches[0]); shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height); /* TODO: what's the usual response to memory allocation errors? */ BUG_ON(!shadow); QXL_INFO(qdev, "surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo), qbo->kptr, shadow); size = mode_cmd.pitches[0] * mode_cmd.height; info = drm_fb_helper_alloc_fbi(&qfbdev->helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out_unref; } info->par = qfbdev; qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, &qxlfb_fb_funcs); fb = &qfbdev->qfb.base; /* setup helper with fb data */ qfbdev->helper.fb = fb; qfbdev->shadow = shadow; strcpy(info->fix.id, "qxldrmfb"); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; info->fbops = &qxlfb_ops; /* * TODO: using gobj->size in various places in this function. Not sure * what the difference between the different sizes is. */ info->fix.smem_start = qdev->vram_base; /* TODO - correct? */ info->fix.smem_len = gobj->size; info->screen_base = qfbdev->shadow; info->screen_size = gobj->size; drm_fb_helper_fill_var(info, &qfbdev->helper, sizes->fb_width, sizes->fb_height); /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = qdev->ddev->mode_config.fb_base; info->apertures->ranges[0].size = qdev->vram_size; info->fix.mmio_start = 0; info->fix.mmio_len = 0; if (info->screen_base == NULL) { ret = -ENOSPC; goto out_destroy_fbi; } info->fbdefio = &qxl_defio; fb_deferred_io_init(info); qdev->fbdev_info = info; qdev->fbdev_qfb = &qfbdev->qfb; DRM_INFO("fb mappable at 0x%lX, size %lu\n", info->fix.smem_start, (unsigned long)info->screen_size); DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", fb->depth, fb->pitches[0], fb->width, fb->height); return 0; out_destroy_fbi: drm_fb_helper_release_fbi(&qfbdev->helper); out_unref: if (qbo) { ret = qxl_bo_reserve(qbo, false); if (likely(ret == 0)) { qxl_bo_kunmap(qbo); qxl_bo_unpin(qbo); qxl_bo_unreserve(qbo); } } if (fb && ret) { drm_gem_object_unreference_unlocked(gobj); drm_framebuffer_cleanup(fb); kfree(fb); } drm_gem_object_unreference_unlocked(gobj); return ret; }
static int amdgpufb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct amdgpu_fbdev *rfbdev = (struct amdgpu_fbdev *)helper; struct amdgpu_device *adev = rfbdev->adev; struct fb_info *info; struct drm_framebuffer *fb = NULL; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; struct amdgpu_bo *abo = NULL; int ret; unsigned long tmp; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; if (sizes->surface_bpp == 24) sizes->surface_bpp = 32; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); ret = amdgpufb_create_pinned_object(rfbdev, &mode_cmd, &gobj); if (ret) { DRM_ERROR("failed to create fbcon object %d\n", ret); return ret; } abo = gem_to_amdgpu_bo(gobj); /* okay we have an object now allocate the framebuffer */ info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } info->par = rfbdev; info->skip_vt_switch = true; ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); goto out; } fb = &rfbdev->rfb.base; /* setup helper */ rfbdev->helper.fb = fb; strcpy(info->fix.id, "amdgpudrmfb"); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &amdgpufb_ops; tmp = amdgpu_bo_gpu_offset(abo) - adev->mc.vram_start; info->fix.smem_start = adev->mc.aper_base + tmp; info->fix.smem_len = amdgpu_bo_size(abo); info->screen_base = abo->kptr; info->screen_size = amdgpu_bo_size(abo); drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base; info->apertures->ranges[0].size = adev->mc.aper_size; /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ if (info->screen_base == NULL) { ret = -ENOSPC; goto out; } DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram apper at 0x%lX\n", (unsigned long)adev->mc.aper_base); DRM_INFO("size %lu\n", (unsigned long)amdgpu_bo_size(abo)); DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(adev->ddev->pdev, info); return 0; out: if (abo) { } if (fb && ret) { drm_gem_object_unreference_unlocked(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); } return ret; }
static int tegra_fbdev_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); struct tegra_drm *tegra = helper->dev->dev_private; struct drm_device *drm = helper->dev; struct drm_mode_fb_cmd2 cmd = { 0 }; unsigned int bytes_per_pixel; struct drm_framebuffer *fb; unsigned long offset; struct fb_info *info; struct tegra_bo *bo; size_t size; int err; bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); cmd.width = sizes->surface_width; cmd.height = sizes->surface_height; cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, tegra->pitch_align); cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = cmd.pitches[0] * cmd.height; bo = tegra_bo_create(drm, size, 0); if (IS_ERR(bo)) return PTR_ERR(bo); info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { dev_err(drm->dev, "failed to allocate framebuffer info\n"); drm_gem_object_put_unlocked(&bo->gem); return PTR_ERR(info); } fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1); if (IS_ERR(fbdev->fb)) { err = PTR_ERR(fbdev->fb); dev_err(drm->dev, "failed to allocate DRM framebuffer: %d\n", err); drm_gem_object_put_unlocked(&bo->gem); return PTR_ERR(fbdev->fb); } fb = &fbdev->fb->base; helper->fb = fb; helper->fbdev = info; info->par = helper; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &tegra_fb_ops; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, helper, fb->width, fb->height); offset = info->var.xoffset * bytes_per_pixel + info->var.yoffset * fb->pitches[0]; if (bo->pages) { bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); if (!bo->vaddr) { dev_err(drm->dev, "failed to vmap() framebuffer\n"); err = -ENOMEM; goto destroy; } } drm->mode_config.fb_base = (resource_size_t)bo->paddr; info->screen_base = (void __iomem *)bo->vaddr + offset; info->screen_size = size; info->fix.smem_start = (unsigned long)(bo->paddr + offset); info->fix.smem_len = size; return 0; destroy: drm_framebuffer_remove(fb); return err; }
static int bochsfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct bochs_device *bochs = container_of(helper, struct bochs_device, fb.helper); struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; struct bochs_bo *bo = NULL; int size, ret; if (sizes->surface_bpp != 32) return -EINVAL; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; /* alloc, pin & map bo */ ret = bochsfb_create_object(bochs, &mode_cmd, &gobj); if (ret) { DRM_ERROR("failed to create fbcon backing object %d\n", ret); return ret; } bo = gem_to_bochs_bo(gobj); ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL); if (ret) return ret; ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); if (ret) { DRM_ERROR("failed to pin fbcon\n"); ttm_bo_unreserve(&bo->bo); return ret; } ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); if (ret) { DRM_ERROR("failed to kmap fbcon\n"); ttm_bo_unreserve(&bo->bo); return ret; } ttm_bo_unreserve(&bo->bo); /* init fb device */ info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) return PTR_ERR(info); info->par = &bochs->fb.helper; ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj); if (ret) { drm_fb_helper_release_fbi(helper); return ret; } bochs->fb.size = size; /* setup helper */ fb = &bochs->fb.gfb.base; bochs->fb.helper.fb = fb; strcpy(info->fix.id, "bochsdrmfb"); info->flags = FBINFO_DEFAULT; info->fbops = &bochsfb_ops; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width, sizes->fb_height); info->screen_base = bo->kmap.virtual; info->screen_size = size; drm_vma_offset_remove(&bo->bo.bdev->vma_manager, &bo->bo.vma_node); info->fix.smem_start = 0; info->fix.smem_len = size; return 0; }
static int udlfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct udl_fbdev *ufbdev = container_of(helper, struct udl_fbdev, helper); struct drm_device *dev = ufbdev->helper.dev; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd; struct udl_gem_object *obj; uint32_t size; int ret = 0; if (sizes->surface_bpp == 24) sizes->surface_bpp = 32; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; size = ALIGN(size, PAGE_SIZE); obj = udl_gem_alloc_object(dev, size); if (!obj) goto out; ret = udl_gem_vmap(obj); if (ret) { DRM_ERROR("failed to vmap fb\n"); goto out_gfree; } info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out_gfree; } info->par = ufbdev; ret = udl_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj); if (ret) goto out_destroy_fbi; fb = &ufbdev->ufb.base; ufbdev->helper.fb = fb; strcpy(info->fix.id, "udldrmfb"); info->screen_base = ufbdev->ufb.obj->vmapping; info->fix.smem_len = size; info->fix.smem_start = (unsigned long)ufbdev->ufb.obj->vmapping; info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &udlfb_ops; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &ufbdev->helper, sizes->fb_width, sizes->fb_height); DRM_DEBUG_KMS("allocated %dx%d vmal %p\n", fb->width, fb->height, ufbdev->ufb.obj->vmapping); return ret; out_destroy_fbi: drm_fb_helper_release_fbi(helper); out_gfree: drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); out: return ret; }
static int armada_fb_create(struct drm_fb_helper *fbh, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = fbh->dev; struct drm_mode_fb_cmd2 mode; struct armada_framebuffer *dfb; struct armada_gem_object *obj; struct fb_info *info; int size, ret; void *ptr; memset(&mode, 0, sizeof(mode)); mode.width = sizes->surface_width; mode.height = sizes->surface_height; mode.pitches[0] = armada_pitch(mode.width, sizes->surface_bpp); mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode.pitches[0] * mode.height; obj = armada_gem_alloc_private_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate fb memory\n"); return -ENOMEM; } ret = armada_gem_linear_back(dev, obj); if (ret) { drm_gem_object_unreference_unlocked(&obj->obj); return ret; } ptr = armada_gem_map_object(dev, obj); if (!ptr) { drm_gem_object_unreference_unlocked(&obj->obj); return -ENOMEM; } dfb = armada_framebuffer_create(dev, &mode, obj); /* * A reference is now held by the framebuffer object if * successful, otherwise this drops the ref for the error path. */ drm_gem_object_unreference_unlocked(&obj->obj); if (IS_ERR(dfb)) return PTR_ERR(dfb); info = drm_fb_helper_alloc_fbi(fbh); if (IS_ERR(info)) { ret = PTR_ERR(info); goto err_fballoc; } strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id)); info->par = fbh; info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &armada_fb_ops; info->fix.smem_start = obj->phys_addr; info->fix.smem_len = obj->obj.size; info->screen_size = obj->obj.size; info->screen_base = ptr; fbh->fb = &dfb->fb; drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.format->depth); drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n", dfb->fb.width, dfb->fb.height, dfb->fb.format->cpp[0] * 8, (unsigned long long)obj->phys_addr); return 0; err_fballoc: dfb->fb.funcs->destroy(&dfb->fb); return ret; }
static int intelfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct intel_fbdev *ifbdev = container_of(helper, struct intel_fbdev, helper); struct intel_framebuffer *intel_fb = ifbdev->fb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct pci_dev *pdev = dev_priv->drm.pdev; struct i915_ggtt *ggtt = &dev_priv->ggtt; struct fb_info *info; struct drm_framebuffer *fb; struct i915_vma *vma; unsigned long flags = 0; bool prealloc = false; void __iomem *vaddr; int ret; if (intel_fb && (sizes->fb_width > intel_fb->base.width || sizes->fb_height > intel_fb->base.height)) { DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d)," " releasing it\n", intel_fb->base.width, intel_fb->base.height, sizes->fb_width, sizes->fb_height); drm_framebuffer_put(&intel_fb->base); intel_fb = ifbdev->fb = NULL; } if (!intel_fb || WARN_ON(!intel_fb_obj(&intel_fb->base))) { DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); ret = intelfb_alloc(helper, sizes); if (ret) return ret; intel_fb = ifbdev->fb; } else { DRM_DEBUG_KMS("re-using BIOS fb\n"); prealloc = true; sizes->fb_width = intel_fb->base.width; sizes->fb_height = intel_fb->base.height; } mutex_lock(&dev->struct_mutex); intel_runtime_pm_get(dev_priv); /* 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_pin_and_fence_fb_obj(&ifbdev->fb->base, DRM_MODE_ROTATE_0, false, &flags); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; } fb = &ifbdev->fb->base; intel_fb_obj_flush(intel_fb_obj(fb), ORIGIN_DIRTYFB); info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { DRM_ERROR("Failed to allocate fb_info\n"); ret = PTR_ERR(info); goto out_unpin; } info->par = helper; ifbdev->helper.fb = fb; strcpy(info->fix.id, "inteldrmfb"); info->fbops = &intelfb_ops; /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = ggtt->mappable_end; info->fix.smem_start = dev->mode_config.fb_base + i915_ggtt_offset(vma); info->fix.smem_len = vma->node.size; vaddr = i915_vma_pin_iomap(vma); if (IS_ERR(vaddr)) { DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); ret = PTR_ERR(vaddr); goto out_unpin; } info->screen_base = vaddr; info->screen_size = vma->node.size; /* This driver doesn't need a VT switch to restore the mode on resume */ info->skip_vt_switch = true; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); /* 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_fb_obj(fb)->stolen && !prealloc) memset_io(info->screen_base, 0, info->screen_size); /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n", fb->width, fb->height, i915_ggtt_offset(vma)); ifbdev->vma = vma; ifbdev->vma_flags = flags; intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(pdev, info); return 0; out_unpin: intel_unpin_fb_vma(vma, flags); out_unlock: intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); return ret; }
static int virtio_gpufb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct virtio_gpu_fbdev *vfbdev = container_of(helper, struct virtio_gpu_fbdev, helper); struct drm_device *dev = helper->dev; struct virtio_gpu_device *vgdev = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct virtio_gpu_object *obj; uint32_t resid, format, size; int ret; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * 4; mode_cmd.pixel_format = drm_mode_legacy_fb_format(32, 24); format = virtio_gpu_translate_format(mode_cmd.pixel_format); if (format == 0) return -EINVAL; size = mode_cmd.pitches[0] * mode_cmd.height; obj = virtio_gpu_alloc_object(dev, size, false, true); if (IS_ERR(obj)) return PTR_ERR(obj); virtio_gpu_resource_id_get(vgdev, &resid); virtio_gpu_cmd_create_resource(vgdev, resid, format, mode_cmd.width, mode_cmd.height); ret = virtio_gpu_vmap_fb(vgdev, obj); if (ret) { DRM_ERROR("failed to vmap fb %d\n", ret); goto err_obj_vmap; } /* attach the object to the resource */ ret = virtio_gpu_object_attach(vgdev, obj, resid, NULL); if (ret) goto err_obj_attach; info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto err_fb_alloc; } info->par = helper; ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb, &mode_cmd, &obj->gem_base); if (ret) goto err_fb_alloc; fb = &vfbdev->vgfb.base; vfbdev->helper.fb = fb; strcpy(info->fix.id, "virtiodrmfb"); info->fbops = &virtio_gpufb_ops; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->screen_buffer = obj->vmap; info->screen_size = obj->gem_base.size; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &vfbdev->helper, sizes->fb_width, sizes->fb_height); info->fix.mmio_start = 0; info->fix.mmio_len = 0; return 0; err_fb_alloc: virtio_gpu_cmd_resource_inval_backing(vgdev, resid); err_obj_attach: err_obj_vmap: virtio_gpu_gem_free_object(&obj->gem_base); return ret; }
static int virtio_gpufb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct virtio_gpu_fbdev *vfbdev = container_of(helper, struct virtio_gpu_fbdev, helper); struct drm_device *dev = helper->dev; struct virtio_gpu_device *vgdev = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct virtio_gpu_object *obj; uint32_t resid, format, size; int ret; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * 4; mode_cmd.pixel_format = drm_mode_legacy_fb_format(32, 24); switch (mode_cmd.pixel_format) { #ifdef __BIG_ENDIAN case DRM_FORMAT_XRGB8888: format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; break; case DRM_FORMAT_ARGB8888: format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; break; case DRM_FORMAT_BGRX8888: format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; break; case DRM_FORMAT_BGRA8888: format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; break; case DRM_FORMAT_RGBX8888: format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM; break; case DRM_FORMAT_RGBA8888: format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM; break; case DRM_FORMAT_XBGR8888: format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM; break; case DRM_FORMAT_ABGR8888: format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM; break; #else case DRM_FORMAT_XRGB8888: format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM; break; case DRM_FORMAT_ARGB8888: format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM; break; case DRM_FORMAT_BGRX8888: format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM; break; case DRM_FORMAT_BGRA8888: format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM; break; case DRM_FORMAT_RGBX8888: format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM; break; case DRM_FORMAT_RGBA8888: format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM; break; case DRM_FORMAT_XBGR8888: format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM; break; case DRM_FORMAT_ABGR8888: format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM; break; #endif default: DRM_ERROR("failed to find virtio gpu format for %d\n", mode_cmd.pixel_format); return -EINVAL; } size = mode_cmd.pitches[0] * mode_cmd.height; obj = virtio_gpu_alloc_object(dev, size, false, true); if (IS_ERR(obj)) return PTR_ERR(obj); virtio_gpu_resource_id_get(vgdev, &resid); virtio_gpu_cmd_create_resource(vgdev, resid, format, mode_cmd.width, mode_cmd.height); ret = virtio_gpu_vmap_fb(vgdev, obj); if (ret) { DRM_ERROR("failed to vmap fb %d\n", ret); goto err_obj_vmap; } /* attach the object to the resource */ ret = virtio_gpu_object_attach(vgdev, obj, resid, NULL); if (ret) goto err_obj_attach; info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto err_fb_alloc; } info->par = helper; ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb, &mode_cmd, &obj->gem_base); if (ret) goto err_fb_init; fb = &vfbdev->vgfb.base; vfbdev->helper.fb = fb; strcpy(info->fix.id, "virtiodrmfb"); info->flags = FBINFO_DEFAULT; info->fbops = &virtio_gpufb_ops; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->screen_base = obj->vmap; info->screen_size = obj->gem_base.size; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &vfbdev->helper, sizes->fb_width, sizes->fb_height); info->fix.mmio_start = 0; info->fix.mmio_len = 0; return 0; err_fb_init: drm_fb_helper_release_fbi(helper); err_fb_alloc: virtio_gpu_cmd_resource_inval_backing(vgdev, resid); err_obj_attach: err_obj_vmap: virtio_gpu_gem_free_object(&obj->gem_base); return ret; }
static int radeonfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct radeon_fbdev *rfbdev = container_of(helper, struct radeon_fbdev, helper); struct radeon_device *rdev = rfbdev->rdev; struct fb_info *info; struct drm_framebuffer *fb = NULL; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; struct radeon_bo *rbo = NULL; int ret; unsigned long tmp; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; /* avivo can't scanout real 24bpp */ if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) sizes->surface_bpp = 32; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); if (ret) { DRM_ERROR("failed to create fbcon object %d\n", ret); return ret; } rbo = gem_to_radeon_bo(gobj); /* okay we have an object now allocate the framebuffer */ info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto out; } /* radeon resume is fragile and needs a vt switch to help it along */ info->skip_vt_switch = false; ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->fb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); goto out; } fb = &rfbdev->fb; /* setup helper */ rfbdev->helper.fb = fb; memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo)); info->fbops = &radeonfb_ops; tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; info->fix.smem_start = rdev->mc.aper_base + tmp; info->fix.smem_len = radeon_bo_size(rbo); info->screen_base = rbo->kptr; info->screen_size = radeon_bo_size(rbo); drm_fb_helper_fill_info(info, &rfbdev->helper, sizes); /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; info->apertures->ranges[0].size = rdev->mc.aper_size; /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ if (info->screen_base == NULL) { ret = -ENOSPC; goto out; } DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); return 0; out: if (rbo) { } if (fb && ret) { drm_gem_object_put_unlocked(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); } return ret; }
mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; rk_obj = rockchip_gem_create_object(dev, size, true); if (IS_ERR(rk_obj)) return -ENOMEM; private->fbdev_bo = &rk_obj->base; fbi = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(fbi)) { dev_err(dev->dev, "Failed to create framebuffer info.\n"); ret = PTR_ERR(fbi); goto out; } helper->fb = rockchip_drm_framebuffer_init(dev, &mode_cmd, private->fbdev_bo); if (IS_ERR(helper->fb)) { dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); ret = PTR_ERR(helper->fb); goto out; } fbi->par = helper;
static int hibmc_drm_fb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct hibmc_fbdev *hi_fbdev = container_of(helper, struct hibmc_fbdev, helper); struct hibmc_drm_private *priv = helper->dev->dev_private; struct fb_info *info; struct drm_mode_fb_cmd2 mode_cmd; struct drm_gem_object *gobj = NULL; int ret = 0; int ret1; size_t size; unsigned int bytes_per_pixel; struct hibmc_bo *bo = NULL; DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n", sizes->surface_width, sizes->surface_height, sizes->surface_bpp); bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * bytes_per_pixel; mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height); ret = hibmcfb_create_object(priv, &mode_cmd, &gobj); if (ret) { DRM_ERROR("failed to create fbcon backing object: %d\n", ret); return -ENOMEM; } bo = gem_to_hibmc_bo(gobj); ret = ttm_bo_reserve(&bo->bo, true, false, NULL); if (ret) { DRM_ERROR("failed to reserve ttm_bo: %d\n", ret); goto out_unref_gem; } ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); if (ret) { DRM_ERROR("failed to pin fbcon: %d\n", ret); goto out_unreserve_ttm_bo; } ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); if (ret) { DRM_ERROR("failed to kmap fbcon: %d\n", ret); goto out_unpin_bo; } ttm_bo_unreserve(&bo->bo); info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); DRM_ERROR("failed to allocate fbi: %d\n", ret); goto out_release_fbi; } info->par = hi_fbdev; hi_fbdev->fb = hibmc_framebuffer_init(priv->dev, &mode_cmd, gobj); if (IS_ERR(hi_fbdev->fb)) { ret = PTR_ERR(hi_fbdev->fb); hi_fbdev->fb = NULL; DRM_ERROR("failed to initialize framebuffer: %d\n", ret); goto out_release_fbi; } priv->fbdev->size = size; hi_fbdev->helper.fb = &hi_fbdev->fb->fb; strcpy(info->fix.id, "hibmcdrmfb"); info->fbops = &hibmc_drm_fb_ops; drm_fb_helper_fill_fix(info, hi_fbdev->fb->fb.pitches[0], hi_fbdev->fb->fb.format->depth); drm_fb_helper_fill_var(info, &priv->fbdev->helper, sizes->fb_width, sizes->fb_height); info->screen_base = bo->kmap.virtual; info->screen_size = size; info->fix.smem_start = bo->bo.mem.bus.offset + bo->bo.mem.bus.base; info->fix.smem_len = size; return 0; out_release_fbi: ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL); if (ret1) { DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1); goto out_unref_gem; } ttm_bo_kunmap(&bo->kmap); out_unpin_bo: hibmc_bo_unpin(bo); out_unreserve_ttm_bo: ttm_bo_unreserve(&bo->bo); out_unref_gem: drm_gem_object_put_unlocked(gobj); return ret; }