Exemplo n.º 1
0
struct drm_framebuffer *
evdi_fb_user_fb_create(struct drm_device *dev,
                       struct drm_file *file,
                       struct drm_mode_fb_cmd2 *mode_cmd)
{
  struct drm_gem_object *obj;
  struct evdi_framebuffer *ufb;
  int ret;
  uint32_t size;

  obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]);
  if (obj == NULL) {
    return ERR_PTR(-ENOENT);
  }

  size = mode_cmd->pitches[0] * mode_cmd->height;
  size = ALIGN(size, PAGE_SIZE);

  if (size > obj->size) {
    DRM_ERROR("object size not sufficient for fb %d %zu %d %d\n",
              size, obj->size, mode_cmd->pitches[0], mode_cmd->height);
    goto err_no_mem;
  }

  ufb = kzalloc(sizeof(*ufb), GFP_KERNEL);
  if (ufb == NULL) {
    goto err_no_mem;
  }

  ret = evdi_framebuffer_init(dev, ufb, mode_cmd, to_evdi_bo(obj));
  if (ret) {
    kfree(ufb);
    goto err_inval;
  }
  drm_gem_object_unreference(obj);
  return &ufb->base;

err_no_mem:
  drm_gem_object_unreference(obj);
  return ERR_PTR(-ENOMEM);
err_inval:
  drm_gem_object_unreference(obj);
  return ERR_PTR(-EINVAL);
}
Exemplo n.º 2
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;
}