Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6a91827 authored by Rob Clark's avatar Rob Clark Committed by Greg Kroah-Hartman
Browse files

staging: drm/omap: DMM based hardware scrolling console



Add support for YWRAP scrolling by shuffling pages around in DMM
instead of sw blits.

Note that fbcon only utilizes this mode if the y resolution is
divided evenly by the font height.  So, for example, a 1920x1080
display using a 16 pixel tall font will not utilize this, but a
1280x1024 display would.

Signed-off-by: default avatarRob Clark <rob@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 65b0bd06
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -79,12 +79,12 @@
#define DMM_PATSTATUS_ERR_UPD_DATA	(1<<14)
#define DMM_PATSTATUS_ERR_ACCESS	(1<<15)

/* note: don't treat DMM_PATSTATUS_ERR_ACCESS as an error */
#define DMM_PATSTATUS_ERR	(DMM_PATSTATUS_ERR_INV_DESCR | \
				DMM_PATSTATUS_ERR_INV_DATA | \
				DMM_PATSTATUS_ERR_UPD_AREA | \
				DMM_PATSTATUS_ERR_UPD_CTRL | \
				DMM_PATSTATUS_ERR_UPD_DATA | \
				DMM_PATSTATUS_ERR_ACCESS)
				DMM_PATSTATUS_ERR_UPD_DATA)



+22 −13
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
 * corresponding slot is cleared (ie. dummy_pa is programmed)
 */
static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
			struct page **pages)
		struct page **pages, uint32_t npages, uint32_t roll)
{
	dma_addr_t pat_pa = 0;
	uint32_t *data;
@@ -197,8 +197,11 @@ static int dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
	data = alloc_dma(txn, 4*i, &pat->data_pa);

	while (i--) {
		data[i] = (pages && pages[i]) ?
		page_to_phys(pages[i]) : engine->dmm->dummy_pa;
		int n = i + roll;
		if (n >= npages)
			n -= npages;
		data[i] = (pages && pages[n]) ?
			page_to_phys(pages[n]) : engine->dmm->dummy_pa;
	}

	/* fill in lut with new addresses */
@@ -262,7 +265,8 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
/*
 * DMM programming
 */
static int fill(struct tcm_area *area, struct page **pages, bool wait)
static int fill(struct tcm_area *area, struct page **pages,
		uint32_t npages, uint32_t roll, bool wait)
{
	int ret = 0;
	struct tcm_area slice, area_s;
@@ -278,12 +282,11 @@ static int fill(struct tcm_area *area, struct page **pages, bool wait)
				.x1 = slice.p1.x,  .y1 = slice.p1.y,
		};

		ret = dmm_txn_append(txn, &p_area, pages);
		ret = dmm_txn_append(txn, &p_area, pages, npages, roll);
		if (ret)
			goto fail;

		if (pages)
			pages += tcm_sizeof(slice);
		roll += tcm_sizeof(slice);
	}

	ret = dmm_txn_commit(txn, wait);
@@ -298,11 +301,12 @@ static int fill(struct tcm_area *area, struct page **pages, bool wait)

/* note: slots for which pages[i] == NULL are filled w/ dummy page
 */
int tiler_pin(struct tiler_block *block, struct page **pages, bool wait)
int tiler_pin(struct tiler_block *block, struct page **pages,
		uint32_t npages, uint32_t roll, bool wait)
{
	int ret;

	ret = fill(&block->area, pages, wait);
	ret = fill(&block->area, pages, npages, roll, wait);

	if (ret)
		tiler_unpin(block);
@@ -312,7 +316,7 @@ int tiler_pin(struct tiler_block *block, struct page **pages, bool wait)

int tiler_unpin(struct tiler_block *block)
{
	return fill(&block->area, NULL, false);
	return fill(&block->area, NULL, 0, 0, false);
}

/*
@@ -558,8 +562,13 @@ int omap_dmm_init(struct drm_device *dev)
		goto fail;
	}

	/* enable some interrupts! */
	writel(0xfefefefe, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
	/* Enable all interrupts for each refill engine except
	 * ERR_LUT_MISS<n> (which is just advisory, and we don't care
	 * about because we want to be able to refill live scanout
	 * buffers for accelerated pan/scroll) and FILL_DSC<n> which
	 * we just generally don't care about.
	 */
	writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);

	lut_table_size = omap_dmm->lut_width * omap_dmm->lut_height *
			omap_dmm->num_lut;
@@ -658,7 +667,7 @@ int omap_dmm_init(struct drm_device *dev)
	/* initialize all LUTs to dummy page entries */
	for (i = 0; i < omap_dmm->num_lut; i++) {
		area.tcm = omap_dmm->tcm[i];
		if (fill(&area, NULL, true))
		if (fill(&area, NULL, 0, 0, true))
			dev_err(omap_dmm->dev, "refill failed");
	}

+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ int omap_dmm_init(struct drm_device *dev);
int omap_dmm_remove(void);

/* pin/unpin */
int tiler_pin(struct tiler_block *block, struct page **pages, bool wait);
int tiler_pin(struct tiler_block *block, struct page **pages,
		uint32_t npages, uint32_t roll, bool wait);
int tiler_unpin(struct tiler_block *block);

/* reserve/release */
+3 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ struct omap_drm_private {
	struct drm_connector *connectors[8];

	struct drm_fb_helper *fbdev;

	bool has_dmm;
};

struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
@@ -107,6 +109,7 @@ int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op);
int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op);
int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
		void (*fxn)(void *arg), void *arg);
int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll);
int omap_gem_get_paddr(struct drm_gem_object *obj,
		dma_addr_t *paddr, bool remap);
int omap_gem_put_paddr(struct drm_gem_object *obj);
+3 −19
Original line number Diff line number Diff line
@@ -218,26 +218,10 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,

	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;
Loading