Example #1
0
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
{
	struct omap_framebuffer *omap_fb;
	struct drm_framebuffer *fb = NULL;
	const struct format *format = NULL;
	int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);

	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
			dev, mode_cmd, mode_cmd->width, mode_cmd->height,
			(char *)&mode_cmd->pixel_format);

	for (i = 0; i < ARRAY_SIZE(formats); i++) {
		if (formats[i].pixel_format == mode_cmd->pixel_format) {
			format = &formats[i];
			break;
		}
	}

	if (!format) {
		dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
				(char *)&mode_cmd->pixel_format);
		ret = -EINVAL;
		goto fail;
	}

	omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
	if (!omap_fb) {
		ret = -ENOMEM;
		goto fail;
	}

	fb = &omap_fb->base;
	omap_fb->format = format;

	for (i = 0; i < n; i++) {
		struct plane *plane = &omap_fb->planes[i];
		int size, pitch = mode_cmd->pitches[i];

		if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) {
			dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
					pitch, mode_cmd->width * format->planes[i].stride_bpp);
			ret = -EINVAL;
			goto fail;
		}

		size = pitch * mode_cmd->height / format->planes[i].sub_y;

		if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
			dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
					bos[i]->size - mode_cmd->offsets[i], size);
			ret = -EINVAL;
			goto fail;
		}

		plane->bo     = bos[i];
		plane->offset = mode_cmd->offsets[i];
		plane->pitch  = pitch;
		plane->paddr  = 0;
	}

	drm_helper_mode_fill_fb_struct(fb, mode_cmd);

	ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
	if (ret) {
		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
		goto fail;
	}

	DBG("create: FB ID: %d (%p)", fb->base.id, fb);

	return fb;

fail:
	if (fb)
		omap_framebuffer_destroy(fb);

	return ERR_PTR(ret);
}
Example #2
0
struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
		struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo)
{
	struct omap_framebuffer *omap_fb;
	struct drm_framebuffer *fb = NULL;
	int size, ret;

	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%d)",
			dev, mode_cmd, mode_cmd->width, mode_cmd->height,
			mode_cmd->bpp);

	/* in case someone tries to feed us a completely bogus stride: */
	mode_cmd->pitch = align_pitch(mode_cmd->pitch,
			mode_cmd->width, mode_cmd->bpp);

	omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
	if (!omap_fb) {
		dev_err(dev->dev, "could not allocate fb\n");
		goto fail;
	}

	fb = &omap_fb->base;
	ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
	if (ret) {
		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
		goto fail;
	}

	DBG("create: FB ID: %d (%p)", fb->base.id, fb);

	size = PAGE_ALIGN(mode_cmd->pitch * mode_cmd->height);

	if (bo) {
		DBG("using existing %d byte buffer (needed %d)", bo->size, size);
		if (size > bo->size) {
			dev_err(dev->dev, "provided buffer object is too small!\n");
			goto fail;
		}
	} else {
		/* for convenience of all the various callers who don't want
		 * to be bothered to allocate their own buffer..
		 */
		union omap_gem_size gsize = {
				.bytes = size,
		};
		DBG("allocating %d bytes for fb %d", size, dev->primary->index);
		bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);
		if (!bo) {
			dev_err(dev->dev, "failed to allocate buffer object\n");
			goto fail;
		}
	}

	omap_fb->bo = bo;
	omap_fb->size = size;

	if (omap_gem_get_paddr(bo, &omap_fb->paddr, true)) {
		dev_err(dev->dev, "could not map (paddr)!\n");
		goto fail;
	}

	drm_helper_mode_fill_fb_struct(fb, mode_cmd);

	return fb;

fail:
	if (fb) {
		omap_framebuffer_destroy(fb);
	}
	return NULL;
}