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

Commit 4a8506d2 authored by Russell King's avatar Russell King
Browse files

drm/armada: convert overlay plane vbl worker to a armada plane worker



Convert the overlay plane to use the generic armada plane worker
infrastructure which is shared with the primary plane.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 4b5dda82
Loading
Loading
Loading
Loading
+12 −36
Original line number Diff line number Diff line
@@ -226,44 +226,15 @@ int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout)
	return wait_event_timeout(plane->frame_wait, !plane->work, timeout);
}

void armada_drm_vbl_event_add(struct armada_crtc *dcrtc,
	struct armada_vbl_event *evt)
struct armada_plane_work *armada_drm_plane_work_cancel(
	struct armada_crtc *dcrtc, struct armada_plane *plane)
{
	unsigned long flags;
	bool not_on_list;

	WARN_ON(drm_vblank_get(dcrtc->crtc.dev, dcrtc->num));

	spin_lock_irqsave(&dcrtc->irq_lock, flags);
	not_on_list = list_empty(&evt->node);
	if (not_on_list)
		list_add_tail(&evt->node, &dcrtc->vbl_list);
	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
	struct armada_plane_work *work = xchg(&plane->work, NULL);

	if (!not_on_list)
	if (work)
		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
}

void armada_drm_vbl_event_remove(struct armada_crtc *dcrtc,
	struct armada_vbl_event *evt)
{
	spin_lock_irq(&dcrtc->irq_lock);
	if (!list_empty(&evt->node)) {
		list_del_init(&evt->node);
		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
	}
	spin_unlock_irq(&dcrtc->irq_lock);
}

static void armada_drm_vbl_event_run(struct armada_crtc *dcrtc)
{
	struct armada_vbl_event *e, *n;

	list_for_each_entry_safe(e, n, &dcrtc->vbl_list, node) {
		list_del_init(&e->node);
		drm_vblank_put(dcrtc->crtc.dev, dcrtc->num);
		e->fn(dcrtc, e->data);
	}
	return work;
}

static int armada_drm_crtc_queue_frame_work(struct armada_crtc *dcrtc,
@@ -429,6 +400,7 @@ static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
{
	void __iomem *base = dcrtc->base;
	struct drm_plane *ovl_plane;

	if (stat & DMA_FF_UNDERFLOW)
		DRM_ERROR("video underflow on crtc %u\n", dcrtc->num);
@@ -439,7 +411,12 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
		drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num);

	spin_lock(&dcrtc->irq_lock);
	armada_drm_vbl_event_run(dcrtc);
	ovl_plane = dcrtc->plane;
	if (ovl_plane) {
		struct armada_plane *plane = drm_to_armada_plane(ovl_plane);
		armada_drm_plane_work_run(dcrtc, plane);
		wake_up(&plane->frame_wait);
	}

	if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
		int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;
@@ -1188,7 +1165,6 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
	dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
	spin_lock_init(&dcrtc->irq_lock);
	dcrtc->irq_ena = CLEAN_SPU_IRQ_ISR;
	INIT_LIST_HEAD(&dcrtc->vbl_list);

	/* Initialize some registers which we don't otherwise set */
	writel_relaxed(0x00000001, dcrtc->base + LCD_CFG_SCLK_DIV);
+2 −18
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ int armada_drm_plane_init(struct armada_plane *plane);
int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
	struct armada_plane *plane, struct armada_plane_work *work);
int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
struct armada_plane_work *armada_drm_plane_work_cancel(
	struct armada_crtc *dcrtc, struct armada_plane *plane);

struct armada_crtc {
	struct drm_crtc		crtc;
@@ -87,27 +89,9 @@ struct armada_crtc {

	spinlock_t		irq_lock;
	uint32_t		irq_ena;
	struct list_head	vbl_list;
};
#define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)

struct armada_vbl_event {
	struct list_head	node;
	void			*data;
	void			(*fn)(struct armada_crtc *, void *);
};

void armada_drm_vbl_event_add(struct armada_crtc *,
	struct armada_vbl_event *);
void armada_drm_vbl_event_remove(struct armada_crtc *,
	struct armada_vbl_event *);
#define armada_drm_vbl_event_init(_e, _f, _d) do {	\
	struct armada_vbl_event *__e = _e;		\
	INIT_LIST_HEAD(&__e->node);			\
	__e->data = _d;					\
	__e->fn = _f;					\
} while (0)

void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
+12 −15
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ struct armada_ovl_plane {
	uint32_t dst_yx;
	uint32_t ctrl0;
	struct {
		struct armada_vbl_event update;
		struct armada_plane_work work;
		struct armada_regs regs[13];
	} vbl;
	struct armada_ovl_plane_properties prop;
@@ -82,14 +82,13 @@ static void armada_ovl_retire_fb(struct armada_ovl_plane *dplane,
}

/* === Plane support === */
static void armada_ovl_plane_vbl(struct armada_crtc *dcrtc, void *data)
static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
	struct armada_plane *plane, struct armada_plane_work *work)
{
	struct armada_ovl_plane *dplane = data;
	struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base);

	armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
	armada_ovl_retire_fb(dplane, NULL);

	wake_up(&dplane->base.frame_wait);
}

static int
@@ -162,9 +161,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
			       dcrtc->base + LCD_SPU_SRAM_PARA1);
	}

	wait_event_timeout(dplane->base.frame_wait,
			   list_empty(&dplane->vbl.update.node),
			   HZ/25);
	if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0)
		armada_drm_plane_work_cancel(dcrtc, &dplane->base);

	if (plane->fb != fb) {
		struct armada_gem_object *obj = drm_fb_obj(fb);
@@ -255,7 +253,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
	}
	if (idx) {
		armada_reg_queue_end(dplane->vbl.regs, idx);
		armada_drm_vbl_event_add(dcrtc, &dplane->vbl.update);
		armada_drm_plane_work_queue(dcrtc, &dplane->base,
					    &dplane->vbl.work);
	}
	return 0;
}
@@ -270,14 +269,13 @@ static int armada_ovl_plane_disable(struct drm_plane *plane)
		return 0;

	dcrtc = drm_to_armada_crtc(dplane->base.base.crtc);
	dcrtc->plane = NULL;

	armada_drm_vbl_event_remove(dcrtc, &dplane->vbl.update);
	armada_drm_plane_work_cancel(dcrtc, &dplane->base);
	armada_drm_crtc_plane_disable(dcrtc, plane);

	dcrtc->plane = NULL;
	dplane->ctrl0 = 0;

	armada_drm_crtc_plane_disable(dcrtc, plane);

	fb = xchg(&dplane->old_fb, NULL);
	if (fb)
		drm_framebuffer_unreference(fb);
@@ -456,8 +454,7 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
		return ret;
	}

	armada_drm_vbl_event_init(&dplane->vbl.update, armada_ovl_plane_vbl,
				  dplane);
	dplane->vbl.work.fn = armada_ovl_plane_work;

	ret = drm_universal_plane_init(dev, &dplane->base.base, crtcs,
				       &armada_ovl_plane_funcs,