示例#1
0
static int codec_lockbuf(struct dce_file_priv *priv,
		uint32_t codec_handle, int32_t id,
		struct drm_gem_object *y, struct drm_gem_object *uv)
{
	struct dce_codec *codec = &priv->codecs[codec_handle-1];
	int i;

	for (i = 0; i < ARRAY_SIZE(codec->locked_buffers); i++) {
		struct dce_buffer *buf = &codec->locked_buffers[i];
		if (buf->id == 0) {
			dma_addr_t paddr;

			DBG("lock[%d]: y=%p, uv=%p", id, y, uv);

			/* for now, until the codecs support relocated buffers, keep
			 * an extra ref and paddr to keep it pinned
			 */
			drm_gem_object_reference(y);
			omap_gem_get_paddr(y, &paddr, true);

			if (uv) {
				drm_gem_object_reference(uv);
				omap_gem_get_paddr(uv, &paddr, true);
			}

			buf->id = id;
			buf->y = y;
			buf->uv = uv;

			return 0;
		}
	}
	dev_err(priv->dev->dev, "too many locked buffers!\n");
	return -ENOMEM;
}
/* pin, prepare for scanout: */
int omap_framebuffer_pin(struct drm_framebuffer *fb)
{
	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
	int ret, i, n = drm_format_num_planes(fb->pixel_format);

	if (omap_fb->pin_count > 0) {
		omap_fb->pin_count++;
		return 0;
	}

	for (i = 0; i < n; i++) {
		struct plane *plane = &omap_fb->planes[i];
		ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true);
		if (ret)
			goto fail;
		omap_gem_dma_sync(plane->bo, DMA_TO_DEVICE);
	}

	omap_fb->pin_count++;

	return 0;

fail:
	for (i--; i >= 0; i--) {
		struct plane *plane = &omap_fb->planes[i];
		omap_gem_put_paddr(plane->bo);
		plane->paddr = 0;
	}

	return ret;
}
示例#3
0
/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL).  Although
 * buffers to unpin are just pushed to the unpin fifo so that the
 * caller can defer unpin until vblank.
 *
 * Note if this fails (ie. something went very wrong!), all buffers are
 * unpinned, and the caller disables the overlay.  We could have tried
 * to revert back to the previous set of pinned buffers but if things are
 * hosed there is no guarantee that would succeed.
 */
int omap_framebuffer_replace(struct drm_framebuffer *a,
		struct drm_framebuffer *b, void *arg,
		void (*unpin)(void *arg, struct drm_gem_object *bo))
{
	int ret = 0, i, na, nb;
	struct omap_framebuffer *ofba = to_omap_framebuffer(a);
	struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
	uint32_t pinned_mask = 0;

	na = a ? drm_format_num_planes(a->pixel_format) : 0;
	nb = b ? drm_format_num_planes(b->pixel_format) : 0;

	for (i = 0; i < max(na, nb); i++) {
		struct plane *pa, *pb;

		pa = (i < na) ? &ofba->planes[i] : NULL;
		pb = (i < nb) ? &ofbb->planes[i] : NULL;

		if (pa)
			unpin(arg, pa->bo);

		if (pb && !ret) {
			ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
			if (!ret) {
				omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE);
				pinned_mask |= (1 << i);
			}
		}
	}

	if (ret) {
		/* something went wrong.. unpin what has been pinned */
		for (i = 0; i < nb; i++) {
			if (pinned_mask & (1 << i)) {
				struct plane *pb = &ofba->planes[i];
				unpin(arg, pb->bo);
			}
		}
	}

	return ret;
}
示例#4
0
/* GEM buffer -> paddr, plus add the buffer to the txn bookkeeping of
 * associated buffers that eventually need to be cleaned up when the
 * transaction completes
 */
static struct drm_gem_object * get_paddr(struct dce_file_priv *priv,
		struct dce_rpc_hdr *req, uint32_t *paddrp, int bo)
{
	struct omap_dce_txn *txn = &txns[req->req_id % ARRAY_SIZE(txns)];
	struct drm_gem_object *obj;
	dma_addr_t paddr;
	int ret;
long t;

	if (txn->bo_count >= ARRAY_SIZE(txn->objs)) {
		DBG("too many buffers!");
		return ERR_PTR(-ENOMEM);
	}

	obj = drm_gem_object_lookup(priv->dev, priv->file, bo);
	if (!obj) {
		DBG("bad handle: %d", bo);
		return ERR_PTR(-ENOENT);
	}

t = mark(NULL);
	ret = omap_gem_get_paddr(obj, &paddr, true);
DBG("get_paddr in %ld us", mark(&t));
	if (ret) {
		DBG("cannot map: %d", ret);
		return ERR_PTR(ret);
	}

	/* the coproc can only see 32bit addresses.. this might need
	 * to be revisited in the future with some conversion between
	 * device address and host address.  But currently they are
	 * the same.
	 */
	*paddrp = (uint32_t)paddr;

	txn->objs[txn->bo_count++] = obj;

	DBG("obj=%p", obj);

	return obj;
}
static struct sg_table *omap_gem_map_dma_buf(
		struct dma_buf_attachment *attachment,
		enum dma_data_direction dir)
{
	struct drm_gem_object *obj = attachment->dmabuf->priv;
	struct sg_table *sg;
	dma_addr_t paddr;
	int ret;

	sg = kzalloc(sizeof(*sg), GFP_KERNEL);
	if (!sg)
		return ERR_PTR(-ENOMEM);

	/* camera, etc, need physically contiguous.. but we need a
	 * better way to know this..
	 */
	ret = omap_gem_get_paddr(obj, &paddr, true);
	if (ret)
		goto out;

	ret = sg_alloc_table(sg, 1, GFP_KERNEL);
	if (ret)
		goto out;

	sg_init_table(sg->sgl, 1);
	sg_dma_len(sg->sgl) = obj->size;
	sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(paddr)), obj->size, 0);
	sg_dma_address(sg->sgl) = paddr;

	/* this should be after _get_paddr() to ensure we have pages attached */
	omap_gem_dma_sync(obj, dir);

out:
	if (ret)
		return ERR_PTR(ret);
	return sg;
}
示例#6
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;
}