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

Commit 923e0575 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 includes some code refactoring which removes
   Exynos specific structure names and uses generic structure
   names instead, and makes all plane updating to be done
   by only exynos_update_plane function. And also it includes
   some cleanup and fixup patches.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (22 commits)
  drm/exynos: fimd: check error status for drm_iommu_attach_device
  drm/exynos: create exynos_check_plane()
  drm/exynos: remove mode_set() ops from exynos_crtc
  drm/exynos: don't duplicate drm_display_mode in fimd context
  drm/exynos: remove struct exynos_drm_manager
  drm/exynos: remove drm_dev from struct exynos_drm_manager
  drm/exynos: move 'type' from manager to crtc struct
  drm/exynos: remove pipe member of struct exynos_drm_manager
  drm/exynos: add pipe param to exynos_drm_crtc_create()
  drm/exynos: rename base object of struct exynos_drm_crtc to 'base'
  drm/exynos: remove exynos_drm_crtc_mode_set_commit()
  drm/exynos: call exynos_update_plane() directly on page flips
  drm/exynos: unify plane update on exynos_update_plane()
  drm/exynos: remove exynos_plane_commit() wrapper
  drm/exynos: don't do any DPMS operation while updating planes
  drm/exynos: Don't touch DPMS when updating overlay planes
  drm/exynos/vidi: remove useless ops->commit()
  drm/exynos/fimd: don't initialize 'ret' variable in fimd_probe()
  drm/exynos: remove struct exynos_drm_overlay
  drm/exynos: remove exynos_drm_crtc_plane_* wrappers
  ...
parents f43dff0e efa75bcd
Loading
Loading
Loading
Loading
+57 −128
Original line number Diff line number Diff line
@@ -20,43 +20,9 @@
#include "exynos_drm_encoder.h"
#include "exynos_drm_plane.h"

#define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc,\
				drm_crtc)

enum exynos_crtc_mode {
	CRTC_MODE_NORMAL,	/* normal mode */
	CRTC_MODE_BLANK,	/* The private plane of crtc is blank */
};

/*
 * Exynos specific crtc structure.
 *
 * @drm_crtc: crtc object.
 * @manager: the manager associated with this crtc
 * @pipe: a crtc index created at load() with a new crtc object creation
 *	and the crtc object would be set to private->crtc array
 *	to get a crtc object corresponding to this pipe from private->crtc
 *	array when irq interrupt occurred. the reason of using this pipe is that
 *	drm framework doesn't support multiple irq yet.
 *	we can refer to the crtc to current hardware interrupt occurred through
 *	this pipe value.
 * @dpms: store the crtc dpms value
 * @mode: store the crtc mode value
 */
struct exynos_drm_crtc {
	struct drm_crtc			drm_crtc;
	struct exynos_drm_manager	*manager;
	unsigned int			pipe;
	unsigned int			dpms;
	enum exynos_crtc_mode		mode;
	wait_queue_head_t		pending_flip_queue;
	atomic_t			pending_flip;
};

static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct exynos_drm_manager *manager = exynos_crtc->manager;

	DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);

@@ -74,8 +40,8 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
		drm_crtc_vblank_off(crtc);
	}

	if (manager->ops->dpms)
		manager->ops->dpms(manager, mode);
	if (exynos_crtc->ops->dpms)
		exynos_crtc->ops->dpms(exynos_crtc, mode);

	exynos_crtc->dpms = mode;

@@ -91,14 +57,15 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct exynos_drm_manager *manager = exynos_crtc->manager;
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(crtc->primary);

	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);

	exynos_plane_commit(crtc->primary);
	if (exynos_crtc->ops->win_commit)
		exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);

	if (manager->ops->commit)
		manager->ops->commit(manager);
	if (exynos_crtc->ops->commit)
		exynos_crtc->ops->commit(exynos_crtc);

	exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON);
}
@@ -109,10 +76,10 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
			    struct drm_display_mode *adjusted_mode)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct exynos_drm_manager *manager = exynos_crtc->manager;

	if (manager->ops->mode_fixup)
		return manager->ops->mode_fixup(manager, mode, adjusted_mode);
	if (exynos_crtc->ops->mode_fixup)
		return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
						    adjusted_mode);

	return true;
}
@@ -122,11 +89,10 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
			  struct drm_display_mode *adjusted_mode, int x, int y,
			  struct drm_framebuffer *old_fb)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct exynos_drm_manager *manager = exynos_crtc->manager;
	struct drm_framebuffer *fb = crtc->primary->fb;
	unsigned int crtc_w;
	unsigned int crtc_h;
	int ret;

	/*
	 * copy the mode data adjusted by mode_fixup() into crtc->mode
@@ -134,24 +100,25 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
	 */
	memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode));

	ret = exynos_check_plane(crtc->primary, fb);
	if (ret < 0)
		return ret;

	crtc_w = fb->width - x;
	crtc_h = fb->height - y;

	if (manager->ops->mode_set)
		manager->ops->mode_set(manager, &crtc->mode);

	return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
	exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
			      crtc_w, crtc_h, x, y, crtc_w, crtc_h);

	return 0;
}

static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
					  struct drm_framebuffer *old_fb)
{
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct drm_framebuffer *fb = crtc->primary->fb;
	unsigned int crtc_w;
	unsigned int crtc_h;
	int ret;

	/* when framebuffer changing is requested, crtc's dpms should be on */
	if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
@@ -162,20 +129,8 @@ static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
	crtc_w = fb->width - x;
	crtc_h = fb->height - y;

	ret = exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0,
	return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
				   crtc_w, crtc_h, x, y, crtc_w, crtc_h);
	if (ret)
		return ret;

	exynos_drm_crtc_commit(crtc);

	return 0;
}

static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
					  struct drm_framebuffer *old_fb)
{
	return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb);
}

static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
@@ -214,6 +169,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
	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;

	/* when the page flip is requested, crtc's dpms should be on */
@@ -245,8 +201,11 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
		spin_unlock_irq(&dev->event_lock);

		crtc->primary->fb = fb;
		ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y,
						    NULL);
		crtc_w = fb->width - crtc->x;
		crtc_h = fb->height - crtc->y;
		ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
					  crtc_w, crtc_h, crtc->x, crtc->y,
					  crtc_w, crtc_h);
		if (ret) {
			crtc->primary->fb = old_fb;

@@ -339,37 +298,42 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
	drm_object_attach_property(&crtc->base, prop, 0);
}

int exynos_drm_crtc_create(struct exynos_drm_manager *manager)
struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
					       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 = manager->drm_dev->dev_private;
	struct exynos_drm_private *private = drm_dev->dev_private;
	struct drm_crtc *crtc;
	int ret;

	exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
	if (!exynos_crtc)
		return -ENOMEM;
		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->manager = manager;
	exynos_crtc->pipe = manager->pipe;
	plane = exynos_plane_init(manager->drm_dev, 1 << manager->pipe,
	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;
	}

	manager->crtc = &exynos_crtc->drm_crtc;
	crtc = &exynos_crtc->drm_crtc;
	crtc = &exynos_crtc->base;

	private->crtc[manager->pipe] = crtc;
	private->crtc[pipe] = crtc;

	ret = drm_crtc_init_with_planes(manager->drm_dev, crtc, plane, NULL,
	ret = drm_crtc_init_with_planes(drm_dev, crtc, plane, NULL,
					&exynos_crtc_funcs);
	if (ret < 0)
		goto err_crtc;
@@ -378,13 +342,13 @@ int exynos_drm_crtc_create(struct exynos_drm_manager *manager)

	exynos_drm_crtc_attach_mode_property(crtc);

	return 0;
	return exynos_crtc;

err_crtc:
	plane->funcs->destroy(plane);
err_plane:
	kfree(exynos_crtc);
	return ret;
	return ERR_PTR(ret);
}

int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
@@ -392,13 +356,12 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe)
	struct exynos_drm_private *private = dev->dev_private;
	struct exynos_drm_crtc *exynos_crtc =
		to_exynos_crtc(private->crtc[pipe]);
	struct exynos_drm_manager *manager = exynos_crtc->manager;

	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
		return -EPERM;

	if (manager->ops->enable_vblank)
		manager->ops->enable_vblank(manager);
	if (exynos_crtc->ops->enable_vblank)
		exynos_crtc->ops->enable_vblank(exynos_crtc);

	return 0;
}
@@ -408,13 +371,12 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
	struct exynos_drm_private *private = dev->dev_private;
	struct exynos_drm_crtc *exynos_crtc =
		to_exynos_crtc(private->crtc[pipe]);
	struct exynos_drm_manager *manager = exynos_crtc->manager;

	if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
		return;

	if (manager->ops->disable_vblank)
		manager->ops->disable_vblank(manager);
	if (exynos_crtc->ops->disable_vblank)
		exynos_crtc->ops->disable_vblank(exynos_crtc);
}

void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
@@ -443,42 +405,9 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe)
	spin_unlock_irqrestore(&dev->event_lock, flags);
}

void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc,
			struct exynos_drm_overlay *overlay)
{
	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;

	if (manager->ops->win_mode_set)
		manager->ops->win_mode_set(manager, overlay);
}

void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos)
{
	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;

	if (manager->ops->win_commit)
		manager->ops->win_commit(manager, zpos);
}

void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos)
{
	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;

	if (manager->ops->win_enable)
		manager->ops->win_enable(manager, zpos);
}

void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos)
{
	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;

	if (manager->ops->win_disable)
		manager->ops->win_disable(manager, zpos);
}

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

@@ -487,15 +416,15 @@ void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb)
	 * for all encoders.
	 */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		manager = to_exynos_crtc(crtc)->manager;
		exynos_crtc = to_exynos_crtc(crtc);

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

@@ -508,8 +437,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
		struct exynos_drm_crtc *exynos_crtc;

		exynos_crtc = to_exynos_crtc(crtc);
		if (exynos_crtc->manager->type == out_type)
			return exynos_crtc->manager->pipe;
		if (exynos_crtc->type == out_type)
			return exynos_crtc->pipe;
	}

	return -EPERM;
@@ -517,8 +446,8 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,

void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
{
	struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);

	if (manager->ops->te_handler)
		manager->ops->te_handler(manager);
	if (exynos_crtc->ops->te_handler)
		exynos_crtc->ops->te_handler(exynos_crtc);
}
+6 −2
Original line number Diff line number Diff line
@@ -17,14 +17,18 @@

#include "exynos_drm_drv.h"

int exynos_drm_crtc_create(struct exynos_drm_manager *manager);
struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
					       int pipe,
					       enum exynos_drm_output_type type,
					       struct exynos_drm_crtc_ops *ops,
					       void *context);
int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
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_overlay *overlay);
			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);
+51 −32
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@
#define MAX_FB_BUFFER	4
#define DEFAULT_ZPOS	-1

#define to_exynos_crtc(x)	container_of(x, struct exynos_drm_crtc, base)
#define to_exynos_plane(x)	container_of(x, struct exynos_drm_plane, base)

/* This enumerates device type. */
enum exynos_drm_device_type {
	EXYNOS_DEVICE_TYPE_NONE,
@@ -44,6 +47,7 @@ enum exynos_drm_output_type {
/*
 * Exynos drm common overlay structure.
 *
 * @base: plane object
 * @fb_x: offset x on a framebuffer to be displayed.
 *	- the unit is screen coordinates.
 * @fb_y: offset y on a framebuffer to be displayed.
@@ -73,11 +77,14 @@ enum exynos_drm_output_type {
 * @local_path: in case of lcd type, local path mode on or off.
 * @transparency: transparency on or off.
 * @activated: activated or not.
 * @enabled: enabled or not.
 *
 * this structure is common to exynos SoC and its contents would be copied
 * to hardware specific overlay info.
 */
struct exynos_drm_overlay {

struct exynos_drm_plane {
	struct drm_plane base;
	unsigned int fb_x;
	unsigned int fb_y;
	unsigned int fb_width;
@@ -104,6 +111,7 @@ struct exynos_drm_overlay {
	bool local_path:1;
	bool transparency:1;
	bool activated:1;
	bool enabled:1;
};

/*
@@ -155,11 +163,10 @@ struct exynos_drm_display {
};

/*
 * Exynos drm manager ops
 * Exynos drm crtc ops
 *
 * @dpms: control device power.
 * @mode_fixup: fix mode data before applying it
 * @mode_set: set the given mode to the manager
 * @commit: set current hw specific display mode to hw.
 * @enable_vblank: specific driver callback for enabling vblank interrupt.
 * @disable_vblank: specific driver callback for disabling vblank interrupt.
@@ -172,44 +179,56 @@ struct exynos_drm_display {
 * @te_handler: trigger to transfer video image at the tearing effect
 *	synchronization signal if there is a page flip request.
 */
struct exynos_drm_manager;
struct exynos_drm_manager_ops {
	void (*dpms)(struct exynos_drm_manager *mgr, int mode);
	bool (*mode_fixup)(struct exynos_drm_manager *mgr,
struct exynos_drm_crtc;
struct exynos_drm_crtc_ops {
	void (*dpms)(struct exynos_drm_crtc *crtc, int mode);
	bool (*mode_fixup)(struct exynos_drm_crtc *crtc,
				const struct drm_display_mode *mode,
				struct drm_display_mode *adjusted_mode);
	void (*mode_set)(struct exynos_drm_manager *mgr,
				const struct drm_display_mode *mode);
	void (*commit)(struct exynos_drm_manager *mgr);
	int (*enable_vblank)(struct exynos_drm_manager *mgr);
	void (*disable_vblank)(struct exynos_drm_manager *mgr);
	void (*wait_for_vblank)(struct exynos_drm_manager *mgr);
	void (*win_mode_set)(struct exynos_drm_manager *mgr,
				struct exynos_drm_overlay *overlay);
	void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
	void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
	void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
	void (*te_handler)(struct exynos_drm_manager *mgr);
	void (*commit)(struct exynos_drm_crtc *crtc);
	int (*enable_vblank)(struct exynos_drm_crtc *crtc);
	void (*disable_vblank)(struct exynos_drm_crtc *crtc);
	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
	void (*win_mode_set)(struct exynos_drm_crtc *crtc,
				struct exynos_drm_plane *plane);
	void (*win_commit)(struct exynos_drm_crtc *crtc, int zpos);
	void (*win_enable)(struct exynos_drm_crtc *crtc, int zpos);
	void (*win_disable)(struct exynos_drm_crtc *crtc, int zpos);
	void (*te_handler)(struct exynos_drm_crtc *crtc);
};

enum exynos_crtc_mode {
	CRTC_MODE_NORMAL,	/* normal mode */
	CRTC_MODE_BLANK,	/* The private plane of crtc is blank */
};

/*
 * Exynos drm common manager structure, maps 1:1 with a crtc
 * Exynos specific crtc structure.
 *
 * @list: the list entry for this manager
 * @base: crtc object.
 * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI.
 * @drm_dev: pointer to the drm device
 * @crtc: crtc object.
 * @pipe: the pipe number for this crtc/manager
 * @pipe: a crtc index created at load() with a new crtc object creation
 *	and the crtc object would be set to private->crtc array
 *	to get a crtc object corresponding to this pipe from private->crtc
 *	array when irq interrupt occurred. the reason of using this pipe is that
 *	drm framework doesn't support multiple irq yet.
 *	we can refer to the crtc to current hardware interrupt occurred through
 *	this pipe value.
 * @dpms: store the crtc dpms value
 * @mode: store the crtc mode value
 * @ops: pointer to callbacks for exynos drm specific functionality
 * @ctx: A pointer to the manager's implementation specific context
 * @ctx: A pointer to the crtc's implementation specific context
 */
struct exynos_drm_manager {
	struct list_head list;
struct exynos_drm_crtc {
	struct drm_crtc			base;
	enum exynos_drm_output_type	type;
	struct drm_device *drm_dev;
	struct drm_crtc *crtc;
	int pipe;
	struct exynos_drm_manager_ops *ops;
	unsigned int			pipe;
	unsigned int			dpms;
	enum exynos_crtc_mode		mode;
	wait_queue_head_t		pending_flip_queue;
	atomic_t			pending_flip;
	struct exynos_drm_crtc_ops	*ops;
	void				*ctx;
};

struct exynos_drm_g2d_private {
+97 −99

File changed.

Preview size limit exceeded, changes collapsed.

+70 −68
Original line number Diff line number Diff line
@@ -12,20 +12,13 @@
#include <drm/drmP.h>

#include <drm/exynos_drm.h>
#include <drm/drm_plane_helper.h>
#include "exynos_drm_drv.h"
#include "exynos_drm_crtc.h"
#include "exynos_drm_fb.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_plane.h"

#define to_exynos_plane(x)	container_of(x, struct exynos_plane, base)

struct exynos_plane {
	struct drm_plane		base;
	struct exynos_drm_overlay	overlay;
	bool				enabled;
};

static const uint32_t formats[] = {
	DRM_FORMAT_XRGB8888,
	DRM_FORMAT_ARGB8888,
@@ -69,16 +62,9 @@ static int exynos_plane_get_size(int start, unsigned length, unsigned last)
	return size;
}

int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
			  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
			  unsigned int crtc_w, unsigned int crtc_h,
			  uint32_t src_x, uint32_t src_y,
			  uint32_t src_w, uint32_t src_h)
int exynos_check_plane(struct drm_plane *plane, struct drm_framebuffer *fb)
{
	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
	unsigned int actual_w;
	unsigned int actual_h;
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
	int nr;
	int i;

@@ -91,12 +77,26 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
			return -EFAULT;
		}

		overlay->dma_addr[i] = buffer->dma_addr;
		exynos_plane->dma_addr[i] = buffer->dma_addr;

		DRM_DEBUG_KMS("buffer: %d, dma_addr = 0x%lx\n",
				i, (unsigned long)overlay->dma_addr[i]);
				i, (unsigned long)exynos_plane->dma_addr[i]);
	}

	return 0;
}

void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
			  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
			  unsigned int crtc_w, unsigned int crtc_h,
			  uint32_t src_x, uint32_t src_y,
			  uint32_t src_w, uint32_t src_h)
{
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	unsigned int actual_w;
	unsigned int actual_h;

	actual_w = exynos_plane_get_size(crtc_x, crtc_w, crtc->mode.hdisplay);
	actual_h = exynos_plane_get_size(crtc_y, crtc_h, crtc->mode.vdisplay);

@@ -113,84 +113,86 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
	}

	/* set drm framebuffer data. */
	overlay->fb_x = src_x;
	overlay->fb_y = src_y;
	overlay->fb_width = fb->width;
	overlay->fb_height = fb->height;
	overlay->src_width = src_w;
	overlay->src_height = src_h;
	overlay->bpp = fb->bits_per_pixel;
	overlay->pitch = fb->pitches[0];
	overlay->pixel_format = fb->pixel_format;

	/* set overlay range to be displayed. */
	overlay->crtc_x = crtc_x;
	overlay->crtc_y = crtc_y;
	overlay->crtc_width = actual_w;
	overlay->crtc_height = actual_h;
	exynos_plane->fb_x = src_x;
	exynos_plane->fb_y = src_y;
	exynos_plane->fb_width = fb->width;
	exynos_plane->fb_height = fb->height;
	exynos_plane->src_width = src_w;
	exynos_plane->src_height = src_h;
	exynos_plane->bpp = fb->bits_per_pixel;
	exynos_plane->pitch = fb->pitches[0];
	exynos_plane->pixel_format = fb->pixel_format;

	/* set plane range to be displayed. */
	exynos_plane->crtc_x = crtc_x;
	exynos_plane->crtc_y = crtc_y;
	exynos_plane->crtc_width = actual_w;
	exynos_plane->crtc_height = actual_h;

	/* set drm mode data. */
	overlay->mode_width = crtc->mode.hdisplay;
	overlay->mode_height = crtc->mode.vdisplay;
	overlay->refresh = crtc->mode.vrefresh;
	overlay->scan_flag = crtc->mode.flags;
	exynos_plane->mode_width = crtc->mode.hdisplay;
	exynos_plane->mode_height = crtc->mode.vdisplay;
	exynos_plane->refresh = crtc->mode.vrefresh;
	exynos_plane->scan_flag = crtc->mode.flags;

	DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)",
			overlay->crtc_x, overlay->crtc_y,
			overlay->crtc_width, overlay->crtc_height);
	DRM_DEBUG_KMS("plane : offset_x/y(%d,%d), width/height(%d,%d)",
			exynos_plane->crtc_x, exynos_plane->crtc_y,
			exynos_plane->crtc_width, exynos_plane->crtc_height);

	plane->crtc = crtc;

	exynos_drm_crtc_plane_mode_set(crtc, overlay);

	return 0;
}

void exynos_plane_commit(struct drm_plane *plane)
{
	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_overlay *overlay = &exynos_plane->overlay;

	exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos);
	if (exynos_crtc->ops->win_mode_set)
		exynos_crtc->ops->win_mode_set(exynos_crtc, exynos_plane);
}

void exynos_plane_dpms(struct drm_plane *plane, int mode)
{
	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(plane->crtc);

	if (mode == DRM_MODE_DPMS_ON) {
		if (exynos_plane->enabled)
			return;

		exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos);
		if (exynos_crtc->ops->win_enable)
			exynos_crtc->ops->win_enable(exynos_crtc,
						     exynos_plane->zpos);

		exynos_plane->enabled = true;
	} else {
		if (!exynos_plane->enabled)
			return;

		exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos);
		if (exynos_crtc->ops->win_disable)
			exynos_crtc->ops->win_disable(exynos_crtc,
						      exynos_plane->zpos);

		exynos_plane->enabled = false;
	}
}

static int
int
exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
		     struct drm_framebuffer *fb, int crtc_x, int crtc_y,
		     unsigned int crtc_w, unsigned int crtc_h,
		     uint32_t src_x, uint32_t src_y,
		     uint32_t src_w, uint32_t src_h)
{

	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
	int ret;

	ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
			crtc_w, crtc_h, src_x >> 16, src_y >> 16,
			src_w >> 16, src_h >> 16);
	ret = exynos_check_plane(plane, fb);
	if (ret < 0)
		return ret;

	exynos_plane_commit(plane);
	exynos_plane_dpms(plane, DRM_MODE_DPMS_ON);
	exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
			      crtc_w, crtc_h, src_x >> 16, src_y >> 16,
			      src_w >> 16, src_h >> 16);

	if (exynos_crtc->ops->win_commit)
		exynos_crtc->ops->win_commit(exynos_crtc, exynos_plane->zpos);

	return 0;
}
@@ -204,7 +206,7 @@ static int exynos_disable_plane(struct drm_plane *plane)

static void exynos_plane_destroy(struct drm_plane *plane)
{
	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);

	exynos_disable_plane(plane);
	drm_plane_cleanup(plane);
@@ -216,11 +218,11 @@ static int exynos_plane_set_property(struct drm_plane *plane,
				     uint64_t val)
{
	struct drm_device *dev = plane->dev;
	struct exynos_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
	struct exynos_drm_private *dev_priv = dev->dev_private;

	if (property == dev_priv->plane_zpos_property) {
		exynos_plane->overlay.zpos = val;
		exynos_plane->zpos = val;
		return 0;
	}

@@ -257,10 +259,10 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
				    unsigned long possible_crtcs,
				    enum drm_plane_type type)
{
	struct exynos_plane *exynos_plane;
	struct exynos_drm_plane *exynos_plane;
	int err;

	exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
	exynos_plane = kzalloc(sizeof(struct exynos_drm_plane), GFP_KERNEL);
	if (!exynos_plane)
		return ERR_PTR(-ENOMEM);

@@ -274,7 +276,7 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
	}

	if (type == DRM_PLANE_TYPE_PRIMARY)
		exynos_plane->overlay.zpos = DEFAULT_ZPOS;
		exynos_plane->zpos = DEFAULT_ZPOS;
	else
		exynos_plane_attach_zpos_property(&exynos_plane->base);

Loading