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

Commit 18566aca 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

adding runtime PM support to MIC driver, and including some
cleanups - especially using atomic helper functions
instead of specific ones - and fixups.

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos:
  drm/exynos: g2d: prevent integer overflow in
  drm/exynos: fix a timeout loop
  drm/exynos: use atomic helper commit
  drm/exynos: remove unnecessary codes
  drm/exynos: mic: Add runtime PM support
  drm/exynos: Stop using drm_framebuffer_unregister_private
  drm/exynos: mic: Fix parse_dt function
  drm/exynos: mic: Add mode_set callback function
parents 02a84c13 e41456bf
Loading
Loading
Loading
Loading
+8 −20
Original line number Diff line number Diff line
@@ -39,6 +39,14 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)

	if (exynos_crtc->ops->disable)
		exynos_crtc->ops->disable(exynos_crtc);

	if (crtc->state->event && !crtc->state->active) {
		spin_lock_irq(&crtc->dev->event_lock);
		drm_crtc_send_vblank_event(crtc, crtc->state->event);
		spin_unlock_irq(&crtc->dev->event_lock);

		crtc->state->event = NULL;
	}
}

static void
@@ -203,23 +211,3 @@ 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 drm_pending_vblank_event *e;
	unsigned long flags;

	spin_lock_irqsave(&crtc->dev->event_lock, flags);

	e = crtc->state->event;
	if (e && e->base.file_priv == file)
		crtc->state->event = NULL;
	else
		e = NULL;

	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);

	if (e)
		drm_event_cancel_free(crtc->dev, &e->base);
}
+0 −4
Original line number Diff line number Diff line
@@ -40,8 +40,4 @@ 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
+0 −114
Original line number Diff line number Diff line
@@ -38,56 +38,6 @@
#define DRIVER_MAJOR	1
#define DRIVER_MINOR	0

struct exynos_atomic_commit {
	struct work_struct	work;
	struct drm_device	*dev;
	struct drm_atomic_state *state;
	u32			crtcs;
};

static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
{
	struct drm_device *dev = commit->dev;
	struct exynos_drm_private *priv = dev->dev_private;
	struct drm_atomic_state *state = commit->state;

	drm_atomic_helper_commit_modeset_disables(dev, state);

	drm_atomic_helper_commit_modeset_enables(dev, state);

	/*
	 * Exynos can't update planes with CRTCs and encoders disabled,
	 * its updates routines, specially for FIMD, requires the clocks
	 * to be enabled. So it is necessary to handle the modeset operations
	 * *before* the commit_planes() step, this way it will always
	 * have the relevant clocks enabled to perform the update.
	 */

	drm_atomic_helper_commit_planes(dev, state, 0);

	drm_atomic_helper_wait_for_vblanks(dev, state);

	drm_atomic_helper_cleanup_planes(dev, state);

	drm_atomic_state_put(state);

	spin_lock(&priv->lock);
	priv->pending &= ~commit->crtcs;
	spin_unlock(&priv->lock);

	wake_up_all(&priv->wait);

	kfree(commit);
}

static void exynos_drm_atomic_work(struct work_struct *work)
{
	struct exynos_atomic_commit *commit = container_of(work,
				struct exynos_atomic_commit, work);

	exynos_atomic_commit_complete(commit);
}

static struct device *exynos_drm_get_dma_device(void);

static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
@@ -202,65 +152,6 @@ static void exynos_drm_unload(struct drm_device *dev)
	dev->dev_private = NULL;
}

static int commit_is_pending(struct exynos_drm_private *priv, u32 crtcs)
{
	bool pending;

	spin_lock(&priv->lock);
	pending = priv->pending & crtcs;
	spin_unlock(&priv->lock);

	return pending;
}

int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
			 bool nonblock)
{
	struct exynos_drm_private *priv = dev->dev_private;
	struct exynos_atomic_commit *commit;
	struct drm_crtc *crtc;
	struct drm_crtc_state *crtc_state;
	int i, ret;

	commit = kzalloc(sizeof(*commit), GFP_KERNEL);
	if (!commit)
		return -ENOMEM;

	ret = drm_atomic_helper_prepare_planes(dev, state);
	if (ret) {
		kfree(commit);
		return ret;
	}

	/* This is the point of no return */

	INIT_WORK(&commit->work, exynos_drm_atomic_work);
	commit->dev = dev;
	commit->state = state;

	/* Wait until all affected CRTCs have completed previous commits and
	 * mark them as pending.
	 */
	for_each_crtc_in_state(state, crtc, crtc_state, i)
		commit->crtcs |= drm_crtc_mask(crtc);

	wait_event(priv->wait, !commit_is_pending(priv, commit->crtcs));

	spin_lock(&priv->lock);
	priv->pending |= commit->crtcs;
	spin_unlock(&priv->lock);

	drm_atomic_helper_swap_state(state, true);

	drm_atomic_state_get(state);
	if (nonblock)
		schedule_work(&commit->work);
	else
		exynos_atomic_commit_complete(commit);

	return 0;
}

int exynos_atomic_check(struct drm_device *dev,
			struct drm_atomic_state *state)
{
@@ -307,12 +198,7 @@ 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)
+31 −1
Original line number Diff line number Diff line
@@ -187,11 +187,40 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)
	return exynos_fb->dma_addr[index];
}

static void exynos_drm_atomic_commit_tail(struct drm_atomic_state *state)
{
	struct drm_device *dev = state->dev;

	drm_atomic_helper_commit_modeset_disables(dev, state);

	drm_atomic_helper_commit_modeset_enables(dev, state);

	/*
	 * Exynos can't update planes with CRTCs and encoders disabled,
	 * its updates routines, specially for FIMD, requires the clocks
	 * to be enabled. So it is necessary to handle the modeset operations
	 * *before* the commit_planes() step, this way it will always
	 * have the relevant clocks enabled to perform the update.
	 */
	drm_atomic_helper_commit_planes(dev, state,
					DRM_PLANE_COMMIT_ACTIVE_ONLY);

	drm_atomic_helper_commit_hw_done(state);

	drm_atomic_helper_wait_for_vblanks(dev, state);

	drm_atomic_helper_cleanup_planes(dev, state);
}

static struct drm_mode_config_helper_funcs exynos_drm_mode_config_helpers = {
	.atomic_commit_tail = exynos_drm_atomic_commit_tail,
};

static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
	.fb_create = exynos_user_fb_create,
	.output_poll_changed = exynos_drm_output_poll_changed,
	.atomic_check = exynos_atomic_check,
	.atomic_commit = exynos_atomic_commit,
	.atomic_commit = drm_atomic_helper_commit,
};

void exynos_drm_mode_config_init(struct drm_device *dev)
@@ -208,4 +237,5 @@ void exynos_drm_mode_config_init(struct drm_device *dev)
	dev->mode_config.max_height = 4096;

	dev->mode_config.funcs = &exynos_drm_mode_config_funcs;
	dev->mode_config.helper_private = &exynos_drm_mode_config_helpers;
}
+1 −3
Original line number Diff line number Diff line
@@ -270,11 +270,9 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
	/* release drm framebuffer and real buffer */
	if (fb_helper->fb && fb_helper->fb->funcs) {
		fb = fb_helper->fb;
		if (fb) {
			drm_framebuffer_unregister_private(fb);
		if (fb)
			drm_framebuffer_remove(fb);
	}
	}

	drm_fb_helper_unregister_fbi(fb_helper);
	drm_fb_helper_release_fbi(fb_helper);
Loading