static int rockchip_drm_fbdev_update(struct drm_fb_helper *helper, struct drm_framebuffer *fb) { struct fb_info *fbi = helper->fbdev; struct drm_device *dev = helper->dev; struct rockchip_drm_gem_buf *buffer; unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); unsigned long offset; DRM_DEBUG_KMS("%s\n", __FILE__); drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height); /* RGB formats use only one buffer */ buffer = rockchip_drm_fb_buffer(fb, 0); if (!buffer) { DRM_LOG_KMS("buffer is null.\n"); return -EFAULT; } /* map pages with kernel virtual space. */ if (!buffer->kvaddr) { if (is_drm_iommu_supported(dev)) { unsigned int nr_pages = buffer->size >> PAGE_SHIFT; buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); } else { phys_addr_t dma_addr = buffer->dma_addr; if (dma_addr) buffer->kvaddr = phys_to_virt(dma_addr); else buffer->kvaddr = (void __iomem *)NULL; } if (!buffer->kvaddr) { DRM_ERROR("failed to map pages to kernel space.\n"); return -EIO; } }
static void exynos_drm_fbdev_update(struct drm_fb_helper *helper, struct drm_framebuffer *fb, struct exynos_drm_gem_obj *exynos_gem_obj, unsigned int fb_width, unsigned int fb_height) { struct fb_info *fbi = helper->fbdev; struct drm_device *dev = helper->dev; struct exynos_drm_gem_buf *buffer = exynos_gem_obj->buffer; struct drm_gem_object *drm_gem_object = &exynos_gem_obj->base; size_t size = drm_gem_object->size; DRM_DEBUG_KMS("[FB:%d] [NEW FB:%d]\n", DRM_BASE_ID(helper->fb), DRM_BASE_ID(fb)); drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height); dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr; fbi->screen_base = buffer->kvaddr; fbi->fix.smem_start = (unsigned long)(buffer->dma_addr); fbi->screen_size = size; fbi->fix.smem_len = size; }
static int intelfb_create(struct intel_fbdev *ifbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = ifbdev->helper.dev; #if 0 struct drm_i915_private *dev_priv = dev->dev_private; #endif struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd; struct drm_i915_gem_object *obj; int size, ret; /* we don't do packed 24bpp */ 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] = roundup2(mode_cmd.width * ((sizes->surface_bpp + 7) / 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; size = roundup2(size, PAGE_SIZE); obj = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } DRM_LOCK(dev); /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, false); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; } #if 0 info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = ifbdev; #else info = malloc(sizeof(struct fb_info), DRM_MEM_KMS, M_WAITOK | M_ZERO); info->fb_size = size; info->fb_bpp = sizes->surface_bpp; info->fb_width = sizes->fb_width; info->fb_height = sizes->fb_height; info->fb_pbase = dev->agp->base + obj->gtt_offset; info->fb_vbase = (vm_offset_t)pmap_mapdev_attr(info->fb_pbase, size, PAT_WRITE_COMBINING); #endif ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_unpin; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; ifbdev->helper.fbdev = info; #if 0 strcpy(info->fix.id, "inteldrmfb"); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unpin; } info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = size; // memset(info->screen_base, 0, size); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ #endif DRM_DEBUG_KMS("allocated %dx%d (s %dbits) fb: 0x%08x, bo %p\n", fb->width, fb->height, fb->depth, obj->gtt_offset, obj); DRM_UNLOCK(dev); #if 1 KIB_NOTYET(); #else vga_switcheroo_client_fb_set(dev->pdev, info); #endif return 0; out_unpin: i915_gem_object_unpin(obj); out_unref: drm_gem_object_unreference(&obj->base); DRM_UNLOCK(dev); out: return ret; }
static int mtk_fbdev_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = helper->dev; struct drm_mode_fb_cmd2 mode = { 0 }; struct mtk_drm_fb *mtk_fb; struct mtk_drm_gem_obj *mtk_gem; struct drm_gem_object *gem; struct fb_info *info; struct drm_framebuffer *fb; unsigned long offset; size_t size; int err; mode.width = sizes->surface_width; mode.height = sizes->surface_height; mode.pitches[0] = sizes->surface_width * ((sizes->surface_bpp + 7) / 8); mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); mode.height = mode.height;/* << 1; for fb use? */ size = mode.pitches[0] * mode.height; dev_info(dev->dev, "mtk_fbdev_probe %dx%d bpp %d pitch %d size %zu\n", mode.width, mode.height, sizes->surface_bpp, mode.pitches[0], size); mtk_gem = mtk_drm_gem_create(dev, size, true); if (IS_ERR(mtk_gem)) { err = PTR_ERR(mtk_gem); goto fini; } gem = &mtk_gem->base; mtk_fb = mtk_drm_framebuffer_init(dev, &mode, &gem); if (IS_ERR(mtk_fb)) { dev_err(dev->dev, "failed to allocate DRM framebuffer\n"); err = PTR_ERR(mtk_fb); goto free; } fb = &mtk_fb->base; info = framebuffer_alloc(0, dev->dev); if (!info) { dev_err(dev->dev, "failed to allocate framebuffer info\n"); err = PTR_ERR(info); goto release; } helper->fb = fb; helper->fbdev = info; info->par = helper; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &mediatek_fb_ops; err = fb_alloc_cmap(&info->cmap, 256, 0); if (err < 0) { dev_err(dev->dev, "failed to allocate color map: %d\n", err); goto destroy; } drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, helper, fb->width, fb->height); offset = info->var.xoffset * (fb->bits_per_pixel + 7) / 8; offset += info->var.yoffset * fb->pitches[0]; strcpy(info->fix.id, "mtk"); /* dev->mode_config.fb_base = (resource_size_t)bo->paddr; */ info->var.yres = info->var.yres_virtual;/* >> 1; for fb use? */ info->fix.smem_start = mtk_gem->dma_addr + offset; info->fix.smem_len = size; info->screen_base = mtk_gem->kvaddr + offset; info->screen_size = size; return 0; destroy: drm_framebuffer_unregister_private(fb); mtk_drm_fb_destroy(fb); release: framebuffer_release(info); free: mtk_drm_gem_free_object(&mtk_gem->base); fini: dev_err(dev->dev, "mtk_fbdev_probe fail\n"); return err; }
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 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 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 evdifb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct evdi_fbdev *ufbdev = (struct evdi_fbdev *)helper; struct drm_device *dev = ufbdev->helper.dev; struct fb_info *info; struct device *device = dev->dev; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd; struct evdi_gem_object *obj; uint32_t size; int ret = 0; if (sizes->surface_bpp == 24) { sizes->surface_bpp = 32; } else if (sizes->surface_bpp != 32) { EVDI_ERROR("Not supported pixel format (bpp=%d)\n", sizes->surface_bpp); 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; size = ALIGN(size, PAGE_SIZE); obj = evdi_gem_alloc_object(dev, size); if (!obj) goto out; ret = evdi_gem_vmap(obj); if (ret) { DRM_ERROR("failed to vmap fb\n"); goto out_gfree; } info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_gfree; } info->par = ufbdev; ret = evdi_framebuffer_init(dev, &ufbdev->ufb, &mode_cmd, obj); if (ret) goto out_gfree; fb = &ufbdev->ufb.base; ufbdev->helper.fb = fb; ufbdev->helper.fbdev = info; strcpy(info->fix.id, "evdidrmfb"); 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 = &evdifb_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); ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_gfree; } DRM_DEBUG_KMS("allocated %dx%d vmal %p\n", fb->width, fb->height, ufbdev->ufb.obj->vmapping); return ret; out_gfree: drm_gem_object_unreference(&ufbdev->ufb.obj->base); out: return ret; }
static int nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct nouveau_framebuffer *nouveau_fb; struct pscnv_bo *nvbo; struct drm_gem_object *obj; struct drm_mode_fb_cmd mode_cmd; struct pci_dev *pdev = dev->pdev; struct device *device = &pdev->dev; int size, ret; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.bpp = sizes->surface_bpp; mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); mode_cmd.pitch = roundup(mode_cmd.pitch, 256); mode_cmd.depth = sizes->surface_depth; size = mode_cmd.pitch * mode_cmd.height; size = roundup(size, PAGE_SIZE); obj = pscnv_gem_new(dev, size, PSCNV_GEM_CONTIG, 0, 0xd15fb, 0); if (!obj) { ret = -ENOMEM; NV_ERROR(dev, "failed to allocate framebuffer\n"); goto out; } nvbo = obj->driver_private; ret = dev_priv->vm->map_user(nvbo); if (ret) { NV_ERROR(dev, "failed to map fb: %d\n", ret); pscnv_mem_free(nvbo); goto out; } mutex_lock(&dev->struct_mutex); info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unref; } ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unref; } info->par = nfbdev; nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo); nouveau_fb = &nfbdev->nouveau_fb; fb = &nouveau_fb->base; /* setup helper */ nfbdev->helper.fb = fb; nfbdev->helper.fbdev = info; strcpy(info->fix.id, "nouveaufb"); if (nouveau_nofbaccel) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_DISABLED; else info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; #ifdef FBINFO_CAN_FORCE_OUTPUT info->flags |= FBINFO_CAN_FORCE_OUTPUT; #endif info->fbops = &nouveau_fbcon_ops; info->fix.smem_start = dev->mode_config.fb_base + nvbo->map1->start; info->fix.smem_len = size; info->screen_base = ioremap_wc(dev_priv->fb_phys + nvbo->map1->start, size); info->screen_size = size; drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); /* FIXME: we really shouldn't expose mmio space at all */ info->fix.mmio_start = pci_resource_start(pdev, 1); info->fix.mmio_len = pci_resource_len(pdev, 1); /* Set aperture base/size for vesafb takeover */ info->apertures = dev_priv->apertures; if (!info->apertures) { ret = -ENOMEM; goto out_unref; } info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->pixmap.scan_align = 1; #if 0 if (dev_priv->channel && !nouveau_nofbaccel) { switch (dev_priv->card_type) { case NV_50: nv50_fbcon_accel_init(info); info->fbops = &nv50_fbcon_ops; break; default: nv04_fbcon_accel_init(info); info->fbops = &nv04_fbcon_ops; break; }; } #endif nouveau_fbcon_zfill(dev, nfbdev); /* To allow resizeing without swapping buffers */ NV_INFO(dev, "allocated %dx%d fb: 0x%llx 0x%llx, bo %p\n", nouveau_fb->base.width, nouveau_fb->base.height, nvbo->start, nvbo->map1->start, nvbo); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unref: mutex_unlock(&dev->struct_mutex); out: return ret; }
static int hisi_drm_fbdev_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct hisi_drm_fbdev *fbdev = to_hisi_drm_fbdev(helper); struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_device *dev = helper->dev; struct drm_gem_cma_object *obj; struct drm_framebuffer *fb; unsigned int bytes_per_pixel; unsigned long offset; struct fb_info *fbi; size_t size; int ret; /* TODO: Need to use ion heaps to create frame buffer?? */ 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); sizes->surface_depth = PREFERRED_BPP; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height * HISI_NUM_FRAMEBUFFERS; 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 = roundup(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE); obj = drm_gem_cma_create(dev, size); if (IS_ERR(obj)) return -ENOMEM; fbi = framebuffer_alloc(0, dev->dev); if (!fbi) { dev_err(dev->dev, "Failed to allocate framebuffer info.\n"); ret = -ENOMEM; goto err_drm_gem_cma_free_object; } fbdev->fb = hisi_drm_fb_alloc(dev, &mode_cmd, &obj, 1, true); if (IS_ERR(fbdev->fb)) { dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); ret = PTR_ERR(fbdev->fb); goto err_framebuffer_release; } fb = &fbdev->fb->fb; helper->fb = fb; helper->fbdev = fbi; fbi->par = helper; fbi->flags = FBINFO_FLAG_DEFAULT; fbi->fbops = &hisi_drm_fbdev_ops; ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret) { dev_err(dev->dev, "Failed to allocate color map.\n"); goto err_hisi_drm_fb_destroy; } drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height/HISI_NUM_FRAMEBUFFERS); offset = fbi->var.xoffset * bytes_per_pixel; offset += fbi->var.yoffset * fb->pitches[0]; dev->mode_config.fb_base = (resource_size_t)obj->paddr; fbi->screen_base = obj->vaddr + offset; fbi->fix.smem_start = (unsigned long)(obj->paddr + offset); fbi->screen_size = size; fbi->fix.smem_len = size; DRM_DEBUG_DRIVER("exit successfully.\n"); return 0; err_hisi_drm_fb_destroy: drm_framebuffer_unregister_private(fb); hisi_drm_fb_destroy(fb); err_framebuffer_release: framebuffer_release(fbi); err_drm_gem_cma_free_object: drm_gem_cma_free_object(&obj->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 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 = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_i915_gem_object *obj; int size, ret; bool prealloc = false; mutex_lock(&dev->struct_mutex); 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_unreference(&intel_fb->base); intel_fb = ifbdev->fb = NULL; } if (!intel_fb || WARN_ON(!intel_fb->obj)) { DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); ret = intelfb_alloc(helper, sizes); if (ret) goto out_unlock; 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; } obj = intel_fb->obj; size = obj->base.size; info = framebuffer_alloc(0, &dev->pdev->dev); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = helper; fb = &ifbdev->fb->base; ifbdev->helper.fb = fb; ifbdev->helper.fbdev = info; strcpy(info->fix.id, "inteldrmfb"); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unpin; } info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = dev_priv->gtt.mappable_end; info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj); info->fix.smem_len = size; info->screen_base = ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj), size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = 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->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 (ifbdev->fb->obj->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%08lx, bo %p\n", fb->width, fb->height, i915_gem_obj_ggtt_offset(obj), obj); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unpin: i915_gem_object_ggtt_unpin(obj); drm_gem_object_unreference(&obj->base); out_unlock: mutex_unlock(&dev->struct_mutex); return ret; }
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 drm_device *dev = bochs->dev; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd; struct device *device = &dev->pdev->dev; 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, 0); 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 = framebuffer_alloc(0, device); if (info == NULL) return -ENOMEM; info->par = &bochs->fb.helper; ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj); if (ret) return ret; bochs->fb.size = size; /* setup helper */ fb = &bochs->fb.gfb.base; bochs->fb.helper.fb = fb; bochs->fb.helper.fbdev = info; 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; #if 0 /* FIXME: get this right for mmap(/dev/fb0) */ info->fix.smem_start = bochs_bo_mmap_offset(bo); info->fix.smem_len = size; #endif ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { DRM_ERROR("%s: can't allocate color map\n", info->fix.id); return -ENOMEM; } return 0; }
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; }
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 intelfb_create(struct intel_fbdev *ifbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = ifbdev->helper.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd; struct drm_i915_gem_object *obj; struct device *device = &dev->pdev->dev; int size, ret; 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] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / 8), 64); 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 = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(dev, obj, false); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; } info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = ifbdev; ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_unpin; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; ifbdev->helper.fbdev = info; strcpy(info->fix.id, "inteldrmfb"); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unpin; } info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = size; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", fb->width, fb->height, obj->gtt_offset, obj); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unpin: i915_gem_object_unpin(obj); out_unref: drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); out: 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 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->ifb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_i915_gem_object *obj; int size, ret; mutex_lock(&dev->struct_mutex); if (!intel_fb->obj) { DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n"); ret = intelfb_alloc(helper, sizes); if (ret) goto out_unlock; } else { DRM_DEBUG_KMS("re-using BIOS fb\n"); sizes->fb_width = intel_fb->base.width; sizes->fb_height = intel_fb->base.height; } obj = intel_fb->obj; size = obj->base.size; info = framebuffer_alloc(0, &dev->pdev->dev); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = helper; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; ifbdev->helper.fbdev = info; strcpy(info->fix.id, "inteldrmfb"); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj); info->fix.smem_len = size; info->screen_base = ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj), size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = size; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->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 (ifbdev->ifb.obj->stolen) 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%08lx, bo %p\n", fb->width, fb->height, i915_gem_obj_ggtt_offset(obj), obj); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unpin: i915_gem_object_unpin(obj); drm_gem_object_unreference(&obj->base); out_unlock: mutex_unlock(&dev->struct_mutex); 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 intel_fbdev *ifbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = ifbdev->helper.dev; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd mode_cmd; struct drm_i915_gem_object *obj; struct device *device = &dev->pdev->dev; int size, ret; /* we don't do packed 24bpp */ if (sizes->surface_bpp == 24) sizes->surface_bpp = 32; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.bpp = sizes->surface_bpp; mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); mode_cmd.depth = sizes->surface_depth; size = mode_cmd.pitch * mode_cmd.height; size = ALIGN(size, PAGE_SIZE); obj = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } mutex_lock(&dev->struct_mutex); /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, false); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; } info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = ifbdev; ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_unpin; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; ifbdev->helper.fbdev = info; strcpy(info->fix.id, "inteldrmfb"); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } /* setup aperture base/size for vesafb takeover */ info->aperture_base = dev->mode_config.fb_base; if (!IS_GEN2(dev)) info->aperture_size = pci_resource_len(dev->pdev, 2); else info->aperture_size = pci_resource_len(dev->pdev, 0); info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = size; // memset(info->screen_base, 0, size); drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->pixmap.scan_align = 1; DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", fb->width, fb->height, obj->gtt_offset, obj); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unpin: i915_gem_object_unpin(obj); out_unref: drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); out: 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 = framebuffer_alloc(0, drm->dev); if (!info) { dev_err(drm->dev, "failed to allocate framebuffer info\n"); tegra_bo_free_object(&bo->gem); return -ENOMEM; } fbdev->fb = tegra_fb_alloc(drm, &cmd, &bo, 1); if (IS_ERR(fbdev->fb)) { dev_err(drm->dev, "failed to allocate DRM framebuffer\n"); err = PTR_ERR(fbdev->fb); goto release; } fb = &fbdev->fb->base; helper->fb = fb; helper->fbdev = info; info->par = helper; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &tegra_fb_ops; err = fb_alloc_cmap(&info->cmap, 256, 0); if (err < 0) { dev_err(drm->dev, "failed to allocate color map: %d\n", err); goto destroy; } drm_fb_helper_fill_fix(info, fb->pitches[0], fb->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]; 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_unregister_private(fb); tegra_fb_destroy(fb); release: framebuffer_release(info); return err; }
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 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 drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj; struct device *device = &dev->pdev->dev; int size, ret; /* we don't do packed 24bpp */ 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] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / 8), 64); 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 = i915_gem_object_create_stolen(dev, size); if (obj == NULL) obj = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } mutex_lock(&dev->struct_mutex); /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; } info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = helper; ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_fbrelease; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; ifbdev->helper.fbdev = info; strncpy(info->fix.id, "inteldrmfb", sizeof(info->fix.id) - 1); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_fbdestroy; } /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_decmap; } info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = dev_priv->gtt.mappable_end; info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj); info->fix.smem_len = size; info->screen_base = ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj), size); if (!info->screen_base) { ret = -ENOSPC; goto out_freeap; } info->screen_size = 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->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 (ifbdev->ifb.obj->stolen) 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%08lx, bo %p\n", fb->width, fb->height, i915_gem_obj_ggtt_offset(obj), obj); mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_freeap: kfree(info->apertures); out_decmap: fb_dealloc_cmap(&info->cmap); out_fbdestroy: fb->funcs->destroy(fb); out_fbrelease: kfree(info); out_unpin: i915_gem_object_unpin(obj); out_unref: drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); out: return ret; }
static int nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct nouveau_framebuffer *nouveau_fb; struct nouveau_channel *chan; struct nouveau_bo *nvbo; struct drm_mode_fb_cmd mode_cmd; struct pci_dev *pdev = dev->pdev; struct device *device = &pdev->dev; int size, ret; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.bpp = sizes->surface_bpp; mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); mode_cmd.pitch = roundup(mode_cmd.pitch, 256); mode_cmd.depth = sizes->surface_depth; size = mode_cmd.pitch * mode_cmd.height; size = roundup(size, PAGE_SIZE); ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); if (ret) { NV_ERROR(dev, "failed to allocate framebuffer\n"); goto out; } ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM); if (ret) { NV_ERROR(dev, "failed to pin fb: %d\n", ret); nouveau_bo_ref(NULL, &nvbo); goto out; } ret = nouveau_bo_map(nvbo); if (ret) { NV_ERROR(dev, "failed to map fb: %d\n", ret); nouveau_bo_unpin(nvbo); nouveau_bo_ref(NULL, &nvbo); goto out; } chan = nouveau_nofbaccel ? NULL : dev_priv->channel; if (chan && dev_priv->card_type >= NV_50) { ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma); if (ret) { NV_ERROR(dev, "failed to map fb into chan: %d\n", ret); chan = NULL; } } mutex_lock(&dev->struct_mutex); info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unref; } ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unref; } info->par = nfbdev; nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo); nouveau_fb = &nfbdev->nouveau_fb; fb = &nouveau_fb->base; /* setup helper */ nfbdev->helper.fb = fb; nfbdev->helper.fbdev = info; strcpy(info->fix.id, "nouveaufb"); if (nouveau_nofbaccel) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_DISABLED; else info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; info->flags |= FBINFO_CAN_FORCE_OUTPUT; info->fbops = &nouveau_fbcon_sw_ops; info->fix.smem_start = nvbo->bo.mem.bus.base + nvbo->bo.mem.bus.offset; info->fix.smem_len = size; info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo); info->screen_size = size; drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); /* Set aperture base/size for vesafb takeover */ info->apertures = dev_priv->apertures; if (!info->apertures) { ret = -ENOMEM; goto out_unref; } info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->pixmap.scan_align = 1; mutex_unlock(&dev->struct_mutex); if (dev_priv->channel && !nouveau_nofbaccel) { ret = -ENODEV; if (dev_priv->card_type < NV_50) ret = nv04_fbcon_accel_init(info); else if (dev_priv->card_type < NV_C0) ret = nv50_fbcon_accel_init(info); else ret = nvc0_fbcon_accel_init(info); if (ret == 0) info->fbops = &nouveau_fbcon_ops; } nouveau_fbcon_zfill(dev, nfbdev); /* To allow resizeing without swapping buffers */ NV_INFO(dev, "allocated %dx%d fb: 0x%lx, bo %p\n", nouveau_fb->base.width, nouveau_fb->base.height, nvbo->bo.offset, nvbo); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; out_unref: mutex_unlock(&dev->struct_mutex); out: 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; struct device *device = &rdev->pdev->dev; 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 = framebuffer_alloc(0, device); if (info == NULL) { ret = -ENOMEM; goto out_unref; } info->par = rfbdev; ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); goto out_unref; } fb = &rfbdev->rfb.base; /* setup helper */ rfbdev->helper.fb = fb; rfbdev->helper.fbdev = info; memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo)); strcpy(info->fix.id, "radeondrmfb"); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; 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_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unref; } 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_unref; } ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unref; } 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->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); return 0; out_unref: if (rbo) { } if (fb && ret) { drm_gem_object_unreference(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); } return ret; }
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 intelfb_create(struct intel_fbdev *ifbdev, struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = ifbdev->helper.dev; struct drm_i915_private *dev_priv = dev->dev_private; #if 0 struct fb_info *info; #endif struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj; int size, ret; /* we don't do packed 24bpp */ 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] = roundup2(mode_cmd.width * ((sizes->surface_bpp + 7) / 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; size = roundup2(size, PAGE_SIZE); obj = i915_gem_alloc_object(dev, size); if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } DRM_LOCK(); /* Flush everything out, we'll be doing GTT only from now on */ ret = intel_pin_and_fence_fb_obj(dev, obj, false); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; } #if 0 info = framebuffer_alloc(0, device); if (!info) { ret = -ENOMEM; goto out_unpin; } info->par = ifbdev; #endif ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_unpin; fb = &ifbdev->ifb.base; ifbdev->helper.fb = fb; #if 0 ifbdev->helper.fbdev = info; strlcpy(info->fix.id, "inteldrmfb", sizeof(info->fix.id)); info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret) { ret = -ENOMEM; goto out_unpin; } /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { ret = -ENOMEM; goto out_unpin; } info->apertures->ranges[0].base = dev->mode_config.fb_base; info->apertures->ranges[0].size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } info->screen_size = size; // memset(info->screen_base, 0, size); drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ #else { struct rasops_info *ri = &dev_priv->ro; bus_space_handle_t bsh; int err; err = agp_map_subregion(dev_priv->agph, obj->gtt_offset, size, &bsh); if (err) { ret = -err; goto out_unpin; } ri->ri_bits = bus_space_vaddr(dev->bst, bsh); ri->ri_depth = fb->bits_per_pixel; ri->ri_stride = fb->pitches[0]; ri->ri_width = sizes->fb_width; ri->ri_height = sizes->fb_height; switch (fb->pixel_format) { case DRM_FORMAT_XRGB8888: ri->ri_rnum = 8; ri->ri_rpos = 16; ri->ri_gnum = 8; ri->ri_gpos = 8; ri->ri_bnum = 8; ri->ri_bpos = 0; break; case DRM_FORMAT_RGB565: ri->ri_rnum = 5; ri->ri_rpos = 11; ri->ri_gnum = 6; ri->ri_gpos = 5; ri->ri_bnum = 5; ri->ri_bpos = 0; break; } } #endif DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", fb->width, fb->height, obj->gtt_offset, obj); DRM_UNLOCK(); #if 1 DRM_DEBUG_KMS("skipping call to vga_switcheroo_client_fb_set\n"); #else vga_switcheroo_client_fb_set(dev->pdev, info); #endif return 0; out_unpin: i915_gem_object_unpin(obj); out_unref: drm_gem_object_unreference(&obj->base); DRM_UNLOCK(); out: return ret; }