static struct drm_framebuffer * hibmc_user_framebuffer_create(struct drm_device *dev, struct drm_file *filp, const struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_gem_object *obj; struct hibmc_framebuffer *hibmc_fb; DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n", mode_cmd->width, mode_cmd->height, (mode_cmd->pixel_format) & 0xff, (mode_cmd->pixel_format >> 8) & 0xff, (mode_cmd->pixel_format >> 16) & 0xff, (mode_cmd->pixel_format >> 24) & 0xff); obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); if (!obj) return ERR_PTR(-ENOENT); hibmc_fb = hibmc_framebuffer_init(dev, mode_cmd, obj); if (IS_ERR(hibmc_fb)) { drm_gem_object_unreference_unlocked(obj); return ERR_PTR((long)hibmc_fb); } return &hibmc_fb->fb; }
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; }