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

Commit d6f7a18c authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'exynos-drm-next' of...

Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next

 This 2nd pull request includes the following,
   - add configurable plane support and relevant cleanups.
   - fixup kernel panic issue at drm releasing.
   - remove unnecessary codes.

   This has been delayed to resolve a critical issue - which incurrs
   a kernel panic when driver is released - and review it.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: fix kernel panic issue at drm releasing
  drm/exynos: crtc: do not wait for the scanout completion
  drm/exynos: mixer: properly update all planes on the same vblank event
  drm/exynos: crtc: rework atomic_{begin,flush}
  drm/exynos: mixer: unify a check for video-processor window
  drm/exynos: mixer: also allow ARGB1555 and ARGB4444
  drm/exynos: mixer: refactor layer setup
  drm/exynos: mixer: remove all static blending setup
  drm/exynos: mixer: set window priority based on zpos
  drm/exynos: make zpos property configurable
  drm/exynos: rename zpos to index
parents 06249e69 c74d8eb5
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -248,15 +248,16 @@ static void decon_shadow_protect_win(struct decon_context *ctx, int win,
		       protect ? ~0 : 0);
}

static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
					struct exynos_drm_plane *plane)
static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
{
	struct decon_context *ctx = crtc->ctx;
	int i;

	if (test_bit(BIT_SUSPENDED, &ctx->flags))
		return;

	decon_shadow_protect_win(ctx, plane->zpos, true);
	for (i = ctx->first_win; i < WINDOWS_NR; i++)
		decon_shadow_protect_win(ctx, i, true);
}

#define BIT_VAL(x, e, s) (((x) & ((1 << ((e) - (s) + 1)) - 1)) << (s))
@@ -270,7 +271,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
				to_exynos_plane_state(plane->base.state);
	struct decon_context *ctx = crtc->ctx;
	struct drm_framebuffer *fb = state->base.fb;
	unsigned int win = plane->zpos;
	unsigned int win = plane->index;
	unsigned int bpp = fb->bits_per_pixel >> 3;
	unsigned int pitch = fb->pitches[0];
	dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0);
@@ -320,7 +321,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
				struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	unsigned int win = plane->zpos;
	unsigned int win = plane->index;

	if (test_bit(BIT_SUSPENDED, &ctx->flags))
		return;
@@ -336,15 +337,16 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
}

static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
				struct exynos_drm_plane *plane)
static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
{
	struct decon_context *ctx = crtc->ctx;
	int i;

	if (test_bit(BIT_SUSPENDED, &ctx->flags))
		return;

	decon_shadow_protect_win(ctx, plane->zpos, false);
	for (i = ctx->first_win; i < WINDOWS_NR; i++)
		decon_shadow_protect_win(ctx, i, false);

	if (ctx->out_type == IFTYPE_I80)
		set_bit(BIT_WIN_UPDATED, &ctx->flags);
@@ -502,7 +504,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
		ctx->configs[win].zpos = win;
		ctx->configs[win].type = decon_win_types[tmp];

		ret = exynos_plane_init(drm_dev, &ctx->planes[win],
		ret = exynos_plane_init(drm_dev, &ctx->planes[win], win,
					1 << ctx->pipe, &ctx->configs[win]);
		if (ret)
			return ret;
+11 −9
Original line number Diff line number Diff line
@@ -385,15 +385,16 @@ static void decon_shadow_protect_win(struct decon_context *ctx,
	writel(val, ctx->regs + SHADOWCON);
}

static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
					struct exynos_drm_plane *plane)
static void decon_atomic_begin(struct exynos_drm_crtc *crtc)
{
	struct decon_context *ctx = crtc->ctx;
	int i;

	if (ctx->suspended)
		return;

	decon_shadow_protect_win(ctx, plane->zpos, true);
	for (i = 0; i < WINDOWS_NR; i++)
		decon_shadow_protect_win(ctx, i, true);
}

static void decon_update_plane(struct exynos_drm_crtc *crtc,
@@ -407,7 +408,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
	unsigned long val, alpha;
	unsigned int last_x;
	unsigned int last_y;
	unsigned int win = plane->zpos;
	unsigned int win = plane->index;
	unsigned int bpp = fb->bits_per_pixel >> 3;
	unsigned int pitch = fb->pitches[0];

@@ -498,7 +499,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
				struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	unsigned int win = plane->zpos;
	unsigned int win = plane->index;
	u32 val;

	if (ctx->suspended)
@@ -517,15 +518,16 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
	writel(val, ctx->regs + DECON_UPDATE);
}

static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
					struct exynos_drm_plane *plane)
static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
{
	struct decon_context *ctx = crtc->ctx;
	int i;

	if (ctx->suspended)
		return;

	decon_shadow_protect_win(ctx, plane->zpos, false);
	for (i = 0; i < WINDOWS_NR; i++)
		decon_shadow_protect_win(ctx, i, false);
}

static void decon_init(struct decon_context *ctx)
@@ -657,7 +659,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
		ctx->configs[i].zpos = i;
		ctx->configs[i].type = decon_win_types[i];

		ret = exynos_plane_init(drm_dev, &ctx->planes[i],
		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
					1 << ctx->pipe, &ctx->configs[i]);
		if (ret)
			return ret;
+30 −39
Original line number Diff line number Diff line
@@ -68,32 +68,20 @@ static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
				     struct drm_crtc_state *old_crtc_state)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct drm_plane *plane;

	exynos_crtc->event = crtc->state->event;

	drm_atomic_crtc_for_each_plane(plane, crtc) {
		struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);

	if (exynos_crtc->ops->atomic_begin)
			exynos_crtc->ops->atomic_begin(exynos_crtc,
							exynos_plane);
	}
		exynos_crtc->ops->atomic_begin(exynos_crtc);
}

static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
				     struct drm_crtc_state *old_crtc_state)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct drm_plane *plane;

	drm_atomic_crtc_for_each_plane(plane, crtc) {
		struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);

	if (exynos_crtc->ops->atomic_flush)
			exynos_crtc->ops->atomic_flush(exynos_crtc,
							exynos_plane);
	}
		exynos_crtc->ops->atomic_flush(exynos_crtc);
}

static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
@@ -215,29 +203,6 @@ void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
}

void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
{
	struct exynos_drm_crtc *exynos_crtc;
	struct drm_device *dev = fb->dev;
	struct drm_crtc *crtc;

	/*
	 * make sure that overlay data are updated to real hardware
	 * for all encoders.
	 */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		exynos_crtc = to_exynos_crtc(crtc);

		/*
		 * wait for vblank interrupt
		 * - this makes sure that overlay data are updated to
		 *	real hardware.
		 */
		if (exynos_crtc->ops->wait_for_vblank)
			exynos_crtc->ops->wait_for_vblank(exynos_crtc);
	}
}

int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
				       enum exynos_drm_output_type out_type)
{
@@ -261,3 +226,29 @@ void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
	if (exynos_crtc->ops->te_handler)
		exynos_crtc->ops->te_handler(exynos_crtc);
}

void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc,
					struct drm_file *file)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct drm_pending_vblank_event *e;
	unsigned long flags;

	spin_lock_irqsave(&crtc->dev->event_lock, flags);
	e = exynos_crtc->event;
	if (e && e->base.file_priv == file) {
		exynos_crtc->event = NULL;
		/*
		 * event will be destroyed by core part
		 * so below line should be removed later with core changes
		 */
		e->base.destroy(&e->base);
		/*
		 * event_space will be increased by core part
		 * so below line should be removed later with core changes.
		 */
		file->event_space += sizeof(e->event);
		atomic_dec(&exynos_crtc->pending_update);
	}
	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
}
+4 −1
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe);
void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
				   struct exynos_drm_plane *exynos_plane);
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);

/* This function gets pipe value to crtc device matched with out_type. */
int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
@@ -41,4 +40,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
 */
void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);

/* This function cancels a page flip request. */
void exynos_drm_crtc_cancel_page_flip(struct drm_crtc *crtc,
					struct drm_file *file);

#endif
+5 −0
Original line number Diff line number Diff line
@@ -330,7 +330,12 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
static void exynos_drm_preclose(struct drm_device *dev,
					struct drm_file *file)
{
	struct drm_crtc *crtc;

	exynos_drm_subdrv_close(dev, file);

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		exynos_drm_crtc_cancel_page_flip(crtc, file);
}

static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
Loading