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

Commit a7d68836 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 pull request contains just cleanup for atomic pageflip/modeset
   support, and some fixeups.

   We wanted to merge atomic pageflip/modeset feature support, new drivers
   - MIC and DECON for exynos5433 SoC - and relevant patches this time.
   However, I'd found that these features are not only safe enough
   but also aren't tested yet. So for them, I'd like to have enough times
   for the reviews.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: Fix FIMD buffer size calculation
  drm/exynos: Enable DP clock to fix display on Exynos5250 and other
  drm/exynos: fimd: check whether exynos_drm_crtc_create succeed or not
  drm/exynos: dsi: remove the empty mode_valid callback
  drm/exynos: add ratio calculation
  drm/exynos: use src_x and src_y instead of fb_x and fb_y
  drm/exynos: mixer: add 2x scaling to mixer_graph_buffer
  drm/exynos: remove superfluous error messages
  drm/exynos: fix typos in hdmi and mixer
  drm/exynos/ipp: Validate buffer enqueue requests
  drm/exynos: track vblank events on a per crtc basis
  drm/exynos: remove leftover functions declarations
  drm/exynos: remove exynos_plane_destroy()
  drm/exynos: make zpos property immutable
  drm/exynos: preset zpos value for overlay planes
  drm/exynos: remove struct *_win_data abstraction on planes
  drm/exynos: remove unused exynos_crtc->win_enable() callback
  drm/exynos: fimd: fix alpha setting for XR24 pixel format
parents 1d8ac08d 68a29134
Loading
Loading
Loading
Loading
+64 −114
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <video/exynos7_decon.h>

#include "exynos_drm_crtc.h"
#include "exynos_drm_plane.h"
#include "exynos_drm_drv.h"
#include "exynos_drm_fbdev.h"
#include "exynos_drm_iommu.h"
@@ -41,32 +42,16 @@

#define WINDOWS_NR	2

struct decon_win_data {
	unsigned int		ovl_x;
	unsigned int		ovl_y;
	unsigned int		offset_x;
	unsigned int		offset_y;
	unsigned int		ovl_width;
	unsigned int		ovl_height;
	unsigned int		fb_width;
	unsigned int		fb_height;
	unsigned int		bpp;
	unsigned int		pixel_format;
	dma_addr_t		dma_addr;
	bool			enabled;
	bool			resume;
};

struct decon_context {
	struct device			*dev;
	struct drm_device		*drm_dev;
	struct exynos_drm_crtc		*crtc;
	struct exynos_drm_plane		planes[WINDOWS_NR];
	struct clk			*pclk;
	struct clk			*aclk;
	struct clk			*eclk;
	struct clk			*vclk;
	void __iomem			*regs;
	struct decon_win_data		win_data[WINDOWS_NR];
	unsigned int			default_win;
	unsigned long			irq_flags;
	bool				i80_if;
@@ -296,59 +281,16 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)
	}
}

static void decon_win_mode_set(struct exynos_drm_crtc *crtc,
			struct exynos_drm_plane *plane)
{
	struct decon_context *ctx = crtc->ctx;
	struct decon_win_data *win_data;
	int win, padding;

	if (!plane) {
		DRM_ERROR("plane is NULL\n");
		return;
	}

	win = plane->zpos;
	if (win == DEFAULT_ZPOS)
		win = ctx->default_win;

	if (win < 0 || win >= WINDOWS_NR)
		return;


	win_data = &ctx->win_data[win];

	padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
	win_data->offset_x = plane->fb_x;
	win_data->offset_y = plane->fb_y;
	win_data->fb_width = plane->fb_width + padding;
	win_data->fb_height = plane->fb_height;
	win_data->ovl_x = plane->crtc_x;
	win_data->ovl_y = plane->crtc_y;
	win_data->ovl_width = plane->crtc_width;
	win_data->ovl_height = plane->crtc_height;
	win_data->dma_addr = plane->dma_addr[0];
	win_data->bpp = plane->bpp;
	win_data->pixel_format = plane->pixel_format;

	DRM_DEBUG_KMS("offset_x = %d, offset_y = %d\n",
			win_data->offset_x, win_data->offset_y);
	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
			win_data->ovl_width, win_data->ovl_height);
	DRM_DEBUG_KMS("paddr = 0x%lx\n", (unsigned long)win_data->dma_addr);
	DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
			plane->fb_width, plane->crtc_width);
}

static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
{
	struct decon_win_data *win_data = &ctx->win_data[win];
	struct exynos_drm_plane *plane = &ctx->planes[win];
	unsigned long val;
	int padding;

	val = readl(ctx->regs + WINCON(win));
	val &= ~WINCONx_BPPMODE_MASK;

	switch (win_data->pixel_format) {
	switch (plane->pixel_format) {
	case DRM_FORMAT_RGB565:
		val |= WINCONx_BPPMODE_16BPP_565;
		val |= WINCONx_BURSTLEN_16WORD;
@@ -397,7 +339,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
		break;
	}

	DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp);
	DRM_DEBUG_KMS("bpp = %d\n", plane->bpp);

	/*
	 * In case of exynos, setting dma-burst to 16Word causes permanent
@@ -407,7 +349,8 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win)
	 * movement causes unstable DMA which results into iommu crash/tear.
	 */

	if (win_data->fb_width < MIN_FB_WIDTH_FOR_16WORD_BURST) {
	padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;
	if (plane->fb_width + padding < MIN_FB_WIDTH_FOR_16WORD_BURST) {
		val &= ~WINCONx_BURSTLEN_MASK;
		val |= WINCONx_BURSTLEN_8WORD;
	}
@@ -435,7 +378,7 @@ static void decon_win_set_colkey(struct decon_context *ctx, unsigned int win)
 * @protect: 1 to protect (disable updates)
 */
static void decon_shadow_protect_win(struct decon_context *ctx,
							int win, bool protect)
				     unsigned int win, bool protect)
{
	u32 bits, val;

@@ -449,12 +392,12 @@ static void decon_shadow_protect_win(struct decon_context *ctx,
	writel(val, ctx->regs + SHADOWCON);
}

static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
static void decon_win_commit(struct exynos_drm_crtc *crtc, unsigned int win)
{
	struct decon_context *ctx = crtc->ctx;
	struct drm_display_mode *mode = &crtc->base.mode;
	struct decon_win_data *win_data;
	int win = zpos;
	struct exynos_drm_plane *plane;
	int padding;
	unsigned long val, alpha;
	unsigned int last_x;
	unsigned int last_y;
@@ -462,17 +405,14 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
	if (ctx->suspended)
		return;

	if (win == DEFAULT_ZPOS)
		win = ctx->default_win;

	if (win < 0 || win >= WINDOWS_NR)
		return;

	win_data = &ctx->win_data[win];
	plane = &ctx->planes[win];

	/* If suspended, enable this on resume */
	if (ctx->suspended) {
		win_data->resume = true;
		plane->resume = true;
		return;
	}

@@ -490,39 +430,41 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
	decon_shadow_protect_win(ctx, win, true);

	/* buffer start address */
	val = (unsigned long)win_data->dma_addr;
	val = (unsigned long)plane->dma_addr[0];
	writel(val, ctx->regs + VIDW_BUF_START(win));

	padding = (plane->pitch / (plane->bpp >> 3)) - plane->fb_width;

	/* buffer size */
	writel(win_data->fb_width, ctx->regs + VIDW_WHOLE_X(win));
	writel(win_data->fb_height, ctx->regs + VIDW_WHOLE_Y(win));
	writel(plane->fb_width + padding, ctx->regs + VIDW_WHOLE_X(win));
	writel(plane->fb_height, ctx->regs + VIDW_WHOLE_Y(win));

	/* offset from the start of the buffer to read */
	writel(win_data->offset_x, ctx->regs + VIDW_OFFSET_X(win));
	writel(win_data->offset_y, ctx->regs + VIDW_OFFSET_Y(win));
	writel(plane->src_x, ctx->regs + VIDW_OFFSET_X(win));
	writel(plane->src_y, ctx->regs + VIDW_OFFSET_Y(win));

	DRM_DEBUG_KMS("start addr = 0x%lx\n",
			(unsigned long)win_data->dma_addr);
			(unsigned long)val);
	DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
			win_data->ovl_width, win_data->ovl_height);
			plane->crtc_width, plane->crtc_height);

	/*
	 * OSD position.
	 * In case the window layout goes of LCD layout, DECON fails.
	 */
	if ((win_data->ovl_x + win_data->ovl_width) > mode->hdisplay)
		win_data->ovl_x = mode->hdisplay - win_data->ovl_width;
	if ((win_data->ovl_y + win_data->ovl_height) > mode->vdisplay)
		win_data->ovl_y = mode->vdisplay - win_data->ovl_height;
	if ((plane->crtc_x + plane->crtc_width) > mode->hdisplay)
		plane->crtc_x = mode->hdisplay - plane->crtc_width;
	if ((plane->crtc_y + plane->crtc_height) > mode->vdisplay)
		plane->crtc_y = mode->vdisplay - plane->crtc_height;

	val = VIDOSDxA_TOPLEFT_X(win_data->ovl_x) |
		VIDOSDxA_TOPLEFT_Y(win_data->ovl_y);
	val = VIDOSDxA_TOPLEFT_X(plane->crtc_x) |
		VIDOSDxA_TOPLEFT_Y(plane->crtc_y);
	writel(val, ctx->regs + VIDOSD_A(win));

	last_x = win_data->ovl_x + win_data->ovl_width;
	last_x = plane->crtc_x + plane->crtc_width;
	if (last_x)
		last_x--;
	last_y = win_data->ovl_y + win_data->ovl_height;
	last_y = plane->crtc_y + plane->crtc_height;
	if (last_y)
		last_y--;

@@ -531,7 +473,7 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
	writel(val, ctx->regs + VIDOSD_B(win));

	DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %d\n",
			win_data->ovl_x, win_data->ovl_y, last_x, last_y);
			plane->crtc_x, plane->crtc_y, last_x, last_y);

	/* OSD alpha */
	alpha = VIDOSDxC_ALPHA0_R_F(0x0) |
@@ -565,27 +507,23 @@ static void decon_win_commit(struct exynos_drm_crtc *crtc, int zpos)
	val |= DECON_UPDATE_STANDALONE_F;
	writel(val, ctx->regs + DECON_UPDATE);

	win_data->enabled = true;
	plane->enabled = true;
}

static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
static void decon_win_disable(struct exynos_drm_crtc *crtc, unsigned int win)
{
	struct decon_context *ctx = crtc->ctx;
	struct decon_win_data *win_data;
	int win = zpos;
	struct exynos_drm_plane *plane;
	u32 val;

	if (win == DEFAULT_ZPOS)
		win = ctx->default_win;

	if (win < 0 || win >= WINDOWS_NR)
		return;

	win_data = &ctx->win_data[win];
	plane = &ctx->planes[win];

	if (ctx->suspended) {
		/* do not resume this window*/
		win_data->resume = false;
		plane->resume = false;
		return;
	}

@@ -604,42 +542,42 @@ static void decon_win_disable(struct exynos_drm_crtc *crtc, int zpos)
	val |= DECON_UPDATE_STANDALONE_F;
	writel(val, ctx->regs + DECON_UPDATE);

	win_data->enabled = false;
	plane->enabled = false;
}

static void decon_window_suspend(struct decon_context *ctx)
{
	struct decon_win_data *win_data;
	struct exynos_drm_plane *plane;
	int i;

	for (i = 0; i < WINDOWS_NR; i++) {
		win_data = &ctx->win_data[i];
		win_data->resume = win_data->enabled;
		if (win_data->enabled)
		plane = &ctx->planes[i];
		plane->resume = plane->enabled;
		if (plane->enabled)
			decon_win_disable(ctx->crtc, i);
	}
}

static void decon_window_resume(struct decon_context *ctx)
{
	struct decon_win_data *win_data;
	struct exynos_drm_plane *plane;
	int i;

	for (i = 0; i < WINDOWS_NR; i++) {
		win_data = &ctx->win_data[i];
		win_data->enabled = win_data->resume;
		win_data->resume = false;
		plane = &ctx->planes[i];
		plane->enabled = plane->resume;
		plane->resume = false;
	}
}

static void decon_apply(struct decon_context *ctx)
{
	struct decon_win_data *win_data;
	struct exynos_drm_plane *plane;
	int i;

	for (i = 0; i < WINDOWS_NR; i++) {
		win_data = &ctx->win_data[i];
		if (win_data->enabled)
		plane = &ctx->planes[i];
		if (plane->enabled)
			decon_win_commit(ctx->crtc, i);
		else
			decon_win_disable(ctx->crtc, i);
@@ -779,7 +717,6 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
	.enable_vblank = decon_enable_vblank,
	.disable_vblank = decon_disable_vblank,
	.wait_for_vblank = decon_wait_for_vblank,
	.win_mode_set = decon_win_mode_set,
	.win_commit = decon_win_commit,
	.win_disable = decon_win_disable,
};
@@ -818,6 +755,9 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
{
	struct decon_context *ctx = dev_get_drvdata(dev);
	struct drm_device *drm_dev = data;
	struct exynos_drm_plane *exynos_plane;
	enum drm_plane_type type;
	unsigned int zpos;
	int ret;

	ret = decon_ctx_initialize(ctx, drm_dev);
@@ -826,8 +766,18 @@ static int decon_bind(struct device *dev, struct device *master, void *data)
		return ret;
	}

	ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
					   EXYNOS_DISPLAY_TYPE_LCD,
	for (zpos = 0; zpos < WINDOWS_NR; zpos++) {
		type = (zpos == ctx->default_win) ? DRM_PLANE_TYPE_PRIMARY :
						DRM_PLANE_TYPE_OVERLAY;
		ret = exynos_plane_init(drm_dev, &ctx->planes[zpos],
					1 << ctx->pipe, type, zpos);
		if (ret)
			return ret;
	}

	exynos_plane = &ctx->planes[ctx->default_win];
	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
					   ctx->pipe, EXYNOS_DISPLAY_TYPE_LCD,
					   &decon_crtc_ops, ctx);
	if (IS_ERR(ctx->crtc)) {
		decon_ctx_remove(ctx);
+10 −0
Original line number Diff line number Diff line
@@ -32,10 +32,16 @@
#include <drm/bridge/ptn3460.h>

#include "exynos_dp_core.h"
#include "exynos_drm_fimd.h"

#define ctx_from_connector(c)	container_of(c, struct exynos_dp_device, \
					connector)

static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
{
	return to_exynos_crtc(dp->encoder->crtc);
}

static inline struct exynos_dp_device *
display_to_dp(struct exynos_drm_display *d)
{
@@ -1070,6 +1076,8 @@ static void exynos_dp_poweron(struct exynos_dp_device *dp)
		}
	}

	fimd_dp_clock_enable(dp_to_crtc(dp), true);

	clk_prepare_enable(dp->clock);
	exynos_dp_phy_init(dp);
	exynos_dp_init_dp(dp);
@@ -1094,6 +1102,8 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp)
	exynos_dp_phy_exit(dp);
	clk_disable_unprepare(dp->clock);

	fimd_dp_clock_enable(dp_to_crtc(dp), false);

	if (dp->panel) {
		if (drm_panel_unprepare(dp->panel))
			DRM_ERROR("failed to turnoff the panel\n");
+43 −58
Original line number Diff line number Diff line
@@ -34,9 +34,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
	if (mode > DRM_MODE_DPMS_ON) {
		/* wait for the completion of page flip. */
		if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
				!atomic_read(&exynos_crtc->pending_flip),
				HZ/20))
			atomic_set(&exynos_crtc->pending_flip, 0);
				(exynos_crtc->event == NULL), HZ/20))
			exynos_crtc->event = NULL;
		drm_crtc_vblank_off(crtc);
	}

@@ -164,11 +163,10 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
				     uint32_t page_flip_flags)
{
	struct drm_device *dev = crtc->dev;
	struct exynos_drm_private *dev_priv = dev->dev_private;
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct drm_framebuffer *old_fb = crtc->primary->fb;
	unsigned int crtc_w, crtc_h;
	int ret = -EINVAL;
	int ret;

	/* when the page flip is requested, crtc's dpms should be on */
	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
@@ -176,28 +174,30 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
		return -EINVAL;
	}

	mutex_lock(&dev->struct_mutex);
	if (!event)
		return -EINVAL;

	if (event) {
		/*
		 * the pipe from user always is 0 so we can set pipe number
		 * of current owner to event.
		 */
		event->pipe = exynos_crtc->pipe;
	spin_lock_irq(&dev->event_lock);
	if (exynos_crtc->event) {
		ret = -EBUSY;
		goto out;
	}

	ret = drm_vblank_get(dev, exynos_crtc->pipe);
	if (ret) {
		DRM_DEBUG("failed to acquire vblank counter\n");

		goto out;
	}

		spin_lock_irq(&dev->event_lock);
		list_add_tail(&event->base.link,
				&dev_priv->pageflip_event_list);
		atomic_set(&exynos_crtc->pending_flip, 1);
	exynos_crtc->event = event;
	spin_unlock_irq(&dev->event_lock);

	/*
	 * the pipe from user always is 0 so we can set pipe number
	 * of current owner to event.
	 */
	event->pipe = exynos_crtc->pipe;

	crtc->primary->fb = fb;
	crtc_w = fb->width - crtc->x;
	crtc_h = fb->height - crtc->y;
@@ -206,18 +206,17 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
				  crtc_w, crtc_h);
	if (ret) {
		crtc->primary->fb = old_fb;

		spin_lock_irq(&dev->event_lock);
		exynos_crtc->event = NULL;
		drm_vblank_put(dev, exynos_crtc->pipe);
			list_del(&event->base.link);
			atomic_set(&exynos_crtc->pending_flip, 0);
		spin_unlock_irq(&dev->event_lock);

			goto out;
		}
		return ret;
	}

	return 0;

out:
	mutex_unlock(&dev->struct_mutex);
	spin_unlock_irq(&dev->event_lock);
	return ret;
}

@@ -239,13 +238,13 @@ static struct drm_crtc_funcs exynos_crtc_funcs = {
};

struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
					       struct drm_plane *plane,
					       int pipe,
					       enum exynos_drm_output_type type,
					       struct exynos_drm_crtc_ops *ops,
					       void *ctx)
{
	struct exynos_drm_crtc *exynos_crtc;
	struct drm_plane *plane;
	struct exynos_drm_private *private = drm_dev->dev_private;
	struct drm_crtc *crtc;
	int ret;
@@ -255,19 +254,12 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
		return ERR_PTR(-ENOMEM);

	init_waitqueue_head(&exynos_crtc->pending_flip_queue);
	atomic_set(&exynos_crtc->pending_flip, 0);

	exynos_crtc->dpms = DRM_MODE_DPMS_OFF;
	exynos_crtc->pipe = pipe;
	exynos_crtc->type = type;
	exynos_crtc->ops = ops;
	exynos_crtc->ctx = ctx;
	plane = exynos_plane_init(drm_dev, 1 << pipe,
				  DRM_PLANE_TYPE_PRIMARY);
	if (IS_ERR(plane)) {
		ret = PTR_ERR(plane);
		goto err_plane;
	}

	crtc = &exynos_crtc->base;

@@ -284,7 +276,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,

err_crtc:
	plane->funcs->destroy(plane);
err_plane:
	kfree(exynos_crtc);
	return ERR_PTR(ret);
}
@@ -320,26 +311,20 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
{
	struct exynos_drm_private *dev_priv = dev->dev_private;
	struct drm_pending_vblank_event *e, *t;
	struct drm_crtc *drm_crtc = dev_priv->crtc[pipe];
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
	unsigned long flags;

	spin_lock_irqsave(&dev->event_lock, flags);
	if (exynos_crtc->event) {

	list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
			base.link) {
		/* if event's pipe isn't same as crtc then ignore it. */
		if (pipe != e->pipe)
			continue;

		list_del(&e->base.link);
		drm_send_vblank_event(dev, -1, e);
		drm_send_vblank_event(dev, -1, exynos_crtc->event);
		drm_vblank_put(dev, pipe);
		atomic_set(&exynos_crtc->pending_flip, 0);
		wake_up(&exynos_crtc->pending_flip_queue);

	}

	exynos_crtc->event = NULL;
	spin_unlock_irqrestore(&dev->event_lock, flags);
}

+1 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include "exynos_drm_drv.h"

struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
					       struct drm_plane *plane,
					       int pipe,
					       enum exynos_drm_output_type type,
					       struct exynos_drm_crtc_ops *ops,
@@ -27,12 +28,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe);
void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);

void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
			struct exynos_drm_plane *plane);
void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos);
void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);

/* 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,
					unsigned int out_type);
+0 −27
Original line number Diff line number Diff line
@@ -55,13 +55,11 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
{
	struct exynos_drm_private *private;
	int ret;
	int nr;

	private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
	if (!private)
		return -ENOMEM;

	INIT_LIST_HEAD(&private->pageflip_event_list);
	dev_set_drvdata(dev->dev, dev);
	dev->dev_private = (void *)private;

@@ -81,19 +79,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)

	exynos_drm_mode_config_init(dev);

	for (nr = 0; nr < MAX_PLANE; nr++) {
		struct drm_plane *plane;
		unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;

		plane = exynos_plane_init(dev, possible_crtcs,
					  DRM_PLANE_TYPE_OVERLAY);
		if (!IS_ERR(plane))
			continue;

		ret = PTR_ERR(plane);
		goto err_mode_config_cleanup;
	}

	/* setup possible_clones. */
	exynos_drm_encoder_setup(dev);

@@ -237,25 +222,13 @@ static void exynos_drm_preclose(struct drm_device *dev,

static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
{
	struct exynos_drm_private *private = dev->dev_private;
	struct drm_pending_vblank_event *v, *vt;
	struct drm_pending_event *e, *et;
	unsigned long flags;

	if (!file->driver_priv)
		return;

	/* Release all events not unhandled by page flip handler. */
	spin_lock_irqsave(&dev->event_lock, flags);
	list_for_each_entry_safe(v, vt, &private->pageflip_event_list,
			base.link) {
		if (v->base.file_priv == file) {
			list_del(&v->base.link);
			drm_vblank_put(dev, v->pipe);
			v->base.destroy(&v->base);
		}
	}

	/* Release all events handled by page flip handler but not freed. */
	list_for_each_entry_safe(e, et, &file->event_list, link) {
		list_del(&e->link);
Loading